梯度消失与梯度爆炸

简介

梯度消失问题和梯度爆炸问题,总的来说可以称为梯度不稳定问题。

  • ReLU激活函数,用Batch Normal,用残差结构解决梯度消失问题
  • 正则化来限制梯度爆炸

梯度消失

梯度消失的原始是反向传播时的链式法则。当模型的层数过多的时候,计算梯度的时候就会出现非常多的乘积项。用下面这个例子来理解:
y 1 = w 1 x 1 + b 1 y_{1} = w_{1}x_{1} + b_{1} y1=w1x1+b1
z 1 = σ ( y 1 ) z_{1} = \sigma(y_{1}) z1=σ(y1)
此时要更新参数 b 1 b_{1} b1,其梯度求取就是:
∂ z 1 ∂ b 1 = ∂ z 1 ∂ y 1 ∂ y 1 ∂ b 1 = σ ′ ( y 1 ) ∂ y 1 ∂ b 1 \frac{\partial z_{1}}{\partial b_{1}} = \frac{\partial z_{1}}{\partial y_{1}}\frac{\partial y_{1}}{\partial b_{1}}= \sigma'(y_{1})\frac{\partial y_{1}}{\partial b_{1}} b1z1=y1z1b1y1=σ(y1)b1y1
所以就可以看出问题了,当激活函数是sigmoid的时候,其表达式与导数分别为:
g ( z ) = 1 1 + e − z g(z) = \frac{1}{1+e^{-z}} g(z)=1+ez1
g ′ ( z ) = ( 1 1 + e − z ) ′ = e − z ( 1 + e − z ) 2 = g ( z ) ( 1 − g ( z ) ) g'(z) = (\frac{1}{1+e^{-z}})'=\frac{e^{-z}}{(1+e^{-z})^2}=g(z)(1-g(z)) g(z)=(1+ez1)=(1+ez)2ez=g(z)(1g(z))
导数的取值范围在(0,0.25),这是一个小于1的数,那么当网络有很多层时,逐层进行激活,就会乘上很多激活函数的导数,梯度也就会越来越小。

梯度爆炸

梯度爆炸也是类似的情况,只是系数>1,反复累计相乘之后,导致爆炸。

解决方法

ReLU激活函数

ReLU函数的导数在正数部分为1,解决了<1导致的梯度消失问题

Batch Normal

BN层提出来的本质就是为了解决反向传播中的梯度问题。

在神经网络中,有这样的一个问题:Internal Covariate Shift。
假设第一层的输入数据经过第一层的处理之后,得到第二层的输入数据。这时候,第二层的输入数据相对第一层的数据分布,就会发生改变,所以这一个batch,第二层的参数更新是为了拟合第二层的输入数据的那个分布。然而到了下一个batch,因为第一层的参数也改变了,所以第二层的输入数据的分布相比上一个batch,又不太一样了。然后第二层的参数更新方向也会发生改变。层数越多,这样的问题就越明显。
但是为了保证每一层的分布不变的话,那么如果把每一层输出的数据都归一化0均值,1方差不就好了?但是这样就会完全学习不到输入数据的特征了。不管什么数据都是服从标准正太分布,想想也会觉得有点奇怪。所以BN就是增加了两个自适应参数,可以通过训练学习的那种参数。这样吧每一层的数据都归一化到𝛽均值,𝛾标准差的正态分布上。
将输入分布变成正态分布,是一种去除数据绝对差异,扩大相对差异的一种行为,所以BN层用在分类上效果的好的。对于Image-to-Image这种任务,数据的绝对差异也是非常重要的,所以BN层可能起不到相应的效果。

残差结构

就是让深层网络通过走捷径,让网络不那么深层。这样梯度消失的问题就缓解了。

正则化

L2正则化是在损失函数上施加的一个惩罚项,当损失过大的时候,让损失可以保持一个较小的值,避免了梯度爆炸,又有防过拟合的作用。