本文简要介绍梯度消失 (gradient vanishing) 和梯度爆炸 (gradient exploding) 问题,并给出一些可行的解决方法。
神经网络在更新参数的过程中,使用反向传播 (Backpropagation) 算法求得各层网络的梯度,可以看作是
神经网络式的链式法则。反向传播过程是导致梯度消失和梯度爆炸问题的主要原因,而且随着网络的深度增加,这些问题越发明显。
深度神经网络在解决复杂问题时,比浅层神经网络的效果更好,但也无法避免地会遇到梯度消失或梯度爆炸问题。
梯度消失的常见情形:
- 深层网络
- 使用了sigmoid激活函数
梯度爆炸的常见情形:
- 深层网络
- 参数的初始值过大
1. 梯度推导过程
我们用一个例子来说明:
上图是一个5层的网络,每一层的输入记为
xi, bias记为
bi,权重记为
wi,输出为
zi,激活后的输出记为
hi,sigmoid函数用
σ表示,则有:
zi=xiwi+bi
hi=σ(zi)
x4=h3,x3=h2,x2=h1
设最终的损失函数为
L,则利用反向传播方法求
L关于
w1的梯度过程如下:
∂w1∂L=∂h4∂L∂z4∂h4∂x4∂z4∂z3∂x4∂x3∂z3∂z2∂x3∂x2∂z2∂z1∂x2∂w1∂z1=∂h4∂Lσ′(z4)w4σ′(z3)w3σ′(z2)w2σ′(z1)x1(1)
2. sigmoid函数的性质
sigmoid函数的定义为:
σ=1+e−z1
导数:
σ′=(1+e−z)2e−z=σ⋅(1−σ)
由上式可知,
σ′的变化趋势为:先递增,然后递减,并在
σ=21,也即
z=0时取得最大值
41。我们画出
σ′的图像,如下图所示:
因此,我们得到:
σ′(z)≤41
3. 梯度消失与梯度爆炸的原因
神经网络的参数采用随机初始化的方法,取值往往会小于1,也即
∣w∣<1,所以式(1)中,梯度
∂w1∂L随着网络深度的增加,数值一直在减小,并且传递到第
i层时,数值小于第
i+1层的
41。
如果网络非常深,就可能会使得前几层网络参数的梯度接近于0,也就发生了梯度消失现象。
另外,如果网络的初始化参数
∣w∣比较大,会造成
∣σ′(z)w∣>1的情况,此时式(1)中,梯度
∂w1∂L随着网络深度的增加,数值一直增大。如果网络非常深,就可能会使得前几层网络参数的梯度非常大,也就发生了梯度爆炸现象。
4. 一些其他的激活函数
4.1 tanh函数
tanh(z)=ez+e−zez−e−z
tanh′(z)=1−tanh2(z)
tanh函数和其导数的图形如下:
由上图可知,tanh函数的导数值也小于1,比sigmoid函数略好,但仍会导致梯度消失。
4.2 ReLU函数
ReLU(z)=max(x,0)
ReLU′(z)={0,1,z≤0z>0
ReLU函数和其导数的图形如下:
由上图可知,ReLU函数的导数,在正值部分恒为1,因此不会导致梯度消失或梯度爆炸问题。
另外ReLU函数还有一些优点:
- 计算方便,计算速度快
- 解决了梯度消失问题,收敛速度快
ReLU函数的缺点:
- 输出不是zero-centered,同sigmoid一样
- 某些神经元可能永远不会激活,导致相应的参数永远不会被更新。(解决方法:减小learning rate;Xavier初始化方法)
- 数据没有被压缩,数据的幅值会随着网络层数的增加而不断扩张。
5. 解决方案
5.1 Batch Normalization 批标准化
BN将网络中每一层的输出标准化为正态分布,并使用缩放和平移参数对标准化之后的数据分布进行调整,可以将集中在梯度饱和区的原始输出拉向线性变化区,增大梯度值,缓解梯度消失问题,并加快网络的学习速度。
详细解读,请参考 Batch Normalization 批标准化及其相关数学原理和推导
5.2 选用ReLU、leak ReLU、eReLU等激活函数
ReLU函数的性质,在上文已有相关表述。
5.3 使用梯度剪切预防梯度爆炸
为梯度设置一个阈值,在更新过程中,超过这个阈值的梯度被强制限定在这一范围,防止梯度爆炸。
5.4 使用正则化 (regularization) 预防梯度爆炸
在损失函数中加入参数的正则化项,在防止过拟合的同时,还可以防止梯度爆炸。
L=∥wx−y∥2+γ∥w∥2
5.5 使用残差网络ResNet
使用ResNet可以轻松搭建几百层、上千层的网络,而不用担心梯度消失问题。
5.6 LSTM网络