感知机
1 概念
- 感知机就相当于一仅有输入层和输出层的神经网络,每一个连接权都代表该属性的重要性程度,其中w0代表一个阈值。如果每个属性值与其对应权重相乘之和大于该阈值,那么根据sign函数,就可以做出分类。
2 PLA算法(感知机学习算法)
- 直观上:通过迭代的方式,每一次选择一条线,来更新权重向量,如果第t轮的线无法准确的预测结果,那就对权重向量做出改变,也就是对决策边界进行调整。当样本真实类别为1,但感知机将其分类为-1的时候,就用原来的权重向量减去x,使得决策线离x轴更近;当样本真实类别为-1,但感知机将其分类为1的时候,就用原来的权重加上x,使得决策线离x轴更远。不断的进行迭代,最后使得其不再出错。
- 根据上面所论述的规则,看下面的视图
- 首先进入第一次迭代,先随机初始化一条线,然后找到一个错误的点x1,x1∈1类,因此权重向量会加上这个x的值,所以线就会以图片中心为原点向顺时针方向更新
- 由第一轮更新出来的决策边界,又发现了一个分类错误的1类点,因此,下一次更新还是朝顺时针更新。
- 这次更新完成之后找到一个分类错误的-1类点,因此下一次会向逆时针方向更新。
- 依此进行,最后迭代到一条近乎完美的决策边界
- PLA何时停止呢?
假设我们的数据是线性可分的,因此肯定存在一条分界线,可以完美的将属于不同类别的样本进行分割,也就是说我们机器做出的分类与实际的分类是一模一样的,因此根据公式可知,必有下列不等式成立,因为W的转置乘X与y同号。
再进一步,那么必有随机第t轮的值大于等于该最小值大于0.
下面再来看w_f与w_t的关系,由公式得:
又由上面的推导可知,w_f的转置x_n(t)y_n(t)>miny_nw_fx_n
再进一步,可得下面不等式,该不等式可以反映出第t轮的w与w_f的乘积要小于第t+1轮w与w_f的乘积,当两个向量的内积越来越大,说明两个向量在越来越接近,但是这里只考虑了一半,因为有可能是因为长度上的问题。
下面证明另外一半:
- 因为PLA是知错才改,因此根据PLA的机制,每一次增长的最大距离就是加上最大的向量x
- 又因为两个正规化权重向量内积的最大值是1,因此可证明PLA是会停止的。
- 那么当我们的数据存在一些噪音,从而导致没有办法找到完美的线进行分界怎么办呢?
答:这里可以使用Pocket算法,也就是在每一次找到一条新的线的时候都看看是不是比上一条好,如果是就将其保存下来,这样可以找到局部最优解。
2 代码实例:
- 首先查看数据分布:
import pandas as pd
import numpy as np
from matplotlib import pyplot as plt
from scipy.io import loadmat
data = loadmat('E:/Data/Ng/Coursera-ML-AndrewNg-Notes-master/code/ex6-SVM/data/ex6data1.mat')
X =data['X']
y = np.ravel(data['y'])
Data = np.insert(X,2,values=y,axis=1)
Data = pd.DataFrame(Data,columns=['X1','X2','Y'])
cluster1= Data[Data['Y'].isin([1])] #将属于1类的样本全部分离出来
cluster2= Data[Data['Y'].isin([0])] #将属于0类的样本全部分离出来
plt.scatter(cluster1['X1'],cluster1['X2'],color='red',marker='o',label='cluster1')
plt.scatter(cluster2['X1'],cluster2['X2'],color='blue',marker='x',label='cluster2')
plt.legend(loc=1)
plt.show()
结果如下:
- 定义sign函数与代价函数
def sign(x):
"""x>=0,则属于1类;x<0,则属于-1类"""
if x>=0:
return 1
else:
return -1
def cost(theta,X,y):
m = X.shape[0]
Cost=0.0
for i in range(m):
x_i = X[i,:]
h_i = sign(theta @ x_i.T)
y_i = y[i]
if h_i!= int(y_i):
Cost-= (y_i*h_i)
return Cost
- 随机梯度下降
def gradient(theta,X,y,epoch,l):
m = X.shape[0]
index_list = np.arange(m)
for i in range(epoch):
index = int(np.random.choice(index_list,size=1))
x_i = X[index,:]
h_i = sign(x_i@theta.T)
y_i = y[index]
if h_i!=int(y_i):
theta = theta + (l*y_i)*x_i
return theta
if __name__ == '__main__':
Y = np.array([1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,1])
X = np.insert(X,0,values=np.ones(X.shape[0]),axis=1)
theta = np.zeros(X.shape[1])
theta = gradient(theta,X,Y,1000,1)
final_x2 = (theta[0] + theta[1]*X[:,1])/(-theta[2])
plt.scatter(cluster1['X1'],cluster1['X2'],color='red',marker='o',label='cluster1')
plt.scatter(cluster2['X1'],cluster2['X2'],color='blue',marker='x',label='cluster2')
plt.plot(X[:,1],f)
plt.legend(loc=1)
plt.show()
结果如下: