PLA算法实现与展示

1.PLA算法
作为机器学习的入门基础算法,主要是要理解其产生由来。感知机模型为了应对线性可分二分类问题而设计的算法,求得一个超平面S使得所有数据能正确分类。
即使得每个数据都 f ( x ) = s i g n ( w ⋅ x + b ) f(x)=sign(w\cdot x+b) f(x)=sign(wx+b)
然而这个数学问题无法优化,因此转化为求错误分类的代价函数的最小值
m i n L ( w ) = ∑ x i = M k − y i ( w ⋅ x i + b ) minL(w) =\sum_{x_i=M}^{k} -y_i(w\cdot x_i+b) minL(w)=xi=Mkyi(wxi+b)
其中有两个注意的点:

  1. (xi,yi)是分类错误的点,也就是说其本质是有错误点驱动的优化函数,对于可线性分类数据总存在一个超平面S使得L(w)为0,对于无法线性可分数据也能找出分类错误最少的超平面
  2. 有高数知识可知,要求的函数最小值即在其梯度方向寻找,损失函数L(w)关于w求导可知其导数为 m i n L ( w ) ′ = ∑ x i = M k − y i x i minL(w)' =\sum_{x_i=M}^{k} -y_i x_i minL(w)=xi=Mkyixi
    即每次w更新应在梯度方向上更新为 w i + 1 = w i + y i ⋅ x i ( 旋 转 ) w_{i+1}=w_i+y_i\cdot x_i(旋转) wi+1=wi+yixi
    b i + 1 = b i + y i ( 平 移 ) b_{i+1}=b_i+y_i(平移) bi+1=bi+yi

2.收敛性
关于收敛性的证明过程如下:
在这里插入图片描述
对上面证明过程进行补充:
在这里插入图片描述
3.算法实现
以numpy生成两类正态数据,再对其标记,最后使用PLA算法进行分类,并用matplotlib显示分类效果

from matplotlib import pyplot as plt
import numpy as np

#生成训练数据
def generate_data(u1,o1,u2,o2,n,m):
    #此产生两组正态分布数据(产出为元组数据)
    t1=np.random.normal(u1,o1,size=(n,2))
    t2=np.random.normal(u2,o2,size=(m,2))
    a_x=np.array(t1)
    b_x=np.array(t2)
    #给两组正态数据打标签
    a_y=np.ones(n)
    b_y=np.negative(np.ones(m))
    class1=np.c_[a_x,a_y]
    class2=np.c_[b_x,b_y]
    return class1,class2
#pla算法实现
def pla():
    w=np.zeros(3)#初始化w0
    n=50#正类数据量
    m=50#负类数据量
    c1,c2=generate_data(2,1,-2,1,n,m)
    test=np.vstack((c1,c2))#合并两类数据,将c1类与c2类合并为同一二维矩阵
    x0=np.ones(m+n)
    test=np.c_[x0,test]#插入列向量x0=[1,1,...,1],实现w=[b,w1,w2] * x[1,x1,x2]
    cnt=0
    while True:
        cnt+=1
        if cnt>1000:
            print('非线性可分数据')
            break
        success=True
        for i in range(len(test)):
            x=np.array(test[i][:-1])
            y=np.dot(x,w)
            if np.sign(y)==np.sign(test[i][-1]):
                continue
            w=w+test[i][-1]*x #更新w值
            success = False
            break
        if success==True:
            break
    #绘制分类前效果
    plt.scatter(c1[:, 0], c1[:, 1], c='r', marker='o')  # 正类正态分布
    plt.scatter(c2[:, 0], c2[:, 1], c='b', marker='x')  # 负类正态分布
    plt.show()

    #绘制分类后效果
    x=np.linspace(min(test[:,1])-1,max(test[:,2])+1,50)
    y=-w[1]/w[2]*x-w[0]/w[2]   #见下文数学推导
    plt.plot(x,y,c='g')#超平面
    plt.scatter(c1[:, 0], c1[:, 1], c='r',marker='o')  # 正类正态分布
    plt.scatter(c2[:, 0], c2[:, 1], c='b',marker='x')  # 负类正态分布
    plt.show()
    return cnt,w

if __name__=='__main__':
    cnt,w=pla()
    print("迭代次数:",cnt)
    print("超平面法向量:",w)

其中由法向量推超平面直线推导:
已知超平面为 W ⋅ X = 0 {\rm W\cdot X=0} WX=0,其中 X {\rm X} X为二维向量,即x,y轴
W ⋅ X = W ⋅ ( x , y ) = ( b , w 1 , w 2 ) ⋅ ( 1 , x , y ) = b + w 1 x + w 2 y = 0 {\rm W\cdot X= W\cdot(x,y)=(b,w_1,w_2)\cdot(1,x,y)=b+w_1x+w_2y=0} WX=W(x,y)=(b,w1,w2)(1,x,y)=b+w1x+w2y=0,则直线表达式为: y = − w 1 w 2 x − b w 2 {y=-\frac{w_1}{w_2}x-\frac{b}{w_2}} y=w2w1xw2b
注: b {b} b为代码中的w[0], x {x} x为test的第二列, y {y} y为tes的第三列

4.分类效果展示
其算法分类效果如下:
分类前:
在这里插入图片描述

分类后:
在这里插入图片描述

  • 4
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值