本文将讲解感知机的原理以及笔者使用Python语言对其的实现:
什么叫感知机呢?
在李航老师《统计学习方法》中是这么讲的:“感知机(perceptron)是二类分类的线性分类模型,其输入为实例的特征向量,输出为实例的类别,取+1和-1二值。”
从定义我们可以看出,感知机其实就是能够实现一个二分类问题的表达式或函数。关于二分类问题,是指问题只可以被分为两类的问题,比如人类从性别上分可分为男性和女性,就是一个典型的二分类问题,还有只有黑球和白球的分类等等。那这样的问题如何让机器去实现呢?当然还得从数学上去考虑,如果我们把正确的分类标记为+1,错误的分类标为-1的话,只需要找到一个满足条件的函数去实现它就可以了。
符号函数(一般用sign(x)表示)是很有用的一类函数,其表达式为:
以上就是我们感知机的原理部分,接下来,我们将使用Python语言将其实现:
话不多说,直接上python代码:
# -*- encoding:utf-8 -*-
# The entire code is used to implement the perceptron
"""
Created on Tuesday, 24 December 14:58 2019
@author:Jeaten
@email:[email protected]
"""
import numpy as np
import random
def data():
'''
该函数用于产生训练数据
:return: 返回特征和标签
'''
train = [((3, 3), 1), ((4, 3), 1), ((1, 1), -1)]#((x,y),c):(x,y)为数据的坐标,c为所属类别
feature=[]
label=[]
for i in train:
feature.append(i[0])
label.append(i[1])
feature=np.array(feature)
label=np.array(label)
return feature,label
class perceptron:
def __init__(self):
'''
:param w:感知机的权重
:param b:感知机的偏置
:param learning_rate:学习率
'''
self.w = np.array([0,0])
self.b=0
self.learning_rate=1
def update(self,w,x,y,b):
'''
该函数用于参数的更新
:param w: 权重
:param x: 数据的特征
:param y: 数据的标签
:param b: 数据的偏置
:return: 无
'''
self.w=w+self.learning_rate*x*y
self.b=b+self.learning_rate*y
def sign(self,w,x,b):
'''
该部分为符号函数
:return 返回计算后的符号函数的值
'''
return np.sign(np.dot(w,x)+b)
def train(self,feature,label):
'''
该函数用于训练感知机
:param feature: 特征
:param label: 标签(数据点所属类别)
:return: 返回最终训练好模型(参数)
'''
stop=True
while stop:
count=len(feature)
for i in range(len(feature)):
if self.sign(self.w,feature[i],self.b)*label[i]<=0:
print( "分类错误!误分类点为:", feature[i] )
self.update( self.w, feature[i], label[i], self.b )
else:
count -= 1
if count == 0:
stop = False
print( "最终权重 w:", self.w, "最终偏置 b:", self.b )
return self.w,self.b
def train_rand(self,feature,label):
'''
该函数使用随机选择数据点来进行训练(随机梯度下降法)
:param feature: 特征
:param label: 标签(数据点所属类别)
:return: 返回最终训练好模型(参数)
'''
stop=True
while stop:
count=len(feature)
index=[i for i in range(len(feature))]
random.shuffle(index)
for i in index:
if self.sign(self.w,feature[i],self.b)*label[i]<=0:
print( "分类错误!误分类点为:",feature[i])
self.update(self.w,feature[i],label[i],self.b)
else:
count-=1
if count==0:
stop=False
print("最终w:",self.w,"最终b:",self.b)
return self.w,self.b
class show:
def draw_curve(self, data,w,b):
'''
该函数应用于查看拟合效果
:param data: 数据点
:param w: 权重
:param b: 偏置
:return: 无
'''
import matplotlib.pyplot as plt
data,label=data
coordinate_x=[]
for i in data:
coordinate_x.append(i[0])
coordinate_y=[]
for i in range(len(data)):
coordinate_x.append(data[i][0])
coordinate_y.append(data[i][1])
if label[i]==1:
plt.plot(data[i][0], data[i][1],'o'+'r',label='right',ms=10)
else:
plt.plot(data[i][0], data[i][1],'*'+'g',label='error',ms=10 )
d_x=np.arange(0,max(coordinate_x),1)
d_y=[]
for i in d_x:
d_y.append(-(w[0]*i+b)/w[1])#一定的学习率下可能会有除0错误
plt.plot(d_x,d_y,)
plt.show()
return True
if __name__ == '__main__':
feature,label=data()
x=np.array(feature)
y=np.array(label)
neuron=perceptron()
show=show()
w, b = neuron.train( x, y )#按序调整
# w,b=neuron.train_rand(x,y)#使用随机梯度下降法
show.draw_curve( data(), w,b )
首先让我们跑一下看看效果,得到权重为w=[1 1],偏置为b=-3,其结果如下图所示:
可以看出此超平面实现了对点的二分类,当然,我们可以使用随机梯度下降方法来进行分类,得到的一种结果为w=[2 1],b=-5,其结果图如下:
接下来,我们构造一个二分类的数据集来看看分类的效果,构造数据集的时候可将产生数据集的“train=”部分用以下或别的函数代替。笔者使用了随机产生1000个数的方法,产生代码如下:
import random
data = []
for i in range( 1000 ):
x = random.randint( 0, 50 )
y = random.randint( 0, 50 )
if x > y:
data.append( ((x, y), 1) )
elif x < y:
data.append( ((x, y), -1) )
train=data
产生方法如下:
我们使用随机梯度下降的方法进行二分类,得到一组参数为:w=[72 -72],b=-1,分类结果如下图所示:
可以看出分类效果还是很不错的。
以上就是本期的感知机的原理和python的代码实现,欢迎交流批评指正!