梯度消失与梯度爆炸
简介
梯度消失问题和梯度爆炸问题,总的来说可以称为梯度不稳定问题。
- 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}}
∂b1∂z1=∂y1∂z1∂b1∂y1=σ′(y1)∂b1∂y1
所以就可以看出问题了,当激活函数是sigmoid的时候,其表达式与导数分别为:
g
(
z
)
=
1
1
+
e
−
z
g(z) = \frac{1}{1+e^{-z}}
g(z)=1+e−z1
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+e−z1)′=(1+e−z)2e−z=g(z)(1−g(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正则化是在损失函数上施加的一个惩罚项,当损失过大的时候,让损失可以保持一个较小的值,避免了梯度爆炸,又有防过拟合的作用。