关于CNN、RNN中的梯度爆炸/梯度弥散

梯度爆炸(gradient explosion) 与 梯度弥散(gradient vanishing) 是神经网络研究中常可能遇到的问题,主要体现在训练不收敛,误差、权重波动大,以及出现NaN值,本文以CNN与RNN为例,说明梯度爆炸/弥散的产生原因

CNN

CNN神经网络的简易图如下:关于CNN、RNN中的梯度爆炸/梯度弥散
ff表示卷积函数,忽略pooling层,则每一层的运算可以表示为xn=f(Wnxn1+bn)x_n=f(W_nx_{n-1}+b_n)
也即xn=f(Wnxn1+bn)=f(Wnf(Wn1xn2+bn1)+bn)=f(Wnf(Wn1f(Wn2xn3+bn2)+bn1)+bn)x_n=f(W_nx_{n-1}+b_n) =f(W_nf(W_{n-1}x_{n-2}+b_{n-1})+b_n)=f(W_nf(W_{n-1}f(W_{n-2}x_{n-3}+b_{n-2})+b_{n-1})+b_n)···
因此,若最后的误差为E,则其对第一层权重的导数为EW1=Efn×fnα×Wn×fn1α×Wn1×f1α×αW1\frac{\partial{E}}{\partial{W_1}}=\frac{\partial{E}}{\partial{f_n}} × \frac{\partial{f_n}}{\partial{α}}×W_n× \frac{\partial{f_{n-1}}}{\partial{α}}×W_{n-1}···× \frac{\partial{f_1}}{\partial{α}}×\frac{\partial{α}}{\partial{W_1}}
其中α为**函数,则以sigmoid函数为例,其导数的取值范围为(0, 0.25],即上面的每一项fnα\frac{\partial{f_n}}{\partial{α}}都小于1,则当网络足够深,会导致越接近输入层的神经元,梯度几乎为0,长时间得不到更新
若为tanh,则范围在(0,2),当每一项大于1时就会出现梯度爆炸,权重更新不稳定

RNN

在CNN中,所谓权值共享仅发生在单个的一层,不同层对应的Wi是不同的,而在RNN中,则是每个时间步都共用一个权重,因此梯度是累加的(RNN中为什么要采用tanh而不是ReLu作为**函数):
fnW1=fnαn×fn1+fnαn×W×fn1αn1×fn1++i=0nfiαi×fa1W×Wn\frac{\partial{f_n}}{\partial{W_1}}=\frac{\partial{f_n}}{\partial{α_n}}×f_{n-1} +\frac{\partial{f_n}}{\partial{α_n}}×W×\frac{\partial{f_{n-1}}}{\partial{α_{n-1}}}×f_{n-1}+···+\prod_{i=0}^n{\frac{\partial{f_i}}{\partial{α_i}}}×\frac{\partial{fa_1}}{\partial{W}}×W^n
因此这里越往前回溯,则将有越多的W连乘,若采用ReLU,系数为1,无法弥补W连乘带来的梯度问题
于是经常采取tanh函数
对于梯度问题,经常采用的方法包括但不限于:

  • 在CNN中采用恒等映射,RNN中采用LSTM
  • 梯度截断,设置一个梯度阈值,超过时进行阶段(该阈值的设定需要一定经验)
  • 对权重进行正则化,如L1(权重的绝对值和)正则化与L2(权重的绝对值平方和再开方)正则化
  • 模型重构