#感知机介绍
神经网络作为深度学习中的重要领域,在众多领域有着广泛的应用。
神经网络又称多层感知机,其基础结构神经元又称感知机,理解单个感知机的工作方式,有助于理解更深层次的神经网络。
话不多说,开始吧!
这里采用二分类问题来简单叙述感知机
对于平面上的点集(x,y),将其分为两类,分别为{0,1},且这两类在平面上可用一组直线集合分开,如图
图中的红色的点代表标签为1, 蓝色的点代表标签为0,介于红色区域和蓝色区域的边界线就是感知机,它将红色和蓝色的区域分开,当要在图中再增加一个点时,如果这个点位于边界线上方则标记为1,否则标记为0。
感知机的学习策略
感知机作为一种线性分类器,可以理解为一个函数,这个函数的函数值为两类或者多类,对于任意样本空间上的点,都可以通过该函数对其进行分类。
对与上面提到的平面上的二分类问题,红色记为1,蓝色记为0。
设感知机为 F(X)=W*X+b;其中X为平面上的点的坐标是一个形如(x1,x2)的二维向量,W是权重,也是一个二维向量(w1,w2),b是偏置,W*X表示W和X的内积。通过F(X)可以对平面点集进行分类。
现在的问题是怎样确定感知机的W和b,才能使能够正确的对平面上的点进行分内呢?,这里采用误差逆传播的策略,不断更新W和b;
这里,首先要定义损失函数,这里采用平方损失,假设我们已经有了一系列的样本点 (X1,Y1),(X2,Y2),(Xn,Yn)…
先将W 初始化为(1,1),b初始化为 1,令yi=F(Xi), 此时若yi !=Yi,则说明感知机对于这一个点无法正确分类, 将误差定义为
loss=(Yi - yi)2(平方损失),在损失函数的基础上更新W 和b,直到损失函数对于任意样本点 (Xi, Yi)都为0;
因为loss是由于W和b的取值不合理以及Xi的值造成的,所以loss与W,bXi 都有关系,这里采用梯度来度量这种影响, 分别求出loss相对于W的梯度,相对于b的梯度,以及相对于Xi的梯度(这里梯度可以理解为偏导数)
图中给出了w1,w2,b的更新公式,就是向梯度的反方向更新。我们希望的是loss的值尽可能的小,这里采用二次函数简单的说明一下为什么要向梯度反方向更新
向着梯度的负方向更新,会到达局部最小值,若整个空间只有一个局部最优值,那么这个值也是全局最优值。除了按照梯度更新外,还有根据二阶偏微分更新的牛顿法和拟牛顿法。
这里按照梯度负方向更新参数,在平面点集本身可分的情况下,一定可以更新到满足条件的W和b,使得F(X)=W*X+b对于每一个点有分类正确。也就是此算法收敛,具体的收敛证明过程可以参照统计学习方法感知机章。
一般的感知机的应该还要使用激活函数,但针对线性可分问题,不使用激活函数也能正确分类。
用python实现一个感知机
感知机测试(利用感知机解决线性可分类问题)
#d导入函数库numpy和数据集iris
import numpy as np
from sklearn.model_selection import train_test_split
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif']=['SimHei'] #用来正常显示中文标签
plt.rcParams['axes.unicode_minus']=False #用来正常显示负号
#使用植物数据库
from sklearn.datasets import load_iris
SEED=2019
#导入数据进行分组
#iris 数据库前两类线性可分(Iris-Setosa 和 Versicolour)
iris=load_iris()
idxs=np.where(iris.target<2)#筛选前两类向量
X = iris.data[idxs]#输入向量
Y = iris.target[idxs]#标签
#绘制四个变量中两个变量的数据展示
plt.scatter(X[Y==0][:,0],X[Y==0][:,2],color='green',label='Iris-Setosa')
plt.scatter(X[Y==1][:,0],X[Y==1][:,2],color='red',label='Iris-Versicolour')
plt.title('Iris Plant database')
plt.xlabel('sepal length in cm')
plt.ylabel('sepal width in cm')
plt.legend(["red","green"])
plt.show()
#将数据集分为训练集和测试集
X_train,X_val,y_train,y_val=train_test_split(X,Y,test_size=0.2,random_state=SEED)
#初始化感知器的权重和偏置
weight=np.random.normal(size=X_train.shape[1])#weight为能够和X_train相乘的矩阵
bias=1
#定义超参数
learning_rate=0.1#学习率
n_epochs=15#迭代次数
del_w=np.zeros(weight.shape)
hist_loss=[]
hist_accuracy=[]
#**利用循环来训练感知器**
for i in range(n_epochs):
#使用阶跃函数作为输出的激活函数
output=np.where(X_train.dot(weight)+bias>0.5,1,0)
#计算均方误差
MSE=np.mean((y_train-output)**2)
#更新权重weight与偏置bias,计算公式由损失函数对权重和偏置求偏导数得到
weight-=learning_rate*np.dot((output-y_train),X_train)
bias+=learning_rate*np.sum(np.dot((output-y_train),X_train))
#计算MSE
loss=np.mean((output-y_train)**2)#损失函数采用均方损失
hist_loss.append(loss)#保存每一次的损失值
#验证预测精度
output_val=np.where(X_val.dot(weight)>0.5,1,0)#测试
accuracy=np.mean(np.where(y_val==output_val,1,0))#计算准确率
hist_accuracy.append(accuracy)
#画出损失值和准确率的变化
fig=plt.figure(figsize=(8,4))
a=fig.add_subplot(1,2,1)
imgplot=plt.plot(hist_loss)
plt.xlabel('epochs')
a.set_title('Training loss')
a=fig.add_subplot(1,2,2)
imgplot=plt.plot(hist_accuracy)
plt.xlabel('epochs')
a.set_title('Validation Accuracy')
plt.show()
欢迎各位大佬评论留言,指指点点,不啬赐教。