感知机是线性分类模型,其输入是一个实例特征向量,输出是该实例的类别,取+1和-1。而感知机是输入空间(特征空间)中将实例划分为正负两类的分离超平面,属于判别模型。感知机学习的目标就是求出将训练数据进行线性划分的分离超平面,导入基于误分类的损失函数,利用梯度下降法对损失函数极小化,求得感知机模型。有一点,要注意:使用感知机的前提是训练数据线性可分。
1 感知机的模型
感知机模型
假设训练数据集(T=left { left ( x_{1},y_{1}
ight ),left ( x_{2},y_{2}
ight ),cdots ,left ( x_{m},y_{m}
ight )
ight }),其中,每个样本有(n)个特征,输出二元类别(left { +1,-1
ight }),感知机的目的是在特征空间中找到一个超平面(S):( heta _{0}+ heta _{1}x_{1}+cdots+ heta _{n}x_{n}=0),将特征空间划分成两个部分,位于两部分的点分别被分为正类和负类。由于使用感知机的前提是数据线性可分,因此超平面(S)不是唯一的,感知机模型有多个解。令(x_{0}=1),超平面(S)表达式为:
其向量表示为:( heta ^{T}cdot x=0),其中( heta)和(x)均为((n+1) imes 1)的列向量。
感知机模型的表达式:(y=sign( heta ^{T}cdot x)),
其中,
感知机损失函数
输入空间中任一点(x_{0})到超平面(S)的距离表达式为:$$frac{| heta ^{T}cdot x^{(i)}|}{|| heta ||{2}}$$
对于误分类的数据(left ( x_{i},y_{i}
ight )),$$-y{i}( heta ^{T}cdot x)> 0$$
因为当( heta ^{T}cdot x> 0)时,(y_{i}=-1),而当( heta ^{T}cdot x< 0)时,(y_{i}=+1)。所以,误分类点(x_{i})到超平面(S)的距离表达式为:$$-frac{y_{i}( heta ^{T}cdot x^{(i)})}{|| heta ||{2}}$$
假设超平面(S)的误分类点集合为(M),所有误分类点到超平面(S)的总距离表达式为: $$-frac{1}{|| heta||{2}}sum_{x_{i}epsilon M}y_{i}( heta ^{T}cdot x^{(i)})$$
不考虑(frac{1}{|| heta||_{2}}),则得到感知机损失函数表达式为:$$J( heta )=-sum_{x_{i}epsilon M}y_{i}( heta ^{T}cdot x^{(i)})$$
由损失函数看出,损失函数是非负的,没有误分类点时,损失函数值为0,当误分类点越少,误分类点离超平面越近,损失函数值就越小。
2 感知机算法
感知机算法
输入: 线性可分数据集(T=left { (x_{1},y_{1}),(x_{2},y_{2}),cdots ,(x_{m},y_{m}) ight }),每个样本是(n)维特征,(y_{i}epsilon left { -1,+1 ight }),学习率(alpha)((0< alpha leq 1));
输出: 感知机模型参数 $ heta $向量;
step1 初始化$ heta (和)alpha$
step2 数据集中选择一个误分类点((x_{i},y_{i})),这里(x_{i})是(n)维向量,如果该点满足(y_{i}( heta ^{T}cdot x_{i})leq 0)
step3 对感知机模型参数 $ heta $向量进行一次随机梯度下降迭代: ( heta := heta +alpha y_{i}x_{i})
step4 直到数据集中不存在误分类点,否则跳转至步骤2
3 感知机代码实现
from sklearn.datasets import make_classification
x,y = make_classification(n_samples=1000, n_features=2, n_redundant=0, n_informative=1, n_clusters_per_class=1)
#训练数据和测试数据
x_data_train = x[:800,:]
x_data_test = x[800:,:]
y_data_train = y[:800]
y_data_test = y[800:]
#正例和反例
positive_x1 = [x[i,0] for i in range(1000) if y[i] == 1]
positive_x2 = [x[i,1] for i in range(1000) if y[i] == 1]
negetive_x1 = [x[i,0] for i in range(1000) if y[i] == 0]
negetive_x2 = [x[i,1] for i in range(1000) if y[i] == 0]
#定义一个感知机
from sklearn.linear_model import Perceptron
clf = Perceptron(fit_intercept=False, n_iter=30, shuffle=False)
clf.fit(x_data_train, y_data_train)
print(clf.coef_)
#输出
[[-0.33706658 3.30497893]]
print(clf.intercept_)
#输出
[ 0.]
acc = clf.score(x_data_test,y_data_test)
print(acc) #0.985
#可视化感知机结果
import numpy as np
from matplotlib import pyplot as plt
#画出正例和反例的散点图
plt.scatter(positive_x1,positive_x2,c='red')
plt.scatter(negetive_x1,negetive_x2,c='blue')
#画出超平面(在本例中即是一条直线)
line_x = np.arange(-4,4)
line_y = line_x * (-clf.coef_[0][0] / clf.coef_[0][1]) - clf.intercept_
plt.plot(line_x,line_y)
plt.show()