感知机原理及代码实现小结
感知机是线性分类模型,其输入是一个实例特征向量,输出是该实例的类别,取+1和-1。而感知机是输入空间(特征空间)中将实例划分为正负两类的分离超平面,属于判别模型。感知机学习的目标就是求出将训练数据进行线性划分的分离超平面,导入基于误分类的损失函数,利用梯度下降法对损失函数极小化,求得感知机模型。有一点,要注意:使用感知机的前提是训练数据线性可分。
1 感知机的模型
感知机模型
假设训练数据集\(T=\left \{ \left ( x_{1},y_{1} \right ),\left ( x_{2},y_{2} \right ),\cdots ,\left ( x_{m},y_{m} \right )\right \}\),其中,每个样本有\(n\)个特征,输出二元类别\(\left \{ +1,-1 \right \}\),感知机的目的是在特征空间中找到一个超平面\(S\):\(\theta _{0}+\theta _{1}x_{1}+\cdots+\theta _{n}x_{n}=0\),将特征空间划分成两个部分,位于两部分的点分别被分为正类和负类。由于使用感知机的前提是数据线性可分,因此超平面\(S\)不是唯一的,感知机模型有多个解。令\(x_{0}=1\),超平面\(S\)表达式为:
其向量表示为:\(\theta ^{T}\cdot x=0\),其中\(\theta\)和\(x\)均为\((n+1)\times 1\)的列向量。
感知机模型的表达式:\(y=sign(\theta ^{T}\cdot x)\),
其中,
感知机损失函数
输入空间中任一点\(x_{0}\)到超平面\(S\)的距离表达式为:$$\frac{|\theta ^{T}\cdot x^{(i)}|}{||\theta ||{2}}$$
对于误分类的数据\(\left ( x_{i},y_{i} \right )\),$$-y(\theta ^{T}\cdot x)> 0$$
因为当\(\theta ^{T}\cdot x> 0\)时,\(y_{i}=-1\),而当\(\theta ^{T}\cdot x< 0\)时,\(y_{i}=+1\)。所以,误分类点\(x_{i}\)到超平面\(S\)的距离表达式为:$$-\frac{y_{i}(\theta ^{T}\cdot x^{(i)})}{||\theta ||{2}}$$
假设超平面\(S\)的误分类点集合为\(M\),所有误分类点到超平面\(S\)的总距离表达式为: $$-\frac{1}{||\theta||{2}}\sum_{x_{i}\epsilon M}y_{i}(\theta ^{T}\cdot x^{(i)})$$
不考虑\(\frac{1}{||\theta||_{2}}\),则得到感知机损失函数表达式为:$$J(\theta )=-\sum_{x_{i}\epsilon M}y_{i}(\theta ^{T}\cdot x^{(i)})$$
由损失函数看出,损失函数是非负的,没有误分类点时,损失函数值为0,当误分类点越少,误分类点离超平面越近,损失函数值就越小。
2 感知机算法
感知机算法
输入: 线性可分数据集\(T=\left \{ (x_{1},y_{1}),(x_{2},y_{2}),\cdots ,(x_{m},y_{m}) \right \}\),每个样本是\(n\)维特征,\(y_{i}\epsilon \left \{ -1,+1 \right \}\),学习率\(\alpha\)(\(0< \alpha \leq 1\));
输出: 感知机模型参数 $\theta $向量;
step1 初始化$\theta \(和\)\alpha$
step2 数据集中选择一个误分类点\((x_{i},y_{i})\),这里\(x_{i}\)是\(n\)维向量,如果该点满足\(y_{i}(\theta ^{T}\cdot x_{i})\leq 0\)
step3 对感知机模型参数 $\theta $向量进行一次随机梯度下降迭代: \(\theta :=\theta +\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()