首先什么是人工神经网络?简单来说就是将单个感知器作为一个神经网络节点,然后用此类节点组成一个层次网络结构,我们称此网络即为人工神经网络。当网络的层次大于等于3层(输入层+隐藏层(大于等于1)+输出层)时,我们称之为多层人工神经网络。

 

BP(Back Propagation,后向传播)算法是迄今最成功的神经网络学习算法,现实任务中使用神经网络时,大多是在使用BP算法进行训练[2],包括最近炙手可热的深度学习概念下的卷积神经网络(CNNs)。

BP算法_BP算法

BP神经网络

BP神经网络是这样一种神经网络模型,它是由一个输入层、一个输出层和一个或多个隐层构成,它的激活函数采用sigmoid函数,采用BP算法训练的多层前馈神经网络。

BP算法基本思想

BP算法全称叫作误差反向传播(error Back Propagation,或者也叫作误差逆传播)算法。其算法基本思想为:在前馈网络中,输入信号经输入层输入,通过隐层计算由输出层输出,输出值与标记值比较,若有误差,将误差反向由输出层向输入层传播,在这个过程中,利用梯度下降算法对神经元权值进行调整。

神经网络训练的快慢跟以下因素息息相关:

1.参数(权值,偏置,学习率等)

2.网络结构(层数,每层节点个数)

不同的人不同的大脑结构(参数初始值不同,网络结构与算法不同),决定了你在不同领域的天赋(网络收敛快)不同,天赋高应该怀有一颗感恩之心,天赋低也不要气馁,要努力学习(网络训练),不要怕犯错,你去学了就不会错太多(前向传播),犯了错要反思,要改正(反向传播),错的多需要改的就多(更新参数),改完以后继续尝试,直到不再犯错(网络训练结束)。

BP算法数学工具

BP算法中核心的数学工具就是微积分的链式求导法则。

BP算法_BP算法_02

BP算法_BP算法_03

All needed information is local!!!

也就是说,要求某一个节点上的导数,你需要的信息仅仅是在你后面的那个节点的导数与节点本身函数变换的导数之间的乘积。

为了简单起见,这里只介绍只有一个隐层的BP网络,多个隐层的也是一样的原理。这个网络的工作原理应该很清楚了。

首先,一组输入x1、x2、…、xm来到输入层,然后通过与隐层的连接权重产生一组数据s1、s2、…、sn作为隐层的输入,然后通过隐层节点的θ(⋅)激活函数后变为θ(sj)其中sj表示隐层的第j个节点产生的输出,这些输出将通过隐层与输出层的连接权重产生输出层的输入,这里输出层的处理过程和隐层是一样的,最后会在输出层产生输出y¯j,这里j是指输出层第j个节点的输出。这只是前向传播的过程,很简单吧?在这里,先解释一下隐层的含义,可以看到,隐层连接着输入和输出层,它到底是什么?它就是特征空间,隐层节点的个数就是特征空间的维数,或者说这组数据有多少个特征。而输入层到隐层的连接权重则将输入的原始数据投影到特征空间,比如sj就表示这组数据在特征空间中第j个特征方向的投影大小,或者说这组数据有多少份量的j特征。而隐层到输出层的连接权重表示这些特征是如何影响输出结果的,比如某一特征对某个输出影响比较大,那么连接它们的权重就会比较大。关于隐层的含义就解释这么多,至于多个隐层的,可以理解为特征的特征。

 前面提到激活函数θ(⋅),一般使用S形函数(即sigmoid函数),比如可以使用log-sigmoid:θ(s)=1/1+e^−s

 BP算法_BP算法_04

 或者tan-sigmoid:θ(s)=(e^s−e^−s)/(e^s+e^−s)

 BP算法_BP算法_05

具体过程

BP算法_BP算法_06

一次 BP 权值调整的过程是这样的:

1.输入向量从输入节点依次向后传播,我们可以计算出 the activation of all the hidden and output units

2.计算每个输出节点的残差

3.输出节点的残差依次向前传播,

4.由此可以求得各个隐层的残差由隐层的残差可以求得隐层左侧权重的更新

对于反向传播算法主要从以下几个方面进行总结:

1)局部极小值 

对于多层网络,误差曲面可能含有多个不同的局部极小值,梯度下降可能导致陷入局部极小值。缓解局部极小值的方法主要有增加冲量项,使用随机梯度下降,多次使用不同的初始权值训练网络等。

2)权值过多  

当隐藏节点越多,层数越多时,权值成倍的增长。权值的增长意味着对应的空间的维数越高,过高的维数易导致训练后期的过拟合。

3)算法终止策略 

当迭代次数达到设定的阀值时,或者损失函数小于设定的阀值时

4)过拟合  

当网络的训练次数过多时,可能会出现过拟合的情况。解决过拟合主要两种方法:一种是使用权值衰减的方式,即每次迭代过程中以某个较小的因子降低每个权值;另一种方法就是使用验证集的方式来找出使得验证集误差最小的权值,对训练集较小时可以使用交叉验证等。  

实现代码如下

import numpy as np

def nonlin(x, deriv=False):

if (deriv == True):

return x * (1 - x) #如果deriv为true,求导数

return 1 / (1 + np.exp(-x))

X = np.array([[0.35],[0.9]]) #输入层

y = np.array([[0.5]]) #输出值

np.random.seed(1)

W0 = np.array([[0.1,0.8],[0.4,0.6]])

W1 = np.array([[0.3,0.9]])

print ‘original ‘,W0,’\n’,W1

for j in xrange(100):

l0 = X #相当于文章中x0

l1 = nonlin(np.dot(W0,l0)) #相当于文章中y1

l2 = nonlin(np.dot(W1,l1)) #相当于文章中y2

l2_error = y - l2

Error = 1/2.0*(y-l2)**2

print “Error:”,Error

l2_delta = l2_error * nonlin(l2, deriv=True) #this will backpack

#print ‘l2_delta=’,l2_delta

l1_error = l2_delta*W1; #反向传播

l1_delta = l1_error * nonlin(l1, deriv=True)

W1 += l2_delta*l1.T;        #修改权值
W0 += l0.T.dot(l1_delta)
print W0,'\n',W1