感知机算法收敛性证明及Python代码实现

转载来自:https://blog.csdn.net/deramer1/article/details/87928860
大家一起学习讨论
一、感知机原理
感知机是最简单的线性二分类模型,如果要处理的数据是线性可分的,则该模型能取得很好的效果,如果数据不是线性可分的,则该模型不能取得很好的效果。以二维平面为例,如果要分类的点,能被一条直线分开,直线的一侧是正类,直线的另一侧是负类,则说明数据是线性可分的。如果数据需要一个圆来分开则说明数据不是线性可分的,曾经感知机因为不能处理异或问题,而被人批判,导致神经网络的研究停滞了几十年。
1.1 感知机形式
感知机就是为了确定一条直线WX+b,让直线的一侧为正类,直线的另一侧是负类。当WX+b运算大于0时为+1,WX+b运算小于0时为-1,为此引入了sign函数。
感知机算法收敛性证明及Python代码实现
文章图片

1.2感知机学习过程
感知器的训练过程就是确定W,b,从而确定一个平面分离正类和负类。训练过程中,我们需要注意的是那些被误分类的点,比如,本来是正类,却被感知机分成了负类。下面的式子是判断该点是否被误分类:
感知机算法收敛性证明及Python代码实现
文章图片

如果WX+b>0,y为-1,则整个式子大于0,该点被误分类。如果WX+b>0,y为+1,整个式子小于0,被正确分类。
如果不考虑1/||W||,上面的式子则是感知机的损失函数。如果有N个点,则损失函数为如下:
【感知机算法收敛性证明及Python代码实现】感知机算法收敛性证明及Python代码实现
文章图片

对于给定的训练集T,求解参数W,b的过程就是求解损失函数极小值的过程。
感知机算法收敛性证明及Python代码实现
文章图片

感知器的算法是由误分类确定的,首先选取一个超平面W0,b0,采用随机梯度下降法最小化上面的式子,梯度为:
感知机算法收敛性证明及Python代码实现
文章图片

整个感知器的运算流程如下:
感知机算法收敛性证明及Python代码实现
文章图片

每当有一个点被分类错误的时候,就会更新算法。我们知道w控制的是直线的斜率,b控制的是直线的平移。对w,b进行更新就是控制直线的旋转和平移,而η控制的是旋转和平移的角度。
1.3感知机收敛性证明

上面推导的时候,少加了一个注解,现补充如下:
感知机算法收敛性证明及Python代码实现
文章图片

1.4感知机无法解决异或问题
感知机算法收敛性证明及Python代码实现
文章图片


二、感知机编码实现

  1. import numpy as np
  2. import pandas as pd
  3. import matplotlib.pyplot as plt
  4. from sklearn.datasets import load_iris

我们用的数据集是iris数据集,这个数据集是用来给花做分类的数据集,每个样本包括了花萼长度、花萼宽度、花瓣长度、花瓣宽度四个特征,通过这四个特征来将花分为山鸢尾、变色鸢尾还是维吉尼亚鸢尾。本次我只抽取一部分数据做二分类。
  1. #读取iris数据集,并将数据,标签存入DataFrame中,
  2. iris = load_iris()
  3. raw_data = https://www.it610.com/article/iris.data
  4. data = https://www.it610.com/article/pd.DataFrame(raw_data,columns=iris.feature_names)
  5. data['label'] = iris.target

显示data数据集如下所示:
感知机算法收敛性证明及Python代码实现
文章图片

  1. data_array = np.array(data.iloc[:100,[0,1,-1]])
  2. X,Y = data_array[:,:-1],data_array[:,-1]
  3. Y = np.array([1 if i ==1 else -1 for i in Y]) #将标签为0,1,变为-1,+1

将data中第一列、第二列作为特征存入X中,data最后一列作为标签存入Y中。
  1. plt.scatter(X[:50,0],X[:50,1],label='0')
  2. plt.scatter(X[50:100,0],X[50:100,1],label='1')
  3. plt.xlabel('sepal length')
  4. plt.ylabel('sepal width')
  5. plt.legend()
  6. plt.show()

X中数据显示如下
感知机算法收敛性证明及Python代码实现
文章图片


  1. #定义sign函数
  2. def sign(X,W,b):
  3. return np.dot(W,X) + b
  4. #遍历数据集
  5. def train(X,Y,W,b,learning_rate=0.1):
  6. for i in range(len(X)):
  7. if(Y[i]*sign(X[i],W,b)<=0):
  8. W = W + learning_rate*Y[i]*X[i]
  9. b = b + learning_rate*Y[i]
  10. return W,b
  11. 将数据集遍历1000遍,每100次打印一下W,b值
  12. W = np.zeros([1,2])
  13. b = 0
  14. for i in range(1000):
  15. W,b = train(X,Y,W,b)
  16. if(i%100==0):
  17. print(i,W,b)

  1. x_ = np.linspace(4,7,10)
  2. y_ =-(W[0][0]*x_ + b)/W[0][1]
  3. plt.plot(x_,y_)
  4. plt.scatter(X[:50,0],X[:50,1],label='0')
  5. plt.scatter(X[50:100,0],X[50:100,1],label='1')
  6. plt.xlabel('sepal length')
  7. plt.ylabel('sepal width')
  8. plt.legend()
  9. plt.show()

将超平面画出来,如下
感知机算法收敛性证明及Python代码实现
文章图片




    推荐阅读