BP算法(Back Propagation),即反向传播算法,是一种与最优化方法(如梯度下降法)结合使用的,用来训练人工神经网络的常见方法。BP算法会计算网络中所有权重的损失函数的梯度,这个梯度会反馈给最优化方法,用来更新权值以最小化损失函数。它的学习过程由信号的正向传播(求损失)与误差的反向传播(误差回传)两个过程组成。
要了解BP算法的计算过程,我们首先要先了解BP神经网络的基本模型,如下图所示:
从上图中可以看出,BP神经网络模型主要有输入层,隐含层,输出层。其中,隐含层可以有多层。Xn是我们已知的样本数据;Wij是第i层到第j层的权值,在信息正向传递的过程中,同样为已知数据,而在误差反向传递的过程中,我们要更新的就是Wij;Ym是最后输出的数据。
对BP神经网络模型有了基本了解以后,我们来了解一下BP算法的总体流程,BP算法流程图如下:
上面我们说过 ,BP算法的学习过程由信号的正向传播(求损失)与误差的反向传播(误差回传)两个过程组成。接下来,我们通过一个简单的例子来分别说明这两个过程(本例为转载):
假设,你有这样一个网络层:
第一层是输入层,包含两个神经元i1,i2,和截距项b1;第二层是隐含层,包含两个神经元h1,h2和截距项b2,第三层是输出o1,o2,每条线上标的wi是层与层之间连接的权重,激活函数我们默认为sigmoid函数。
现在对它们赋上初值,如下图:
输入数据 i1=0.05,i2=0.10;
输出数据 o1=0.01,o2=0.99;
初始权重 w1=0.15,w2=0.20,w3=0.25,w4=0.30,w5=0.40,w6=0.45,w7=0.50,w8=0.55
我们的目标是在给出输入数据i1和i2(0.05和0.10)的情况下,使输出尽可能与原始输出o1,o2(0.01和0.99)接近。
(一)前向传播
1、输入层—->隐含层:
计算神经元h1的输入加权和:
神经元h1的输出o1:(此处用到激活函数为sigmoid函数):
同理,可计算出神经元h2的输出o2:
2、隐含层—->输出层:
计算输出层神经元o1和o2的值:
得到outo1和outo2以后,前向传播的过程就结束了,我们得到输出值为[0.75136079 , 0.772928465],与实际值[0.01 , 0.99]相差还很远,现在我们对误差进行反向传播,更新权值,重新计算输出。
(二)反向传播
1、计算总误差
总误差(square error),即流程图中的E:
本例中有两个输出,所以我们需要分别计算o1和o2的误差,然后对o1和o2的误差进行加和,总误差为两者之和:
2、隐含层—->输出层的权值更新:
以权重参数w5为例,如果我们想知道w5对整体误差产生了多少影响,可以用整体误差对w5求偏导求出:(链式法则)
下面的图可以更直观的看清楚误差是怎样反向传播的:
现在我们来分别计算每个式子的值:
计算:
计算:
(这一步实际上就是对sigmoid函数求导)
计算:
最后三者相乘:
这样我们就计算出整体误差E对w5的偏导值。
最后我们来更新w5的值:
(其中,是学习速率,这里我们取0.5)
同理,可更新w6、w7、w8:
3、隐含层—->隐含层的权值更新:
方法其实与上面说的差不多,但是有个地方需要变一下,在上文计算总误差对w5的偏导时,是从out(o1)—->net(o1)—->w5,但是在隐含层之间的权值更新时,是out(h1)—->net(h1)—->w1,而out(h1)会接受E(o1)和E(o2)两个地方传来的误差,所以这个地方两个都要计算。
计算:
先计算:
同理,计算出:
两者相加得到总值:
再计算:
再计算:
最后,三者相乘:
最后,更新w1的权值:
同理,可更新w2、w3、w4的权值:
通过本例,我们对BP算法的具体操作和计算过程有了一些了解,接下来我们来具体说一说BP算法中涉及到的一些概念和核心方法。
(一)激活函数
在多层神经网络中,上层节点的输出和下层节点的输入之间具有一个函数关系,这个函数称为激活函数。
1、激活函数的用途
如果不用激励函数(其实相当于激励函数是f(x) = x),在这种情况下,因为每一层节点的输入都是上层输出的线性函数,所以无论神经网络有多少层,输出都是输入的线性组合,与没有隐藏层效果相当,这种情况下神经网络的逼近能力就相当有限。正因如此,我们才需要引入非线性函数作为激活函数,这样深层神经网络表达能力才能更加强大(不再是输入的线性组合,而是几乎可以逼近任意函数)。对于激活函数,一般要求连续可微,以满足求导需求。
2、常见的几种激活函数
Sigmoid函数的表达式:
Sigmoid的图像如下:
Sigmoid的导数图像:
通过分析图像,我们不难发现,Sigmoid函数的输出值范围在0到1之间,特别的,如果是非常大的负数,输出为0;如果是非常大的正数,输出为1。
Sigmiod函数的优点:
(1)Sigmoid的取值范围在(0, 1),而且是单调递增,比较容易优化
(2)Sigmoid求导比较容易,可以直接推导得出。
缺点:
(1)Sigmoid函数收敛比较缓慢
(2)由于Sigmoid是软饱和,容易产生梯度消失,对于深度网络训练不太适合(从图上sigmoid的导数可以看出当x趋于无穷大的时候,也会使导数趋于0)
(3) Sigmoid函数并不是以(0,0)为中心点
tanh函数的表达式:
tanh的函数图像:
tanh的导数图像:
tanh函数的优点:
(1)函数输出以(0,0)为中学
(2)收敛速度相对于Sigmoid更快
缺点:
(1) tanh没有解决sigmoid梯度消失的问题
(二)偏导数、方向导数与梯度(这部分内容主要转载于https://www.cnblogs.com/shine-lee/p/11715033.html)
在上文讲解BP算法是如何计算的例子中,我们提到了链式法则,链式法则的计算里就利用了偏导数 。“偏导”的英文本意是“partial derivatives(局部导数)”,就是“局限于与自己相关的某个小范围之内的导数计算”,并不直接关注全局发生了什么,而是根据与自己相关的信息,计算并输出接下来的结果(链式法则中偏导数的具体计算公式和方法可参考https://zhuanlan.zhihu.com/p/44138371?utm_source=wechat_session)。
(三)梯度下降法
我们都知道,BP算法的正向传播是从输入层经过隐藏层再到输出层,最终得到预测结果,而在第一次传输过程中,使用到的权重(或者说参数)都是开始随机初始化的数据,这就导致利用随机初始化的权重计算得到的结果,与真实值的误差通常很大。
而神经网络要做的一件事其实就是得到与真实值相近甚至一样的预测值,那么就把问题指向了如何修正这些权重,才能使得预测值接近真实值。于是就提出了损失函数,损失函数实际上就是计算真实值和预测值之间的误差。我们以这个误差为基准,来进行BP算法的第二个部分——反向传播。这个过程的核心就是梯度下降法,求每个权重对应误差的偏导数值,以此作为修正权重的依据。
在上文中我们简要介绍了梯度的几何意义,具体来说,对于函数f(x,y),在点(x0,y0),沿着梯度向量的方向就是(∂f/∂x0, ∂f/∂y0)T的方向是f(x,y)增加最快的地方。或者说,沿着梯度向量的方向,更加容易找到函数的最大值。反过来说,沿着梯度向量相反的方向,也就是 -(∂f/∂x0, ∂f/∂y0)T的方向,梯度减少最快,也就是更加容易找到函数的最小值。
正因为梯度向量的这种特性,在最小化损失函数时,我们可以通过梯度下降法来迭代求解,以得到最小化的损失函数(梯度下降法的算法详解可参考https://www.cnblogs.com/pinard/p/5970503.html)。在这里我们主要探讨的问题是:梯度下降法找到的一定是下降最快的方向么?答案是否定的。梯度下降法并不一定是全局下降最快的方向,它只是目标函数在当前的点的切平面(当然高维问题不能叫平面)上下降最快的方向。
(暂时先这样,梯度下降法的总结略多,之后会继续更,个人认为通过例子学习BP算法比直接推导抽象公式要更容易理解,具体推导的抽象公式会慢慢更)