神经网络中BP(back propagation)到底在干些什么

前言

想要理解神经网络的工作原理,反向传播(BP)是必须搞懂的东西。BP其实并不难理解,说白了就是用链式法则(chain rule)算算算。本文试图以某个神经网络为例,尽可能直观,详细,明了地说明反向传播的整个过程。

正向传播

在反向传播之前,必然是要有正向传播的。正向传播时的所有参数都是预先随机取的,没人能说这样的参数好不好,得要试过才知道,试过之后,根据得到的结果与目标值的差距,再通过反向传播取修正各个参数。下图就是一个神经网络,我们以整个为例子来说明整个过程

图1:神经网络图

我懒,此图取自参考文献[1],图中的各个符号说明如下(顺序从下往上):
x i x_i xi:输入样本中的第 i i i个特征的值
v i h v_{ih} vih x i x_i xi与隐层第 h h h个神经元连接的权重
α h \alpha_h αh:第h个隐层神经元的输入, α h = ∑ i = 1 d v i h x i \alpha_h=\sum_{i=1}^d v_{ih}x_i αh=i=1dvihxi
b h b_h bh:第h个隐层神经元的输出,某个神经元的输入和输出有关系 f ( α h ) = b h f(\alpha_h)=b_h f(αh)=bh,其中 f ( x ) f(x) f(x)为激活函数,比如Sigmoid函数 f ( x ) = 1 1 + e − x f(x)=\dfrac{1}{1+e^{-x}} f(x)=1+ex1
w h j w_hj whj:隐层第 h h h个神经元和输出层第 j j j个神经元连接的权重
β j \beta_j βj:输出层第 j j j个神经元的输入, β j = ∑ h = 1 q w h j b h \beta_j=\sum_{h=1}^q w_{hj}b_h βj=h=1qwhjbh
y j y_j yj:第 j j j个输出层神经元的输出, f ( β j ) = y j f(\beta_j)=y_j f(βj)=yj f ( x ) f(x) f(x)为激活函数
为了方便书写,我们假设截距项bias已经在参数 w w w v v v之中了,也就是说在输入数据的时候,我们增添了一个 x 0 = 1 x_0=1 x0=1,由于我懒,图中没有画出来,但心里要清楚这一点。
相信看了图之后,神经网络的正向传播就相当简单明了了,不过,这里我还是啰嗦一句,举个例子,比如输出 y j y_j yj的计算方法为

y j = f ( β j ) = f ( ∑ h = 1 q w h j b h ) = f ( ∑ h = 1 q w h j f ( α h ) ) = f ( ∑ h = 1 q w h j f ( ∑ i = 1 d v i h x i ) ) y_j=f(\beta_j)=f(\sum_{h=1}^q w_{hj}b_h)=f(\sum_{h=1}^q w_{hj}f(\alpha_h))=f(\sum_{h=1}^q w_{hj}f(\sum_{i=1}^d v_{ih}x_i)) yj=f(βj)=f(h=1qwhjbh)=f(h=1qwhjf(αh))=f(h=1qwhjf(i=1dvihxi))

反向传播

好了,通过正向传播,我们就已经得到了 l l l y y y的值了,将它们与目标值 t t t,也就是我们期望它们成为的值作比较,并放入损失函数中,记作 L L L
损失 L L L可以自行选择,比如常见的均方误差 L = 1 2 ∑ j = 1 l ( y j − t j ) 2 L=\dfrac{1}{2}\sum_{j=1}^l (y_j - t_j)^2 L=21j=1l(yjtj)2
利用这个误差,我们将进行反向传播,以此来更新参数 w w w v v v。更新时,我们采用的是梯度下降法,也就是

{ w : = w + Δ w v : = v + Δ v \begin{cases}w := w + \Delta w \\ v := v + \Delta v\end{cases} {w:=w+Δwv:=v+Δv

其中, Δ w = − η ∂ L ∂ w \Delta w = -\eta \dfrac{\partial L}{\partial w} Δw=ηwL Δ v = − η ∂ L ∂ v \Delta v = -\eta \dfrac{\partial L}{\partial v} Δv=ηvL η \eta η为学习率。
下面要做的工作就是计算出每个参数的梯度,这也就是链式法则发挥作用的地方了。
比如,我们要计算 w h j w_{hj} whj。从网络结构中不难看出 w h j w_{hj} whj影响了 β j \beta_j βj从而影响了 y j y_j yj,最终影响了 L L L所以我们有

Δ w h j = − η ∂ β j ∂ w h j ∂ y j ∂ β j ∂ L ∂ y j \Delta w_{hj}=-\eta \dfrac{\partial \beta_j}{\partial w_{hj}} \dfrac{\partial y_j}{\partial \beta_j} \dfrac{\partial L}{\partial y_j} Δwhj=ηwhjβjβjyjyjL

只要确定了损失函数 L L L和激活函数 f ( x ) f(x) f(x),上面所有的都是可以算的,而且 ∂ β h ∂ w h j = b h \dfrac{\partial \beta_h}{\partial w_{hj}} = b_h whjβh=bh这点是显而易见的。并且, ∂ y j ∂ β j = ∂ f ( β j ) ∂ β j \dfrac{\partial y_j}{\partial \beta_j} = \dfrac{\partial f(\beta_j)}{\partial \beta_j} βjyj=βjf(βj)就是激活函数的导数。
同理, v i h v_{ih} vih影响了 α h \alpha_h αh,从而影响了 b h b_h bh,从而影响了 β 1 \beta_{1} β1 β 2 \beta_{2} β2,…, β l \beta_{l} βl,从而影响了 y 1 y_1 y1 y 2 y_2 y2,…, y l y_l yl,最终影响了 L L L

Δ v i h = − η ∂ α h ∂ v i h ∂ b h ∂ α h ∑ j = 1 l ( ∂ β j ∂ b h ∂ y j ∂ β j ∂ L ∂ y j ) \Delta v_{ih} = -\eta \dfrac{\partial \alpha_h}{\partial v_{ih}} \dfrac{\partial b_h}{\partial \alpha_h}\sum_{j=1}^l (\dfrac{\partial \beta_j}{\partial b_h} \dfrac{\partial y_j}{\partial \beta_j} \dfrac{\partial L}{\partial y_j}) Δvih=ηvihαhαhbhj=1l(bhβjβjyjyjL)

其中, ∂ α h ∂ v i h = x i \dfrac{\partial \alpha_h}{\partial v_{ih}}=x_i vihαh=xi ∂ β j ∂ b h = w h j \dfrac{\partial \beta_j}{\partial b_h} = w_{hj} bhβj=whj ∂ y j ∂ β j = ∂ f ( β j ) ∂ β j \dfrac{\partial y_j}{\partial \beta_j} = \dfrac{\partial f(\beta_j)}{\partial \beta_j} βjyj=βjf(βj) ∂ b h ∂ α h = ∂ f ( α h ) ∂ α h \dfrac{\partial b_h}{\partial \alpha_h} = \dfrac{\partial f(\alpha_h)}{\partial \alpha_h} αhbh=αhf(αh)是激活函数的导数。
至此,我们已经可以算出 Δ w \Delta w Δw Δ v \Delta v Δv,从而更新参数了。

关于激活函数的几点说明

从推出的公式中不难看出,随着反向传播向输出层这个方向的推进,激活函数的影响也就越来越来了。通俗一点来说,在计算 Δ w h j \Delta w_{hj} Δwhj,我们只乘了一个激活函数的导数,然而在计算 Δ v i h \Delta v_{ih} Δvih时,我们乘了多个激活函数的导数。

Δ w h j = − η ∂ β j ∂ w h j f ′ ( β j ) ∂ L ∂ y j \Delta w_{hj}=-\eta \dfrac{\partial \beta_j}{\partial w_{hj}} f'(\beta_j) \dfrac{\partial L}{\partial y_j} Δwhj=ηwhjβjf(βj)yjL

Δ v i h = − η ∂ α h ∂ v i h f ′ ( α h ) ∑ j = 1 l ( ∂ β j ∂ b h f ′ ( β j ) ∂ L ∂ y j ) \Delta v_{ih} = -\eta \dfrac{\partial \alpha_h}{\partial v_{ih}} f'(\alpha_h) \sum_{j=1}^l (\dfrac{\partial \beta_j}{\partial b_h} f'(\beta_j) \dfrac{\partial L}{\partial y_j}) Δvih=ηvihαhf(αh)j=1l(bhβjf(βj)yjL)

不难推断出,如果隐层的层数更多的话,激活函数的影响还要更大。
一个比较传统的激活函数时Sigmoid函数,其图像如下所示。

图2:Sigmoid函数

不难发现,当 x x x比较大的时候,或比较小的时候, f ′ ( x ) f'(x) f(x)是趋近于0的,当神经网络的层数很深的时候,这么多个接近0的数相乘就会导致传到输出层这边的时候已经没剩下多少信息了,这时梯度对模型的更新就没有什么贡献了。那么大多数神经元将会饱和,导致网络就几乎不学习。这其实也是Sigmoid函数现在在神经网络中不再受到青睐的原因之一。
另一个原因是Sigmoid 函数不是关于原点中心对称的,这会导致梯度在反向传播过程中,要么全是正数,要么全是负数。导致梯度下降权重更新时出现 Z 字型的下降。
所以,就出现了ReLU这个激活函数 f ( x ) = max ⁡ ( 0 , x ) f\left( x\right) =\max \left( 0,x\right) f(x)=max(0,x),其图像如下图所示。

图3:ReLU函数

ReLU 对于 SGD 的收敛有巨大的加速作用,而且只需要一个阈值就可以得到激活值,而不用去算一大堆复杂的(指数)运算。
不过,由于它左半边的状态,ReLU在训练时比较脆弱并且可能“死掉”。
因此,人们又研究出了Leaky ReLU,PReLU等等的激活函数。这里不展开讨论。

参考文献

[1] 周志华. 机器学习 : = Machine learning[M]. 清华大学出版社, 2016.
[2] http://cs231n.github.io/neural-networks-1/
[2] http://www.jianshu.com/p/6df4ab7c235c

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

七元权

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值