MP模型:1943年提出,是一种基于阈值逻辑运算法创造的神经网络计算模型。由固定的结构和权重组成。是一种简单的数学模型,模拟生物神经元的激活方式。成功证明神经元能够执行逻辑功能,开创了人工神经网络研究的时代。
感知机模型:1957年提出,结构和MP模型相似,一般被视为最简单的人工神经网络,也被作为二元线性分类器广泛使用。一般是指单层的人工神经网络
感知机的学习过程:就是将实际值和理论输出值做差,由此来调整每一个输出端的权重,学习规则是用来计算新的权重向量W和新的偏差值B的算法。
下面使用python简单的实现一个感知机的训练过程
import matplotlib.pyplot as plt
import math as math
import numpy as np
#迭代次数
n=0
#学习率
lr=0.10
#输入数据
#定义一个5行4列的数组对象 ndarray
#外界输入是4个值,前两个值是偏置,后面两个坐标某个点的坐标
X=np.array([[1,1,2,3],[1,1,4,5],[1,1,1,1],[1,1,5,3],[1,1,0,1]])
print(X[:,1])
#输出标签
Y=np.array([1,1,-1,1,-1])
#初始化权重的值,4个随机值,取值范围【-1,1】
W=(np.random.random(X.shape[1])-0.5)*2
print(W)
#更新权重函数
def get_update():
global X,Y,W,lr,n
n+=1
#输出X与W的转置相乘,得到的结果由阶跃函数处理
new_output=np.sign(np.dot(X,W.T))
#调整权重:新的权重=旧的权重+改变权重
#改变权重=标签的差值乘以输入X,再乘以学习率
new_W=W+lr*((Y-new_output.T).dot(X)/int(X.shape[0]))
W=new_W
def get_show():
all_x=X[:,2]
all_y= X[:, 3]
negative_x=[1,0]
negative_y=[1,1]
#计算分界线斜率和截距
k=-W[2]/W[3]
b=-(W[0]+W[1])/W[3]
x_data=np.linspace(0,5)
plt.figure()
plt.plot(x_data,x_data*k+b,'r')
plt.plot(all_x, all_y, 'b*')
plt.plot(negative_x, negative_y, 'yo')
plt.xlabel('x')
plt.xlabel('y')
plt.show()
def main():
for _ in range(100):
get_update()
new_outout=np.sign(np.dot(X,W.T))
if(new_outout==Y.T).all():
print('迭代次数:',n)
break
plt.pause(0.1)
get_show()
if __name__ == '__main__':
main()
结果如图所示
感知机本质是一种线性模型,只能处理线性分类问题,简单的异或问题都没有办法正常解决。
多层感知机(MLP)
由单层感知机推广而来,主要特点是有多个神经元层,一般将第一层叫做输入层,最后一层叫输出层,中间的叫做隐藏层。多层感知机没有规定隐藏层的数量,也对隐藏层和输入层神经元的个数没有限制。下面两张图为单层隐藏层前馈网络,多隐藏层前馈网络
多层感知机的关键问题:训练各层间的连接权值。比较常用的是使用反向传播BP算法对神经网络的连接权值进行训练。 误差逆传播(error BackPropagation,简称BP)算法。
BP算法
有一篇博文,将BP算法使用数据推算的方法展示,讲的非常好。可以参考一下;BP算法详解 - CharlesQAQ - 博客园
权重是位于连线上的值,神经元就是每一个小圈,是经过全连接计算后得到的值。偏置是一个常数。引用上面微博中的推算方法,进行bp算法的推算
目标:通过i1,i2输入和权值和偏置的加权计算,使得o1,o2的输出值,接近真正的输出值,0.1和0.99.这也是学习权值和偏置偏置值的意义。这样通过输入值和权值和偏置的加权计算就可以得到类别。下面开始推导:
step1:前向传播
输入层—->隐含层:
计算神经元h1和h2的输入加权和:
neth1=i1*w1+i2*w2+b1*1=0.05*0.15+0.1*0.2+0.35*1=0.3775
neth2=i1*w3+i2*w4+b1*1=0.05*0.25+0.1*0.3+0.35*1=0.5968
由于神经元处的输出是有激活函数的。所以需要使用激活函数计算神经元h1和h2的输入加权和作为第二层隐藏层的真正的输出。
隐含层—->输出层
这样前向传播的过程就结束了,我们得到输出值为[0.75136079 , 0.772928465],与实际值[0.01 , 0.99]相差还很远,现在我们对误差进行反向传播,更新权值,重新计算输出。
step2:反向传播
1.计算总误差
总误差:(square error)
2.隐含层—->输出层的权值更新:
以权重参数w5为例,如果我们想知道w5对整体误差产生了多少影响,可以用整体误差对w5求偏导求出:(链式法则)
下面的图可以更直观的看清楚误差是怎样反向传播的:
现在我们来分别计算每个式子的值:
这样我们就计算出整体误差E(total)对w5的偏导值。
将上面的每一步求导后的公式组合,不带入数值,能得到以下的表达式:
3.隐含层—->隐含层的权值更新:
方法其实与上面说的差不多,但是有个地方需要变一下,在上文计算总误差对w5的偏导时,是从out(o1)—->net(o1)—->w5,但是在隐含层之间的权值更新时,是out(h1)—->net(h1)—->w1,而out(h1)会接受E(o1)和E(o2)两个地方传来的误差,所以这个地方两个都要计算。
首先计算两个误差带来的误差
这样误差反向传播法就完成了,最后我们再把更新的权值重新计算,不停地迭代,在这个例子中第一次迭代之后,总误差E(total)由0.298371109下降至0.291027924。迭代10000次后,总误差为0.000035085,输出为[0.015912196,0.984065734](原输入为[0.01,0.99]),证明效果还是不错的。
总结:反向传播的过程就是第L层神经元的误差值,等于第L+1层所有与神经元j相连的神经元的误差值的权重之和乘以该神经元j的激活函数的梯度。
这样的方法能够使分类变成非线性,也可以解决异或的问题。使用该方法,再次实现感知机的代码段。
import matplotlib.pyplot as plt
import math as math
import numpy as np
#迭代次数
n=0
#学习率
lr=0.11
#输入数据
#定义一个5行4列的数组对象 ndarray
#外界输入是6个值,前一个值是偏置,后面x1,x2,x1^2,x1*x2,x2^2
X=np.array([[1,0,0,0,0,0],[1,0,1,0,0,1],[1,1,0,1,0,0],[1,1,1,1,1,1]])
print(X[:,1])
#输出标签
Y=np.array([-1,1,1,-1])
#初始化权重的值,4个随机值,取值范围【-1,1】
W=(np.random.random(X.shape[1])-0.5)*2
print('初始化权重的值:',W)
#更新权重函数
def get_update():
global X,Y,W,lr,n
n+=1
#输出X与W的转置相乘,得到的结果由阶跃函数处理
new_output=np.sign(np.dot(X,W.T))
#调整权重:新的权重=旧的权重+改变权重
#改变权重=标签的差值乘以输入X,再乘以学习率
new_W=W+lr*((Y-new_output.T).dot(X)/int(X.shape[0]))
W=new_W
def get_line(x,root):
a=W[5]
b=W[2]+x*W[4]
c = W[0] + x * W[1]+ x *x* W[3]
if root==1:
return(-b+np.sqrt(b*b-4*a*c))/(2*a)
if root==2:
return(-b-np.sqrt(b*b-4*a*c))/(2*a)
def get_show():
#正样本
x1=[0,1]
y1=[1,0]
# 负样本
x2 = [0, 1]
y2 = [0, 1]
#计算分界线斜率和截距
x_data=np.linspace(-1,2)
plt.figure()
plt.plot(x_data,get_line(x_data,1),'r')
plt.plot(x_data, get_line(x_data, 2), 'r')
plt.plot(x1, y1, 'bo')
plt.plot(x2, y2, 'yo')
plt.xlabel('x')
plt.xlabel('y')
plt.show()
def main():
for _ in range(10000):
get_update()
get_show()
last_outout=np.dot(X,W.T)
print('最后逼近值:',last_outout)
if __name__ == '__main__':
main()
BP算法改进
BP算法易形成局部极小而得不到全局最优,训练次数多使得学习效率低,存在收敛速度慢等问题。
传统的BP算法改进主要有两类:
启发式算法:如附加动量法,自适应算法。
数值优化算法:如共轭梯度法、牛顿迭代法等。
1,附加动量项
这是一种广泛用于加速梯度下降法收敛的优化方法。附加动量法面临学习率的选取的困难,进而产生收敛速度与收敛性之间的矛盾。
核心思想:在梯度下降搜索时,若当前梯度下降与之前梯度下降方向相同,则加速搜索,反之则减速搜索。
标准BP算法的参数更新项为:
∆ω(t)= ηg(t)
式中,∆ω(t)为第t次迭代的参数调整量,η为学习率,g(t)为第t次迭代所计算出的梯度。
添加动量项之后,基于梯度下降的参数更新为:
∆ωt= ηgt+α∆ωt-1
式中α被称为动量系数,一般α∈(0,1),α∆ω(t-1)代表之前梯度下降的方向和大小信息对当前梯度下降的调整作用。
2,自适应学习率
核心思想:自适应改变学习率,使其根据环境变化增大或减小。
ηt=σ(t)η(t-1)
上式中,σ(t)为第 t 次迭代时的自适应学习速率因子。
3,引入陡度因子
核心思想:如果在调整进入平坦区后,设法压缩神经元的净输入,使其输出退出激活函数的不饱和区,就可以改变误差函数的形状,从而使调整脱离平坦区。
在原激活函数中引入一个陡度因子λ