感知机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、每次更新权重都仅仅依据一个错误点,比较片面,更新后可能会得到一个更差的分类结果。

感知机PLA算法的python实现