《统计学习方法》学习笔记—感知机模型python实现

这篇博客详细介绍了感知机模型,它是一种用于二类分类的线性模型。内容涵盖了感知机的基本概念,包括其作为线性分类器的角色、目的和学习算法。博主讨论了感知机在训练数据线性可分情况下的工作原理,特别是损失函数和梯度下降的学习策略。文章还提到了感知机的对偶形式,并展示了如何用Python实现这一模型。虽然在代码实现动态图保存时遇到了问题,但博主提供了解决方案。

感知机


  感知机是二类分类的线形模型,输入为实例的特征向量,输出为实例的类别,取值为-1/+1两种值。
  感知机对应于输入空间的特征向量,将其中的实例划分为正负两类的分离超平面,属于判别模型。
  目的:旨在求出将训练数据进行线形划分的分离超平面。

  • 前提条件:数据集是线形可分类的。(例如:XOR规则就是线形不可分的。)

  • 损失函数:基于无分类的距离超平面的距离和函数。

  • 学习算法:基于损失函数的固定梯度,沿着梯度方向,上升最快,反之负方向下降最快。由于损失函数的非负性,修改w和b,使得逼近损失函数的梯度的负方向,从而使损失函数逐渐逼近于0,来达到划分平面的目的。

#机器学习 感知机原始形式学习代码
import numpy as np
from matplotlib import pyplot as plt
from matplotlib import animation 
#Data_set=np.array([[3,3,1],[4,3,1],[1,1,-1]])
Data_set=np.array([[3,3,1],[4,3,1],[1,1,-1],[1,2,1],[5,4,1],[4,1,-1],[6,2,-1],[0,3,1]])
#Data_set[1,0:2]
w=np.array([0,0])
b=0
theta=1
history=[]
def ganzhiji(dataset):

    global w,b,theta,history
    s=dataset.shape[0]
    history.append([w,b])
    for i in range(s):
        if(dataset[i,2]*(np.dot(w,dataset[i,0:2])+b)<=0):
            w=w+theta*dataset[i,2]*dataset[i,0:2]
            b=b+theta*dataset[i,2]
            ganzhiji(dataset)
            return w,b

if __name__=='__main__':
    s=ganzhiji(Data_set)
    print('最终迭代参数为:',s)

    fig=plt.figure()
    ax=plt.axes(xlim=(-6, 6), ylim=(-6, 6))
    line,=ax.plot([],[],'g',lw=2)
    label=ax.text([],[],'')

    #显示测试数据的开始框架
    def show():

        x, y, x_, y_= [],[],[],[]
        for i in range(Data_set.shape[0]):
            if(Data_set[i,2]>0):
                x.append(Data_set[i,0])
                y.append(Data_set[i,1])
            else:
                x_.append(Data_set[i,0])
                y_.append(Data_set[i,1]) 
        #对中文显示进行支持设置中文字体     
        plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']
        plt.plot(x,y,'bo',x_,y_,'rx')
        plt.xlabel('x')
        plt.ylabel('y')
        plt.title('感知机模型')
        return line,label


    #历史参数的动态显示
    def animate(i):
        w=history[i][0]
        b=history[i][1]
        if(w[1]==0):return line,label            
        x1=-6
        y1=-(b+w[0]*x1)/w[1]
        x2=6
        y2=-(b+w[0]*x2)/w[1]
        line.set_data([x1,x2],[y1,y2])
        x0=0
        y0=-(b+w[0]*x0)/w[1]
        str1=[w[0],w[1]],b
        label.set_text(str1)
        label.set_position([x0,y0])
        return line,label
    for i in history:
        print(i)
    #ImageMagick-7.0.1-Q16解码器需要提前装入才能生成动态视频
    plt.rcParams["animation.convert_path"]="C:\ImageMagick-7.0.1-Q16\magick.exe"
    anim=animation.FuncAnimation(fig,animate,init_func=show,frames=len(history),interval=500, repeat=True,blit=True)
    plt.show()
    anim.save('原始型.gif', fps=2, writer='imagemagick')

一下是原始形式的逐步逼近的动态展示图。
这里写图片描述

以上是原始形式的逐步逼近

下面对感知机对偶形式进行模拟

#感知机对偶形式
from matplotlib import pyplot as plt
from matplotlib import animation
import numpy as np

#data_set=np.array([[3,3,1],[4,3,1],[1,1,-1]])
data_set=np.array([[3,3,1],[4,3,1],[1,1,-1],[1,2,1],[5,4,1],[4,1,-1],[6,2,-1],[0,3,1]])

datax=data_set[:,0:2]   #x数据集
datay=data_set[:,2]     #标记-1/+1
lenth=data_set.shape[0] #数据集长度

#构建Gram矩阵
Gram=np.zeros([lenth,lenth])
for i in range(lenth):
    for j in range(lenth):
        Gram[i][j]=np.dot(datax[i],datax[j])
print('输出格拉姆矩阵:\n',Gram)


#建立alpha系数矩阵
alpha=np.zeros([1,data_set.shape[0]])[0]
b=0

#添加列表存储系数
history=[]

def ganzhiji2():
    global alpha,b
    w1,w2=np.dot(alpha*datay,datax)
    history.append([[w1,w2],b])
    for i in range(data_set.shape[0]):
        if((np.dot(alpha*datay,Gram[:,i])+b)*datay[i]<=0):
            alpha[i]=alpha[i]+1
            b=b+datay[i]
            ganzhiji2()
    return alpha,b

if __name__=='__main__':
    s=ganzhiji2()
    print(history)

    fig=plt.figure()
    ax=plt.axes(xlim=(-6, 6), ylim=(-6, 6))
    line,=ax.plot([],[],'g',lw=2)
    label=ax.text([],[],'')

    #显示测试数据的开始框架
    def show():

        x, y, x_, y_= [],[],[],[]
        for i in range(data_set.shape[0]):
            if(data_set[i,2]>0):
                x.append(data_set[i,0])
                y.append(data_set[i,1])
            else:
                x_.append(data_set[i,0])
                y_.append(data_set[i,1])
        #对中文显示进行支持设置中文字体   
        plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']
        plt.plot(x,y,'bo',x_,y_,'rx')
        plt.xlabel('x')
        plt.ylabel('y')
        plt.title('感知机模型')
        return line,label


    #历史参数的动态显示
    def animate(i):
        w=history[i][0]
        b=history[i][1]
        if(w[1]==0):return line,label            
        x1=-6
        y1=-(b+w[0]*x1)/w[1]
        x2=6
        y2=-(b+w[0]*x2)/w[1]
        line.set_data([x1,x2],[y1,y2])
        x0=0
        y0=-(b+w[0]*x0)/w[1]
        str1=[w[0],w[1]],b
        label.set_text(str1)
        label.set_position([x0,y0])
        return line,label
    print('hi')
    for i in history:
        print(i)
    #ImageMagick-7.0.1-Q16解码器需要提前装入才能生成动态视频
    plt.rcParams["animation.convert_path"]="C:\ImageMagick-7.0.1-Q16\magick.exe"
    anim=animation.FuncAnimation(fig,animate,init_func=show,frames=len(history),interval=500, repeat=True,blit=True)
    plt.show()
    anim.save('对偶型.gif', fps=2, writer='imagemagick')

同样能达到预测的效果。
这里写图片描述

代码中对于动态图的保存,需要安装imagemagick软件,并且
plt.rcParams["animation.convert_path"]="C:\ImageMagick-7.0.1-Q16\magick.exe"代码即使写了也会报错,查阅资料发现matplotlib的初始化__init__.py文件对于地址会进行修改出现bug,建议将
rcParams["animation.convert_path"]="C:\ImageMagick-7.0.1-Q16\magick.exe"这段代码添加在__init__.py的1132行即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值