首页 > 人工智能(Artificial Intelligence) > 循环神经网络

循环神经网络(RNN)的反向传播

RNN反向传播算法的思路和DNN是一样的,即通过梯度下降法一轮轮的迭代,得到合适的RNN模型参数U,W,V,b,c。由于我们是基于时间反向传播,所以RNN的反向传播有时也叫做BPTT(back-propagation through time,通过时间的反向传播)。当然这里的BPTT和DNN也有很大的不同点,即这里所有的U,W,V,b,c在序列的各个位置是共享的,反向传播时我们更新的是相同的参数。

为了简化描述,这里的损失函数我们为交叉熵损失函数,输出的激活函数为softmax函数,隐藏层的激活函数为tanh函数。

通过时间的反向传播(Backpropagation through time)

如果$y_t$是预测值,$\hat y_t$是对应的实际值,那么,误差通过交叉熵损失来计算:

$E_t(\hat y_t,y_t) = – \hat y_t log(y_t)$

$E(\hat y,y) = – \sum \hat y_t log(y_t)$

我们通常把整个序列(单词)看作一个训练样本,所以总的误差是每个时间步(字符)中误差的和。权重在每一个时间步长是相同的(所以可以计算总误差后一起更新)。

总结一下反向传播的步骤:

  1. 首先使用预测输出和实际输出计算交叉熵误差
  2. 网络按照时间步完全展开
  3. 对于展开的网络,对于每一个时间步计算权重的梯度
  4. 因为对于所有时间步来说,权重都一样,所以对于所有的时间步,可以一起得到梯度(而不是像神经网络一样对不同的隐藏层得到不同的梯度)
  5. 随后对循环神经元的权重进行升级

对于RNN,由于我们在序列的每个位置都有损失函数,因此最终的损失L为:

$L = \sum\limits_{t=1}^{\tau}L^{(t)}$

其中 V,c 的梯度计算比较简单:

$\frac{\partial L}{\partial c} = \sum\limits_{t=1}^{\tau}\frac{\partial L^{(t)}}{\partial c}  = \sum\limits_{t=1}^{\tau}\hat{y}^{(t)} - y^{(t)}$

$\frac{\partial L}{\partial V} =\sum\limits_{t=1}^{\tau}\frac{\partial L^{(t)}}{\partial V}  = \sum\limits_{t=1}^{\tau}(\hat{y}^{(t)} - y^{(t)}) (s^{(t)})^T$

W,U,b的梯度计算比较的复杂。从RNN的模型可以看出,在反向传播时,在在某一序列位置t的梯度损失由当前位置的输出对应的梯度损失和序列索引位置t+1时的梯度损失两部分共同决定。对于W在某一序列位置t的梯度损失需要反向传播一步步的计算。我们定义序列索引t位置的隐藏状态的梯度为:

$\delta^{(t)} = \frac{\partial L}{\partial s^{(t)}}$

这样我们可以像DNN一样从$\delta^{(t+1)} $递推$\delta^{(t)} $ 。

$\delta^{(t)} =(\frac{\partial o^{(t)}}{\partial s^{(t)}} )^T\frac{\partial L}{\partial o^{(t)}} + (\frac{\partial s^{(t+1)}}{\partial s^{(t)}})^T\frac{\partial L}{\partial s^{(t+1)}} = V^T(\hat{y}^{(t)} - y^{(t)}) + W^T\delta^{(t+1)}diag(1-(s^{(t+1)})^2)$

对于$\delta^{(\tau)} $,由于它的后面没有其他的序列索引了,因此有:

$\delta^{(\tau)} =( \frac{\partial o^{(\tau)}}{\partial s^{(\tau)}})^T\frac{\partial L}{\partial o^{(\tau)}} = V^T(\hat{y}^{(\tau)} - y^{(\tau)})$

有了$\delta^{(\tau)} $,计算W,U,b就容易了,这里给出W,U,b的梯度计算表达式:

$\frac{\partial L}{\partial W} = \sum\limits_{t=1}^{\tau}diag(1-(s^{(t)})^2)\delta^{(t)}(s^{(t-1)})^T$

$\frac{\partial L}{\partial b}= \sum\limits_{t=1}^{\tau}diag(1-(s^{(t)})^2)\delta^{(t)}$

$\frac{\partial L}{\partial U} =\sum\limits_{t=1}^{\tau}diag(1-(s^{(t)})^2)\delta^{(t)}(x^{(t)})^T$

除了梯度表达式不同,RNN的反向传播算法和DNN区别不大。

梯度爆炸和消失问题

RNN基于这样的机制,信息的结果依赖于前面的状态或前N个时间步。普通的RNN可能在学习长距离依赖性方面存在困难。例如,如果我们有这样一句话,“The man who ate my pizza has purple hair”。在这种情况下,purple hair描述的是The man,而不是pizza。所以这是一个长距离的依赖关系。

如果我们在这种情况下后向传播,我们就需要应用链式法则。在三个时间步后对第一个求梯度的公式如下:

$∂E/∂W = ∂E/∂y3 ∂y3/∂h3 ∂h3/∂y2 *∂y2/∂h1 .. $这就是一个长距离的依赖关系.

在这里,我们应用了链式规则,如果任何一个梯度接近0,所有的梯度都会成指数倍的迅速变成零。这样将不再有助于网络学习任何东西。这就是所谓的消失梯度问题。

消失梯度问题与爆炸梯度问题相比,对网络更有威胁性,梯度爆炸就是由于单个或多个梯度值变得非常高,梯度变得非常大。之所以我们更关心梯度消失问题,是因为通过一个预定义的阈值可以很容易地解决梯度爆炸问题。有一些方法来处理消失梯度问题。如LSTM结构(长短期记忆网络)和GRU(门控循环单元)可以用来处理消失的梯度问题。

关闭
感谢您的支持,我会继续努力!
扫码打赏,建议金额1-10元


提醒:打赏金额将直接进入对方账号,无法退款,请您谨慎操作。