前言
提起BP算法(Back Propagation),相信学过深度学习的人都不陌生,在深层的网络中对权重参数的更新免不了要使用这个算法,所以BP算法也是入门深度学习的一个必须理解的算法。
写这篇文章的缘由是我自己对BP算法在此之前也是属于半懂(知道工作原理,不明白处理细节)的状态,看了网上许多文章,觉得讲的都不够简单,让刚入门的小白难以接受,产生劝退效果。因此,打算通过写一篇简单理解BP算法的文章,一方面提升自己对BP的理解,另一方面希望看到这篇文章的小伙伴能够掌握BP算法的原理,为以后的学习铺路。

1. 单层网络参数优化
BP算法是针对深层次网络进行参数更新的算法,因此需要先理解单层网络下,权重是如何被更新的。
1.1 模型定义
为了理解简便,我们采用最简单的线性分类模型
y=f(x)=wTx+b(1)
从公式容易看出,输入是一个向量x,wT是参数矩阵,b是偏置(对这些不了解的可以先看我这篇机器学习:线性分类问题(基础知识))。转换成网络图如下:

可以看出经过网络后,一个三维的输入向量转换成了一个二维的输出向量
例如得到输出向量为y=[0.7,0.3]而真实的数据是y^=[1,0],那么说明模型的参数还不符合预期,存在误差,这时候就要定义损失函数将误差计算出来。
1.2 损失函数
损失函数是用于衡量预测输出和真实输出之间差距的,通常我们采用均方误差(有时候也用熵):
loss(y,y^)=21i=1∑N∣∣y−y^∣∣2(2)
这里N是输入的样本数量,每个样本输入都会得到一组y,y^
有了损失相当于告诉我们模型还不够完善,要对模型优化(就是对权重更新),如何更新的步骤就是参数优化算法要干的事了
1.3 参数优化
相信大家也很熟悉参数优化采用的方式是梯度下降算法(更一般地是随机梯度下降),梯度下降的含义在于我们知道了误差,现在想要将误差减小,注意这里的参数是w,b,你可以简单理解为x,y一元函数优化的过程,下图展示了梯度下降:

如图,我们需要从实际的loss降到期望的最小loss,很显然,最快的方法就是验证导数最大的反方向下降,但是我们下降了一会,到了一个新的loss点的时候,原理的导数最大方向不是当前的导数最大方向了。因此,在梯度下降算法中常常有一个超参数叫做学习率(α),它控制了梯度下降的步长,告诉我们走一段之后重新计算梯度,再往下走。当基本稳定在某个点的时候就不需要再继续下降了。
上面是梯度下降的过程,让我们理解参数是如何被优化的,但同时也可引出三个常见问题的答案
- 梯度下降得到的最小loss是极值点,不是最值点
- 学习率不能太小,会使得收敛速度过慢,训练时间过长
- 学习率不能太大,会达不到区域最优,在附近震荡
到此一轮参数更新已经完成,实际训练中,往往要进行多个周期的更新达到更好的效果,即重复上面的步骤即可。
2. 多层网络的参数优化
上面的方法仅适用于单层(只有输入输出层)的参数优化,当遇到多层网络时,最后一层的参数依然可根据输出的损失,但如何将最后一层的损失传递到前一层,再更新前一层的参数就需要BP算法出马了。
2.1 多层网络模型设计
同样为了简便理解,我们采用一个稍微简单一些的多层网络描述BP算法,网络结构如下:

需要解释的地方是f(a1)=o1是,a1是前面x和w,b计算得到结果,f表示**函数,用于添加非线性操作,使得网络能够处理非线性问题。o1是该神经元的输出,也是下一层的输入
因此我们可以得到第l层和l−1层的关系公式如下所示:
al=wlol−1+bol=f(al)(3)
其中前面一条与单层的时候类似,只是后面多了一个**函数。因此我们可以将整个网络写成下面的方式(为了简便,参数b省略):
f3(w3f2(w2f1(w1x)))=y(4)
说白了就是输入转换成输出再当输入,进行多次(可以理解成多个单层叠加)
2.2 BP算法
我们用C表示损失函数,依据公式(3),对任意层l,将公式形式表达如下(将w扩展成增广矩阵W,b放到增广矩阵中):
al=Wlol−1=g(Wl)ol=f(al)(5)
最后一层输出oL会被用于求损失函数C
按照梯度下降原则,即L对l层参数求导,结合(5)采用求导链式法则
∂Wl∂C=∂al∂C∂Wl∂al=∂al∂C∂Wl∂Wlol−1=∂al∂Col−1T(6)
这里用到了矩阵求导法则∂A∂Ax=xT
注意这部分出来了一个∂al∂C就是误差向量,我们用ξl表示,所谓误差反向传播,就是要将最后一层计算得到的误差传到前面层去,来更新前面的参数。因此我们考虑l+1层和l层的关系,利用链式法则将l与l+1联系,并根据公式(5)引入ol,最终的目的是要ξl的表达式中只包含ξl+1,Wl+1,如下推导:
ξl=∂al∂C=∂al+1∂C∂al∂al+1=∂al+1∂C∂ol∂al+1∂al∂ol=ξl+1∂ol∂Wl+1olf′(al)=ξl+1Wl+1Tf′(al)(7)
这部分的推导可能稍微难理解,需要结合公式(5)对三个部分分别计算求导,将al+1,ol分别替换再求导。矩阵对向量求导公式∂x∂Ax=AT
现在Wl+1T,f′(al)都是确定的,只要我们求得最后一层的误差向量ξL就可以推出倒数第二层的误差向量,再推出倒数第三层…
ξL=∂aL∂C=∂aL∂21∣∣oL−y∣∣2=∂aL∂21∣∣f(aL)−y∣∣2=(f(aL)−y)f′(aL)(8)
下面我们就用L层的误差向量去更新L层参数权重:
由公式(6)和梯度下降法知
WL=WL−α∂WL∂C=WL−αξLf(aL)=WL−α(f(aL)−y)f(aL)f′(aL)(9)
当L层的参数被更新后,计算倒数第二层的误差向量ξL−1,再去更新L−1层的参数,一直到第一层。
在这里我们也可以发现一个常见问题,为什么当网络层数过深的时候,会出现梯度消失的情况。注意到每一次的误差都是要乘上**函数的导数的-公式(8),因此,当采用sigmod
这类当自变量较大,导数趋近于0的**函数时,经过不断的累乘,会使得误差向量趋近于0,使得误差没办法传到前面几层。这种时候可以选用RELU
这类梯度较为稳定的**函数替换。
3. 总结
BP算法涉及到较为复杂的求导和更新,一遍读下来可能会觉得晕,不过不用急,多读几遍,将几个不理解的地方自己手动推导一下,我们总结一下BP的全过程,主要有以下几个步骤:
- 正向传播得到预测输出
- 将预测输出与真实输出根据损失函数计算误差
- 根据误差更新参数权重-公式(9)
- 根据本层误差和本层的参数矩阵和**函数的导数-公式(7)求传递给前一层的误差
- 重复3-4,直到第一层
这篇文章写了5k+字,主要是公式编辑很多,码字不易,如果觉得对你理解BP算法有帮助,不妨点个赞吧~
4. 参考资料
感谢前人的总结和详细的阐述,本文主要还是在前人基础上做了更细微一些的讲解,其中有些地方是我自己的理解,可能有错误或不到之处,欢迎指正批评~