RNN训练方法介绍-BPTT

来源:互联网 发布:如何添加usb打印端口 编辑:程序博客网 时间:2024/04/29 15:35

url:http://blog.csdn.net/sysstc/article/details/75333008


Training RNN——BPTT

由于RNN和时间序列有关,因此我们不能通过Backpropagation来调参,我们使用的是Backpropagation through time(BPTT)

回顾Backpropagation

这里写图片描述 
这里写图片描述

Backpropagation through Time(BPTT)

我们可以将RNN变成如下形式: 
这里写图片描述
参照之前的BP我们发现,反向传播其实就是一个梯度* 矩阵 * 激活函数的微分(放大器)。由于an-1和xn同时会影响到an,而an-1又会被an-2和xn-1影响,并且依次传递下去,a1的值会被x1和memory cell initial影响。因此,我们可以把RNN看成一个非常深的DNN,将input看成:Init,x1,x2,…,xn,output是yn,也就是如果n=100,那么就有100个hidden layer。

  • 如何计算Cn这项的gradient呢 
    BPTT同样等于Backward pass + forward pass,forward pass 可以直接当做是一个DNN来计算,而backward pass可以看成如下所示,通过一个hidden layer,就相当于乘以一个个的放大器(activation function) 
    这里写图片描述
    这里写图片描述
    如何更新参数呢,我们看到上面黄色的箭头都是相同的weights,而上面蓝色的箭头也都是相同的weights。因此我们根据如下方式修改。 
    这里写图片描述
  • 如何计算所有的gradient呢?其实也是一个forward pass和一个backward pass 
    这里写图片描述

RNN中train可能遇到的问题

  1. RNN的error surface(误差曲面)是比较崎岖的,有些地方斜率很大,有些地方斜率很小。如 
    这里写图片描述
  2. RNN中gradient vanish产生的原因和DNN gradient vanish产生的原因不一样。 
    • DNN:gradient vanish是因为backward pass时,每经过一层都要经历一个activation function的微分,那这时如果我们使用的activation function是sigmoid,由于sigmoid的微分最大值为1/4,那么error signal就会越来越小,最后可能会出现梯度消失的情况。我们之前提到的解决方式是将activation function由sigmoid改成relu。
    • RNN: 
      • 从一个小案例分析:参考下面图,我们要计算gradient,下面是一个RNN,Input都是1,output都是1,hidden layer 里面就一个神经元,这里我们将hidden layer设置为一个linear。那么由于是一个linear,是不是我们就不会出现gradient vanish的情况呢?答案是否定的: 
        这里写图片描述
        我们发现w的不同,yn变化忽大忽小。这样就会变得非常难处理。就式子和函数图像来分析原因: 
        这里写图片描述
        这种情况就造成我们在算gradient的时候,大多都是一些极端值。 
        那么从这个角度来看我们发现如果你这时候将activation function设置为sigmoid或tanh,这种微分值小于1的activation function,反而能在某种程度上保护rnn,而用relu则不会削减这些大爆炸的情况。所以在处理RNN的时候还是应该采用tanh或者sigmoid
      • 从一般情况来分析,今天为了简化分析,我们将activation function都认为是linear activation function,底下的error signal 没有考虑activation function,如果error signal对应到的Wn-1是小于1的话,那么值就会变得很小,如果error signal对应到的Wn-1大于1的话,那么值就会变得很大。 
        这里写图片描述
  3. RNN中gradient vanish的解决方法: 
    • Clipped Gradient:设置一个threshold,clip(x,min,max)
    • NAG:Momentum进化版。 
      • Momentum是一个模范物体运动的方法,update方向取决于所在位置的Gradient的反方向+上次的movement,这样就可能会照成数值波动。
      • NAG的update方向取决于从现在所在的位置沿着movement再走一步所在的Gradient的反方向+上一次的movement。这样可能会避免产生震荡的情形 
        这里写图片描述
    • RMSProp:Adagrad的进化版 
      • Adagrad:除去这个参数过去所有算出来的gradient的平方和再开根号(即对二次微分的估算)。这样就可以动态调整learning rate
      • RMSProp: 
        过去的gradient会乘上α(0<α<1),那么越过去的gradient我们考虑的权重就会更小,这样二次微分对同一个参数也会产生变化。 
        这里写图片描述

LSTM解决Gradient vanishing problem

  1. LSTM网络: 
    这里写图片描述
  2. LSTM的BPTT过程(考虑gradient): 
    • LSTM的forward pass过程: 
      • 只需要把data带进去就可以求每个neural的output
    • LSTM的backward pass过程: 
      • 遇到了一个”+”,我们可以把这个看成一个activation function。input:a/b,output:a+b,微分值为1。
      • 遇到了一个”x”,我们也把这个看成一个activation function。input:a/b,output:axb,微分值为b/a,底下图片上的点乘代表的是element-wise。 
        这里写图片描述 
        如果我们今天从yt+1做bptt,假设forget gate是开启状态,那么我们发现,从yt+1开始的error signal在通过灰色matrix时会乘以一个W的transposition,在通过activation function时可能会乘以一个小于1的数字之外,error signal就是一路畅行无阻的,就会一路保持constant的error signal,这就是Constant Error Carrousel(CEC)。这样error signal一路保持constant的值的好处有什么呢?如果今天你要update黄色箭头里的element,那么因为红色箭头不会随时间衰减太多,所以蓝色的值也不会太小,那么拿来update黄色箭头的error signal不会太小。 
        这里写图片描述 
        因此LSTM可以解决gradient vanish的问题,但LSTM不能处理gradient explode的问题因为error signal不只走蓝色的箭头,还有可能走绿色的箭头,绿色的箭头再走到蓝色箭头的部分就会一直乘以一个W的transposition,如果W的transposition是小的则没关系,因为error signal是比较大的(之前提到过,在error signal的流动过程中它减小的很少)。但如果W的transposition是大的,这时候不断的乘以W的transposition,值就会变得越来越大,就可能会导致gradient explode的情况。 
        这里写图片描述
  3. RNN和LSTM的差异:对待memory的方式不同。 
    • 对于RNN,每一个step我们都会把hidden Layer的output写到memory里面去,所以memory里面的值每次都会被完全修正,过去的东西其实一点都没有存留下来。这就会导致当你修改模型中某个参数的时候,可能会造成很大的变化,也有可能没有变化。
    • 对于LSTM,如果没有forget gate,那么我们过去得memory都会保存下来,因为我们用的是”+”。如果我们的forget gate没有被开启,那么这个memory就会永远的存在。这样如果我们的memory都会一直留下来,那么在修改某个参数时造成某个改变时,这个改变就不会消失,这样我们的gradient就不会消失,这样就可以保证我们的gradient不会特别小。但无法保证gradient不会explode。

RNN的变形

这里写图片描述

Better Initialization

  1. 产生gradient explorde/vanish的problem是因为我们不断乘上一个Weight matrix的transposition。如果某一个vector正好是weight matrix的identity value是1的话,这件事情就不会发生,那么我们对RNN进行变形,我们让hiddenlayer和hiddenlayer相接的matrix用indentity matrix,然后用Relu作为activation function,这样activation function的影响就可以不计。 
    红色的就是initialized with identity matrix+ReLU 
    这里写图片描述

总结:

在training RNN的时候可能会遇到Gradient vanish和Gradient explode的问题。 
这里的解决方法:

  • 设置一个threshold(min,max)
  • 优化技术 
    • NAG
    • RMSprop
  • LSTM(或者其他变形)
  • 更好的初始化,hidden layer之间的weight初始化用identity matrix,activation function用ReLU.
原创粉丝点击