在深度神经网络训练过程的反向传播,梯度逐渐变得非常小或非常大。
导致这个现象的主要原因是激活函数和权重初始化不对
(1)梯度消失:在sigmoid函数与Tanh函数中,靠近输出层的的梯度比较大,在反向传播中,随着层数增加,梯度不断乘以小于1的数,越靠近输出层梯度越小
解决:1使用ReLU及其变种,即更换激活函数,activation='relu'
2使用合适的权重初始化,kernel_initializer='he_normal'
3使用Batch Normalization(即标准化规范化处理,让数据分布更加合理), tf.keras.layers.BatchNormalization()
4使用残差连接的神经网络,x = Add()([x, conv(x)])
场景 :一个10层的全连接网络,每层使用 sigmoid 激活函数,权重初始化为标准正态分布(均值为0,方差为1)。
现象:sigmoid函数的导数最大值为0.25。反向传播时,靠近输出层的梯度(如第10层)数值较大,但每向前传播一层,梯度就要乘一次该层的导数(≤0.25)以及权重矩阵。经过多层后,靠近输入层(如第1层)的梯度变得极小(如 0.2510≈9.5×10−70.2510≈9.5×10−7 再乘以权重),几乎为零。导致前几层参数几乎无法更新,网络训练停滞。
(2)梯度爆炸:在反向传播中,梯度不断增大,甚至非常大。通常出现在权重初始化时就比较大,导致训练过程中梯度膨胀
解决:1使用适当优化算法更新梯度,
2将梯度限制到一个合理范围
3权重的初始化采用 Xavier初始化,此外还可以对权重进行L2正则化
场景 :一个5层的循环神经网络(RNN),使用 tanh 激活函数,权重初始化为较大的值(如均值为0,方差为10的高斯分布)。
现象:tanh导数最大为1,但权重矩阵元素值较大(如10)。反向传播时,每传播一层梯度乘以权重矩阵(范数>1),梯度会指数级增长。例如第5层梯度为1,第4层梯度约为 10×1=1010×1=10,第3层梯度约为 10×10=10010×10=100,......,第1层梯度高达 104104。导致参数更新步长过大,损失值变成NaN,模型发散。