反向传播BP思路梳理

反向传播BP思路梳理

学了用了好多神经网络,我却一直没有搞明白神经网络里的反向传播BP是怎么回事。其实具体的公式推导网上有很多资料,都很详细,但是对于数学差劲的我来说每次得看半天才能懂个大概,而且过段时间就忘的一干二净。这次终于下决心要好好理解一下这个东西。

要想学习一个算法,严谨的数学推导固然重要,但最好的办法还是搞清楚它运作的机理,即为什么通过这个方法就可以达到目的?算法中每一个操作的物理意义是什么?搞清楚这些问题后,即使具体的数学推导和证明依然晦涩难懂,但我们却可以把握算法的核心思想,对其有一个直观的理解。本文尽量避免数学推导,希望能以简单直观的方式梳理反向传播的思路。

反向传播是什么?

简单来说,反向传播就是一个利用链式法则,由外而内逐层计算最终输出对每层的变量的梯度的简便算法。该算法在神经网络中得以普遍应用,因为在神经网络中这样由外而内计算梯度的顺序是从输出层到输入层反向进行的,所以形象地被称为反向传播。

为什么要用反向传播?

要回答这个问题,首先我们来回顾一下我们是如何训练神经网络的。

怎么训练神经网络呢?
通过优化一个损失函数loss,使其数值越来越小,那么我们的网络的性能就会越来越好。

怎么改变loss的数值呢?
通过改变我们网络每一层的参数,就能改变网络的输出,进而就可以改变loss的值。

怎么改变参数才能使loss的数值变小呢?
计算loss对每层参数的梯度,每层参数都向loss对其的负梯度方略微改变,只要当前的loss不处于局部最小值且改变的幅度得当,这种操作一般是能够使loss减小的,这便是梯度下降GD的核心思想。

那怎么计算loss对每层参数的梯度呢?
看看上个问题里写的反向传播的定义,知道为什么要用反向传播了吧。在这里,最终输出即是loss,每层的变量即是每层的参数。

反向传播的机理是什么?

关于反向传播的机理,网上有很多资料都写的非常详细,各种推导证明十分严谨,是深入理解反向传播的最佳教材。在这里,我不想班门弄斧,再重新推导一遍这些公式;而是想以不那么严谨但是直观的方法,了解一下反向传播它究竟做了什么,每一步计算需要用到什么,诸如此类的东西。

首先我们说:反向传播到底传什么?你可能会问:刚刚不是才说了反向传播传的是loss对每层参数的梯度吗,为什么又要问一遍?没错,这就是标准答案,但是我觉得这个答案不够形象。接下来完全以我的个人理解,用不太严谨的思路,将反向传播的过程拆成两个部分:计算loss对每层输出的梯度计算每层的输出对其参数的梯度,可以把计算loss对每层输出的梯度看做反向传播路径的主干,而把计算每层的输出对其参数的梯度看做主干在每一层上的分支。我在这里仅仅是为了提醒自己,写一些直观的理解,详细的公式推导可参看参考资料,写的非常好。

简单起见,假定我们有一个不使用激活函数的MLP网络,输出层为第 L L L层,每一层的输出为 z i z^i zi。反向传播的目标是求出损失 J J J对于每一层的权重 W i W^i Wi和偏置 b i b^i bi的梯度 ∂ J ∂ W i \frac{\partial J}{\partial W^i} WiJ ∂ J ∂ b i \frac{\partial J}{\partial b^i} biJ。利用链式求导法则,有

∂ J ∂ W i = ∂ J ∂ z i ⋅ ∂ z i ∂ W i = ∂ J ∂ z L ⋅ ∂ z L ∂ z L − 1 ⋅ ⋯ ⋅ ∂ z i + 1 ∂ z i ⋅ ∂ z i ∂ W i = ( ∂ J ∂ z L ⋅ ∂ z L ∂ z L − 1 ⋅ ⋯ ⋅ ∂ z i + 1 ∂ z i ) ⋅ ∂ z i ∂ W i \frac{\partial J}{\partial W^i} = \frac{\partial J}{\partial z^i}\cdot \frac{\partial z^i}{\partial W^i} = \frac{\partial J}{\partial z^L} \cdot \frac{\partial z^L}{\partial z^{L-1}} \cdot \cdots \cdot \frac{\partial z^{i+1}}{\partial z^i} \cdot \frac{\partial z_i}{\partial W_i} = \left ( \frac{\partial J}{\partial z^L} \cdot \frac{\partial z^L}{\partial z^{L-1}} \cdot \cdots \cdot \frac{\partial z^{i+1}}{\partial z^i} \right ) \cdot \frac{\partial z_i}{\partial W_i} WiJ=ziJWizi=zLJzL1zLzizi+1Wizi=(zLJzL1zLzizi+1)Wizi

同理,

∂ J ∂ b i = ∂ J ∂ z i ⋅ ∂ z i ∂ b i = ∂ J ∂ z L ⋅ ∂ z L ∂ z L − 1 ⋅ ⋯ ⋅ ∂ z i + 1 ∂ z i ⋅ ∂ z i ∂ b i = ( ∂ J ∂ z L ⋅ ∂ z L ∂ z L − 1 ⋅ ⋯ ⋅ ∂ z i + 1 ∂ z i ) ⋅ ∂ z i ∂ b i \frac{\partial J}{\partial b^i} = \frac{\partial J}{\partial z^i}\cdot \frac{\partial z^i}{\partial b^i} = \frac{\partial J}{\partial z^L} \cdot \frac{\partial z^L}{\partial z^{L-1}} \cdot \cdots \cdot \frac{\partial z^{i+1}}{\partial z^i} \cdot \frac{\partial z_i}{\partial b_i} = \left ( \frac{\partial J}{\partial z^L} \cdot \frac{\partial z^L}{\partial z^{L-1}} \cdot \cdots \cdot \frac{\partial z^{i+1}}{\partial z^i} \right ) \cdot \frac{\partial z_i}{\partial b_i} biJ=ziJbizi=zLJzL1zLzizi+1bizi=(zLJzL1zLzizi+1)bizi

我们明显可以看到,上面两个式子存在一个公共部分,即用括号括起来的部分,而且似乎用“反向传播”来形容这个部分似乎更加贴切:这部分正是将梯度从输出层一级一级地回传到需要更新参数的当前层的过程!首先计算损失 J J J对网络输出层的输出 z L z^L zL的梯度 ∂ J ∂ z L \frac{\partial J}{\partial z^L} zLJ,之后使用链式法则,通过将其乘以输出层的输出对上一层的输出的梯度 ∂ z L ∂ z L − 1 \frac{\partial z^L}{\partial z^{L-1}} zL1zL,就能得到损失 J J J对倒数第二层输出的梯度。以此类推,可以很方便地由后至前逐步计算出 J J J对每一层的输出 z i z^i zi的梯度 ∂ J ∂ z i \frac{\partial J}{\partial z^i} ziJ。这部分即是上述计算loss对每层输出的梯度

得到了损失 J J J对本层输出的梯度 ∂ J ∂ z i \frac{\partial J}{\partial z^i} ziJ,接下来继续应用链式法则,只要求出本层输出对相应权重 W W W和偏置 b b b的梯度 ∂ z i ∂ W i \frac{\partial z_i}{\partial W_i} Wizi ∂ z i ∂ b i \frac{\partial z_i}{\partial b_i} bizi并与之相乘,就能得到我们所需要的用于梯度下降的 ∂ J ∂ W i \frac{\partial J}{\partial W^i} WiJ ∂ J ∂ b i \frac{\partial J}{\partial b^i} biJ了。这部分即是上述计算每层的输出对其参数的梯度

如果添加激活函数,则可将 z i z^i zi看作“未激活输出”,每次 ∂ z i − 1 ∂ z i \frac{\partial z_{i-1}}{\partial z_i} zizi1的部分会包含激活函数的导数。卷积层与全连接层类似,可以在参考文献里找到详细讲解。

要想实现有效的反向传播,有什么条件?

有效的反向传播最终能够计算出用于梯度下降的 ∂ J ∂ W i \frac{\partial J}{\partial W^i} WiJ ∂ J ∂ b i \frac{\partial J}{\partial b^i} biJ。那什么时候反向传播会达不到我们想要的结果呢?一是无法进行反向传播,比如前向过程出现不可导的操作时,反向传播会在此中止;二是如果每次反向传播得到的梯度都是0,那么将无法进行参数更新。这里在尽量不涉及数学公式的情况下着重讨论一下后者。

上一节我们把反向传播分为两个部分:主干计算loss对每层输出的梯度和分支计算每层的输出对其参数的梯度。想要反向传播得到有效的梯度,主干中的任何一个中间梯度都不能为0,否则在本次反向传播中其后的所有梯度都将为0;而分支的梯度为0会使得本次本层的权重 W W W或偏置 b b b获得0梯度而无法更新。依据参考文献,在这里做一个简单的归纳。同样以MLP为例,不考虑激活函数。

首先来看主干的部分,即 ∂ J ∂ z L ⋅ ∂ z L ∂ z L − 1 ⋅ ⋯ ⋅ ∂ z i + 1 ∂ z i ⋯ \frac{\partial J}{\partial z^L} \cdot \frac{\partial z^L}{\partial z^{L-1}} \cdot \cdots \cdot \frac{\partial z^{i+1}}{\partial z^{i}} \cdots zLJzL1zLzizi+1。只要损失函数可导,那么 ∂ J ∂ z L \frac{\partial J}{\partial z^L} zLJ这部分肯定没有问题。接下来思考 ∂ z i + 1 ∂ z i \frac{\partial z^{i+1}}{\partial z^i} zizi+1里一般会包含什么内容?由 z i z^i zi z i + 1 z^{i+1} zi+1的前向传播过程一定与 W i + 1 W^{i+1} Wi+1 b i + 1 b^{i+1} bi+1相关,为 z i + 1 = W i + 1 z i + b i + 1 z^{i+1}=W^{i+1}z^i+b^{i+1} zi+1=Wi+1zi+bi+1。此前向过程对 z i z^i zi求导,得到 W i + 1 W^{i+1} Wi+1,而因为 b i + 1 b^{i+1} bi+1 z i z^i zi无关,被当成常数项处理而不被包含。如果 W i + 1 = 0 W^{i+1} = 0 Wi+1=0,则 ∂ z i + 1 ∂ z i = 0 \frac{\partial z^{i+1}}{\partial z^i}=0 zizi+1=0,本次反向传播中断,此层及此后所有层得到的 ∂ J ∂ z i = 0 \frac{\partial J}{\partial z^i}=0 ziJ=0,得不到有效的梯度信息。

假设主干得到了本层有效的梯度 ∂ J ∂ z i ≠ 0 \frac{\partial J}{\partial z^i}\neq 0 ziJ=0,我们再来看分支的情况,即 ∂ z i ∂ W i \frac{\partial z_i}{\partial W_i} Wizi ∂ z i ∂ b i \frac{\partial z_i}{\partial b_i} bizi。这次我们把目光聚焦在与 W i W^i Wi b i b^i bi z i z^i zi有关的前向传播部分,即由 z i − 1 z^{i-1} zi1 z i z^i zi的前向传播过程 z i = W i z i − 1 + b i z^i=W^iz^{i-1}+b^i zi=Wizi1+bi。该过程对 W i W^i Wi求导得到 z i − 1 z^{i-1} zi1,而对 b i b^i bi求导得到常数 1 1 1。因此, W i W^i Wi能否更新除了和主干有关,还和本层输入 z i − 1 z^{i-1} zi1有关,而 b i b^i bi的更新则只与主干的梯度有关。

总结一下,如果某层的权重 W i = 0 W^i=0 Wi=0,则 ∂ z i ∂ z i − 1 = 0 \frac{\partial z^i}{\partial z^{i-1}}=0 zi1zi=0,主干中断,该层之后的所有层在本次反向传播中得不到任何回传的梯度;如果某层的输入 z i − 1 = 0 z^{i-1}=0 zi1=0 W i W^i Wi的分支中断,本次本层的 W i W^i Wi获得的梯度为0,无法更新,但 b i b^i bi不受影响。

加入激活函数与上述分析类似,只是需要考虑激活函数的导数,其中不含影响结论的变量;使用卷积网络思路基本相同,分析推导过程不同,结论大致相同。

结语

写这个文章的起因是和同学讨论,如果卷积层的 W W W b b b都初始化为0的话能不能更新其参数?现在我们可以不严谨地回答一下这个问题了:如果有顺次相连的两个及两个以上的卷积层的 W W W b b b都初始化为0,那么包括这这几个卷积层在内及其之前所有的层,其 W W W全部无法更新,并且除了最后一个0初始化卷积层的 b b b之外的 b b b都无法更新。因为最后一个卷积层权重 W i W^i Wi为0,第一次反向传播主干中断,仅最后一层的参数可能获得更新;而由于其之前的卷积层参数也均为0,故最后一层的输入为0,可知 W i W^i Wi无法更新,依然全部为0,仅 b i b^i bi能够获得更新,但 b i b^i bi的更新并不能影响反向传播,如此一来便始终有 W i = 0 W^i=0 Wi=0。这样的话主干始终不通,第 i i i层及其之前层的所有参数除 b i b^i bi外都不会更新。

另外,除了将网络参数初始化为全0,将所有参数初始化为相同的常数可能使梯度对称,从而使同一层的所有参数总是同步更新而导致训练无效。

写了一堆,感觉挺乱,而且缺少公式不甚严谨,就权当是给自己写个备忘吧。如有错误,欢迎指出。

参考资料

深度神经网络(DNN)反向传播算法(BP)
卷积神经网络(CNN)反向传播算法

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值