网络权重初始化方法总结(上):梯度消失、梯度爆炸与不好的初始化

博客:blog.shinelee.me | 博客园 | CSDN

前向传播与反向传播回顾

神经网络的训练过程可以简化成以下步骤,

  1. 输入预处理(feature scaling等)
  2. 初始化网络weight和bias
  3. 前向传播,得到网络输出
  4. 计算损失函数,得到当前损失
  5. 反向传播,根据链式法则,逐层回传得到损失函数对当前参数的偏导,根据梯度下降算法对当前参数进行更新
  6. 重复步骤3 4 5,直到损失不再减小,即收敛

一个简单的前向传播和反向传播的示意图如下,线性组合和非线性激活交替进行,线性组合层可以为全连接层或卷积层等,图片来自链接

前向传播
前向传播

反向传播
反向传播

梯度下降算法的参数更新公式为,
$$
W(t+1)=W(t)-\eta \frac{d C}{d W}
$$
其中$C=J(W)$为损失函数,即通过参数的偏导对参数进行更新。反向传播时,由链式法则,偏导反向回传,逐层计算损失函数对当前参数的偏导。对某个参数的偏导为一串因子的乘积,因子依次为损失函数对网络输出的偏导、激活函数的偏导、线性组合的偏导、激活函数的偏导、线性组合的偏导……如下面所示(来自链接),这里,损失为二分之LMS,用$C$表示,$z$为线性组合的输出(激活层的输入),$a$为激活层的输出(线性组合的输入),

反向传播中的偏导计算
反向传播中的偏导计算

仔细观察上式,偏导为一串因子的乘积,因子中的每一项对乘积结果都有影响,有几点需要注意,回传时,

  • 每个权重的偏导中含有一个共同的因子项,为损失函数对网络输出的偏导
  • 每经过一个激活层,就有一个激活函数偏导作为因子项,如$\sigma’(z^L)=\frac{\partial a^L}{\partial z^L}$
  • 对当前线性组合层的权重求偏导,含且只含一个当前层的输入(前一层的输出)作为因子项,如$a^{L-1}$
  • 每经过一个线性组合层(全连接层or卷积层),就有一个权重矩阵作为因子项,如$w^L$

所以,激活函数的偏导、权重矩阵、当前层的输入(前一层的输出),这些项的取值均会对偏导数产生影响,偏导数为这些因子项共同作用的结果,特别地,

  • 若激活函数偏导为0,则权重偏导为0;
  • 若前一层的输出(当前层输入)为0,则当前层权重的偏导为0;
  • 若后一层的权重$w^L$为0,则当前层权重的偏导$\frac{\partial C}{\partial {w^{L-1}}}$为0;

直觉上,因子项连乘可能隐含潜在的问题:$0.25^{10} = 0.00000095367431640625$,$2^{10}=1024$。对于现在动辄几十、成百、上千层的网络,这些因子项的取值范围极大地影响着权重偏导的结果:小了,经过连续相乘,结果可能接近于0,大了,结果可能超过数据类型的上界。同时,网络的深度让这个问题指数级地放大了。

梯度消失与梯度爆炸

梯度为偏导数构成的向量。

损失函数收敛至极小值时,梯度为0(接近0),损失函数不再下降。我们不希望在抵达极小值前,梯度就为0了,也不希望下降过程过于震荡,甚至不收敛。梯度消失与梯度爆炸分别对应这2种现象,

梯度消失(vanishing gradients):指的是在训练过程中,梯度(偏导)过早接近于0的现象,导致(部分)参数一直不再更新,整体上表现得像损失函数收敛了,实际上网络尚未得到充分的训练。

梯度爆炸(exploding gradients):指的是在训练过程中,梯度(偏导)过大甚至为NAN(not a number)的现象,导致损失剧烈震荡,甚至发散(divergence)。

由上一节的分析可知,在梯度(偏导)计算中,主要的影响因素来自激活函数的偏导、当前层的输入(前一层的输出)、以及权重的数值等,这些因子连续相乘,带来的影响是指数级的。训练阶段,权重在不断调整,每一层的输入输出也在不断变化,梯度消失和梯度爆炸可能发生在训练的一开始、也可能发生在训练的过程中

因子项中当前层的输入仅出现一次,下面着重看一下激活函数和权重的影响。

激活函数的影响

以Sigmoid和Tanh为例,其函数与导数如下(来自链接),

Sigmoid和Tanh,及其导数
Sigmoid和Tanh,及其导数

两者的导数均在原点处取得最大值,前者为0.25后者为1,在远离原点的正负方向上,两者导数均趋近于0,即存在饱和区。

  • 原点附近:从因子项连乘结果看,Tanh比Sigmoid稍好,其在原点附近的导数在1附近,如果激活函数的输入均在0左右,偏导连续相乘不会很小也不会很大。而sigmoid就会比较糟糕,其导数最大值为0.25,连续相乘会使梯度指数级减小,在反向传播时,对层数越多的网络,浅层的梯度消失现象越明显。
  • 饱和区:一旦陷入饱和区,两者的偏导都接近于0,导致权重的更新量很小,比如某些权重很大,导致相关的神经元一直陷在饱和区,更新量又接近于0,以致很难跳出或者要花费很长时间才能跳出饱和区。

所以,一个改善方向是选择更好的非线性激活函数,比如ReLU,相关激活函数如下图所示,

activation functions
activation functions

ReLU只在负方向上存在饱和区,正方向上的导数均为1,因此相对更少地遭遇梯度消失,但梯度爆炸现象仍然存在。

权重矩阵的影响

假设激活函数为线性,就像ReLU的正向部分,导数全为1。则一个简化版本的全连接神经网络如下图所示,

a simple 9-layer neural network
a simple 9-layer neural network

假设权重矩阵均为$W$,前向传播和反向传播过程均涉及$W$(转置)的反复相乘,$t$步相当于$W^t$,若$W$有特征值分解$W=V \ diag(\lambda) \ V^{-1} $,简单地,
$$
W^t = (V \ diag(\lambda) \ V^{-1})^t = V \ diag(\lambda)^t \ V^{-1}
$$
其中$diag(\lambda)$为特征值对角矩阵,如果特征值$\lambda_i$不在1附近,大于1经过$t$次幂后会“爆炸”,小于1经过$t$次幂后会“消失”。

如果网络初始化时,权重矩阵过小或过大,则在网络训练的初始阶段就可能遭遇梯度消失或梯度爆炸,表现为损失函数不下降或者过于震荡。

不良初始化

至此,一些权重不良初始化导致的问题就不难解释了,

  • 过小,导致梯度消失

  • 过大,导致梯度爆炸

  • 全常数初始化,即所有权重$W$都相同,则$z^{(2)}=W^1 x$相同,导致后面每一层的输入和输出均相同,即$a$和$z$相同,回到反向传播的公式,每层的偏导相同,进一步导致每层的权重会向相同的方向同步更新,如果学习率只有一个,则每层更新后的权重仍然相同,每层的效果等价于一个神经元,这无疑极大限制了网络的能力。

    反向传播中的偏导计算
    反向传播中的偏导计算

  • 特别地,全0初始化,根据上式,如果激活函数$g(0) = 0$,如ReLU,则初始状态所有激活函数的输入$z$和输出$a$都为0,反向传播时所有的梯度为0,权重不会更新,一直保持为0;如果激活函数$g(0) \neq 0$,则初始状态激活层的输入为0,但输出$a\neq 0$,则权重会从最后一层开始逐层向前更新,改变全0的状态,但是每层权重的更新方向仍相同,同上。

这几种权重初始化方法对网络训练过程的影响,可在Initializing neural networks进行可视化实验,可观察权重、梯度和损失的变化,美中不足的是隐藏层的激活函数只有ReLU,不能更换为Sigmoid、Tanh等,如下所示,

network initialization
network initialization

话说回来,所以我们需要好的网络初始化方法,以对反向传播过程中的梯度有所控制。对反向传播中梯度加以控制的方法,不止这里提到的损失函数和权重初始化,还有梯度截断(gradient clipping)、网络模型设计方面等方法,因为本文的重点在于权重初始化,对此按下不表。

那么,合适的网络初始化方法是什么呢?我们下回分解。

参考

0%