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

博客: 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为例,其函数与导数如下(来自 链接 ),

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

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

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

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

权重矩阵的影响

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

假设权重矩阵均为 \(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等,如下所示,

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

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

参考