感知机
1.1.2 感知机
感知机(Perceptron)是Frank Rosenblatt在1957年提出的概念,其结构与MP模型类似,一般被视为最简单的人工神经网络,也作为二元线性分类器被广泛使用。
通常情况下感知机指单层人工神经网络,以区别于多层感知机(Multilayer Perceptron)。尽管感知机结构简单,但能够学习并解决较复杂的问题,其结构如图1.1所示。
假设我们有一个n维输入的单层感知机,x1至xn为n维输入向量的各个分量,w1至wn为各个输入分量连接到感知机的权量(或称权值),θ为阈值,f为激活函数(又称为激励函数或传递函数),y为标量输出。理想的激活函数f (·)通常为阶跃函数或者sigmoid函数。感知机的输出是输入向量X与权重向量W求得内积后,经激活函数f所得到的标量:
图1.1 感知机模型
权重W的初始值一般随机设置,往往达不到较好的拟合结果,那么如何更改权重数值使标量输出y逼近实际值呢?这时就需要简单介绍下感知器的学习过程。首先通过计算得到输出值,然后将实际输出值和理论输出值做差,由此来调整每一个输出端上的权值。学习规则是用来计算新的权值矩阵W及新的偏差B的算法。
举个实际例子来说明。中国通用长度计量单位为厘米(cm),美国通用长度单位为英寸(in),两者之间有一个固定的转化公式。假设我们并不知道该公式,在单层感知机(目前考虑为单输入)的输入端输入以英寸为单位的数值,希望输出端输出相应的厘米计量数值。
首先,先设定输入值为10英寸,并随机生成连接权值,现在假设w为1,此时单层感知机的输出为:
厘米=10×1=10
但我们知道正确输出应该为25.4厘米,这时可以计算出输出值与真实值之间的差:
误差值=真实值-输入值
=25.4-10
=14.4
然后用这个误差值对权重w进行调整。例如,将w由1调整至2,可以得到新的结果:厘米=10×2=20,这个结果明显优于上一个,误差值为5.4。
再次重复上述过程,将w调整至3,结果为:厘米=10×3=30,明显超过真实值,误差为-4.6,这个负号不是意味着不足,而是调超了。
此时可以看出,w=2的结果要优于w=3的结果,如果误差达到可接受的范围,就可以停止训练,或者是w在[2,3]之间继续微调。
上述例子是将感知机接受一个输入,并作出对应的输出,也可以称之为预测器。接下来给出一个单层感知机应用于分类问题的Python应用实例。
1.输入数据集与其对应标签
示例代码如下:
#5组输入数据
X = np.array ([[1,1,2,3],
[1,1,4,7],
[1,1,1,3],
[1,1,5,3],
[1,1,0,1]])
# 标签
Y = np.array([1,1,-1,1,-1])
外界输入是4个值,后两个值确定平面上某个点的位置,前两个数值相当于偏置值,与阈值的意义相同,这里输入了5组数值。Y存储每组值对应的正负标签。现在需要做的就是找到一条直线,将正负值区域区分开。
2.权重的初始化
示例代码如下:
# 权重初始化,取值范围为-1~1
W = (np.random.random(X.shape[1])-0.5)*2
随机生成范围在(-1,1)的权重,权重的个数与输入向量维度相同。
3.更新权重函数
示例代码如下:
#更新权值函数
def get_update():
global X,Y,W,lr,n
n += 1
#输出:X与W的转置相乘,得到的结果再由阶跃函数处理
new_output = np.sign(np.dot(X,W.T))
#调整权重: 新权重 = 旧权重 + 改变权重
new_W = W + lr*((Y-new_output.T).dot(X))/int(X.shape[0])
W = new_W
若随机生成的权重W不能合理区分正负值区域,就要根据当前输出标签和原有标签差值的大小进行权重调整,将二者的差乘以输入向量Xi,再与学习率lr相乘得到权重改变值,与原有权重相加后得到新权重。
完整代码如下:
import numpy as np
import matplotlib.pyplot as plt
n = 0 #迭代次数
lr = 0.10 #学习速率
# 输入数据
X = np.array([[1,1,2,3],
[1,1,4,5],
[1,1,1,1],
[1,1,5,3],
[1,1,0,1]])
# 标签
Y = np.array([1,1,-1,1,-1])
# 权重初始化,取值范围为-1~1
W = (np.random.random(X.shape[1])-0.5)*2
def get_show():
# 正样本
all_x = X[:, 2]
all_y = X[:, 3]
# 负样本
all_negative_x = [1, 0]
all_negative_y = [1, 1]
# 计算分界线斜率与截距
k = -W[2] / W[3]
b = -(W[0] +W[1])/ W[3]
# 生成x刻度
xdata = np.linspace(0, 5)
plt.figure()
plt.plot(xdata,xdata*k+b,'r')
plt.plot(all_x, all_y,'bo')
plt.plot(all_negative_x, all_negative_y, 'yo')
plt.show()
#更新权值函数
def get_update():
#定义所有全局变量
global X,Y,W,lr,n
n += 1
#计算符号函数输出
new_output = np.sign(np.dot(X,W.T))
#更新权重
new_W = W + lr*((Y-new_output.T).dot(X))/int(X.shape[0])
W = new_W
def main():
for _ in range(100):
get_update()
new_output = np.sign(np.dot(X, W.T))
if (new_output == Y.T).all():
print("迭代次数:", n)
break
get_show()
if __name__ == "__main__":
main()
最后分割结果如图1.2所示。
单层感知器结构简单,权重更新计算快速,能够实现逻辑计算中的NOT、OR和AND等简单计算,但是对于稍微复杂的NOR异或问题就无法解决,其本质缺陷是不能处理线性不可分问题,而在此基础上提出的多层感知器就能解决此类问题。
- 点赞
- 收藏
- 关注作者
评论(0)