感知机(Perceptron)的python实现

来源:互联网 发布:js contains方法 编辑:程序博客网 时间:2024/05/27 21:48

数据是随机生成的,以x=10为分界点,第一行为x1,第二行为x2,第三行为y1,第四行为y2,如下:

5.39, 7.88, 3.37, 2.20, 3.25, 1.42, 5.44, 2.30, 5.63, 1.27, 9.50, 2.67, 9.76, 8.75, 2.18, 2.78, 1.73, 9.94, 8.51, 0.6717.46, 12.89, 17.07, 12.09, 15.51, 14.64, 14.44, 11.19, 17.74, 13.31, 14.79, 10.95, 14.28, 14.32, 19.01, 11.69, 18.94, 17.52, 10.30, 17.048.20, 9.85, 5.84, 1.59, 2.94, 9.02, 6.72, 4.05, 9.02, 0.51, 6.03, 7.16, 4.51, 5.23, 3.63, 8.34, 9.82, 9.41, 1.06, 8.216.35, 3.25, 5.95, 3.65, 5.61, 1.21, 0.13, 1.96, 6.71, 1.76, 7.05, 3.18, 7.54, 4.62, 8.12, 0.04, 9.57, 7.33, 0.64, 7.72

python代码如下所示:

import matplotlib.pyplot as pltimport randomx1,x2,y1,y2 = [],[],[],[]def find_mistake(w,x):for i in range(len(x)):if x[i][2]*(w[0]*x[i][0]+w[1]*x[i][1]+w[2])<=0:return ireturn if = open("data")x1 = [float(i) for i in f.readline().split(",")]x2 = [float(i) for i in f.readline().split(",")]y1 = [float(i) for i in f.readline().split(",")]y2 = [float(i) for i in f.readline().split(",")]data = []for i in range(len(x1)):data.append([x1[i],y1[i],-1])data.append([x2[i],y2[i],1])#draw nodeplt.plot(x1, y1,'bx',x2, y2, 'ro')#draw standard lineplt.plot([10,10],[0,10])w = [0,0,0]t = find_mistake(w,data)while t<len(data)-1:w = [w[0]+data[t][2]*data[t][0],w[1]+data[t][2]*data[t][1],w[2]+data[t][2]]t = find_mistake(w,data)print(w)print(data)point1 = [5.39,(-w[2]-w[1]*10)/w[0]]point2  = [(-w[0]*5.39-w[2])/w[1],10]plt.plot(point1,point2,"r")print(point1,point2)plt.show()

学得结果w

[44.02000000000066, -35.07000000000261, -363]

截图如下,蓝色为目标函数,红色为学得函数,效果还不错。



需要注意的是,感知机只能应用于线性可分的数据集,然而事实情况是我们并不知道数据集是否线性可分,所以不能保证感知机是否一定会停下来。而如果我们确定数据集是线性可分的,那么我们就可以通过解线性方程的方法直接求i得各个参数而得到分割超平面,所以这一点很矛盾。事实上在PLA算法的实际应用中,我们是设想数据集是线性不可分的,采用pocket算法来逼近PLA算法。pocket的做法是,设定一个最大迭代次数,每一次迭代的时候选择一个被误分类的数据点,更新w向量,计算更新后的w在数据集上的错误率和更新前w的在数据集上的错误率,比较这两个错误率,选择错误率小的那个w作为新的w进行下一次迭代。直到达到最大迭代次数退出。这样做的好处是保证算法一定能正常退出,坏处是算法的运行时间被延长了,因为每一次更新都必须去在整个数据集上计算错误率。



原创粉丝点击