感知机PLA算法的python实现
import numpy as np
import matplotlib.pyplot as plt
def create_train():
data=np.array([[3,-3],[4,-1.5],[2,-2],[3.5,-1],[5,0],[1,1],[1,2],[0,1],[2,2],[4,3]],dtype=float)
label=np.array([1,1,1,1,1,-1,-1,-1,-1,-1])
return data,label
def pla(data,label):
data_num,feature_num=data.shape
w=np.zeros(feature_num+1)
a=np.ones([data_num,1])
data=np.concatenate((a,data),1)#为训练数据增加常数项
terminated=False#训练结束的标志,所有的训练数据都分类正确
while (terminated==False):
false_num=0
for i in range(data_num):
if(terminated==False):
y=np.sign([email protected][i])
if(y!=label[i]):
w+=label[i]*data[i]
false_num+=1
plot_dots(data,label,w)#每更新一次权重就重新绘制分类线
if(false_num==0):
terminated=True
return w
def plot_dots(data,label,w):
data_num,feature_num=data.shape
xcord1=[]
ycord1=[]
xcord2=[]
ycord2=[]
for i in range(data_num):
if (label[i]==1):
xcord1.append(data[i,1])
ycord1.append(data[i,2])
else:
xcord2.append(data[i,1])
ycord2.append(data[i,2])
plt.figure()
plt.scatter(xcord1,ycord1,s=40,c='red',marker='s')
plt.scatter(xcord2,ycord2,s=40,c='blue')
plt.xlabel('x1')
plt.ylabel('x2')
#绘制分类线
x = np.arange(-3.0, 8.0, 0.1)
y = (-w[0]-w[1] * x)/w[2]
plt.plot(x,y)
plt.pause(10)
def plot_lines(w):
x = range(-3.0, 8.0, 0.1)
y = (-w[0]-w[1] * x)/w[2]
plt.plot(x,y)
def main():
data,label=create_train()
#plot_dots(data,label)
w=pla(data,label)
return w
if __name__=='__main__':
main()
训练之后的分类线如下图所示:可以发现PLA的一个缺陷,分类线距离蓝色点太近了,在测试环节出错的可能性较大。
对PLA的总结:
1、同一组数据,当权重初始化不同,或者训练数据的顺序不同时,最终的分类线可能会有点差别。也就是同一组数据可能会有无数种分类超平面。而SVM的出发点就是分类超平面间隔最大化,也就是找到最优的那个分类超平面。
2、PLA算法收敛的前提是数据是线性可分的。而在实际中的数据往往会携带一定的噪声,用PLA可能无法得到一个较好的结果。
3、每次更新权重都仅仅依据一个错误点,比较片面,更新后可能会得到一个更差的分类结果。