循环神经网络RNN 梯度推导(BPTT)

循环神经网络简介

循环神经网络(Recurrent Neural Network,RNN),是一种sequence model,它的思想就是使用序列信息。在前馈、卷积神经网络中,认为输入(和输出)彼此之间是互相独立的。但是对很多任务而言,这种处理方式很不合理。同时,在前馈、卷积神经网络中,输入和输出的维数都是固定的,不能任意改变,且无法处理变长的序列数据循环神经网络,它对于序列中的每个元素都执行相同的任务,输出依赖于之前的计算。另一种思考循环神经网络的方法是,它们有一个记忆,记忆可以捕获迄今为止已经计算过的信息。理论上循环神经网络可以利用任意长度的序列信息。但是,在实际应用中,由于梯度传播的原因,它们仅能利用有限步长。循环神经网络的网络结构图如下:


mark

在上图的网络中,网络在t时刻接收到输入$x_t$之后,隐藏层的值是$s_t$,输出值是$o_t$。$h_t$的值不仅依赖于$x_t$,还取决于$s_{t-1}$。循环神经网络的计算方法如下:$$
o_t = g(V_{h_t}) (公式1)\\\\
s_t = f(Ux_t+Ws_{t-1}) (公式2)
$$

其中,公式1是输出层的计算公式,输出层可以是一个全连接层,V是输出层的权重矩阵,g是相应的激活函数。公式2是隐藏层的计算公式,它是循环层。U是输入x的权重矩阵,W是上一层的输出值$s_{t-1}$作为这一次的输入的权重矩阵,f是激活函数。

可以看出,循环层和全连接层的区别就是多了一个权重矩阵W。如果把公式2反复带到公式1,我们可以得到:
$$
\begin{aligned}
o_t &= g(Vs_t)\\\\
&=Vf(Vs_t)\\\\
&=Vf(Ux_t+Ws_{t-1})\\\\
&=Vf(Ux_t+Wf(Ux_{t-1}+Ws_{t-2}))\\\\
&=Vf(Ux_t+Wf(Ux_{t-1}+Wf(Ux_{t-2}+Ws_{t-3})))\\\\
&=Vf(Ux_t+Wf(Ux_{t-1}+Wf(Ux_{t-2}+Wf(Ux_{t-3}+…))))
\end {aligned}
$$

从上面可以看出,循环神经网络的输出值$o_t$,是受前面的历次输入值$x_t、x_{t-1}、x_{t-2}、…$影响的,这就是为什么循环神经网络可以往前看任意多个输入值的原因。
循环神经网络的隐藏层的输出可以用于预测词汇/标签等符号的分布,隐藏层状态保留了到目前为止的历史信息。

循环神经网络的训练算法BPTT介绍

循环神网络的训练算法是Backpropagation Through Time,BPTT算法,其基本原理和反向传播算法是一样的,只不过反向传播算法是按照层进行反向传播,BPTT是按照时间t进行反向传播。对于下图所示的循环神经网络:


mark

这个图和上面的图所示的架构没有区别,只不过是把隐藏层的状态用$h_t$表示,t时刻的输出用$y_t$表示。$$
h_t = f(Uh_{t-1}+Wx_t+b)\\\\y_t=softmax(Vh_t)
$$
假设循环神经网络在每个时刻t都有一个监督信息,损失为$J_t$,则整个序列的损失为$J=\sum_{t=1}^T J_t$。$$
J_t = -y_tlogy_t\\\\
J = -\sum_{t=1}^T y_tlogy_t
$$

1、J关于V的梯度计算

$$
\frac {\partial J}{\partial V} = \frac {\partial}{\partial V} \sum_{t=1}^T J_t=\sum_{t=1}^T \frac {\partial J_t}{\partial V}
$$
令$$y_t = softmax(z_t)\\\ z_t = Vh_t$$,则$\frac {\partial J_t}{\partial V}$的计算公式如下:

$$
\frac {\partial J_t}{\partial V} = \frac {\partial J_t}{\partial y_t}\frac {\partial y_t}{\partial V}=\frac {\partial J_t}{\partial y_t} \frac {\partial y_t}{\partial z_t} \frac {\partial z_t}{\partial V}
$$

2、损失J关于U的梯度计算

$$
\frac {\partial J}{\partial U} = \frac {\partial}{\partial U} \sum_{t=1}^T \frac {\partial J_t}{\partial U}=\sum_{t=1}^T \frac {\partial h_t}{\partial U} \frac {\partial J_t}{\partial h_t}
$$
其中,$h_t$是关于U和$h_{t-1}$的函数,而$h_{t-1}$又是关于U和$h_{t-2}$的函数。

用链式法则可以得到:
$$\frac {\partial J}{\partial U} = \sum_{t=1}^T\sum_{k=1}^t \frac {\partial h_k}{\partial U} \frac {\partial h_t}{\partial h_k} \frac {\partial y_t}{\partial h_t}\frac {\partial J_t}{\partial y_t}\\\\
h_t = f(Uh_{t-1} + Wx_t+b)$$
其中,
$$
\frac {\partial h_t}{\partial h_k} = \prod_{i=k+1}^{t} \frac {\partial h_i}{\partial h_{i-1}} = \prod_{i=k+1}^t U^Tdiag[f^{\prime}(h_{i-1})]
$$

则J对U的梯度为:
$$
\frac {\partial J}{\partial U} = \sum_{t=1}^T \sum_{k=1}^t \frac {\partial h_k}{\partial U}(\prod_{i=k+1}^t U^T diag[f^{\prime}(h_{i-1})])\frac {\partial y_t}{\partial h_t}\frac {\partial J_t}{\partial y_t}
$$

3、损失J关于W的梯度计算

$$\frac {\partial J}{\partial W} = \frac {\partial}{\partial W}\sum_{t=1}^T J_t=\sum_{t=1}^T \frac {\partial J_t}{\partial W}=\sum_{t=1}^T \frac {\partial h_t}{\partial W} \frac {\partial J_t}{\partial h_t}$$

用链式法则可以得到:
$$\frac {\partial J}{\partial W}=\sum_{t=1}^T \sum_{k=1}^t \frac{\partial h_k}{\partial W}\frac{\partial h_t}{\partial h_k}\frac {\partial y_t}{\partial h_t} \frac {\partial J_t}{\partial y_t}\\\\
h_t = f(Uh_{t-1} + Wx_t+b)$$

其中,
$$
\frac {\partial h_t}{\partial h_k} = \prod_{i=k+1}^{t} \frac {\partial h_i}{\partial h_{i-1}} = \prod_{i=k+1}^t U^Tdiag[f^{\prime}(h_{i-1})]
$$
则,对W的梯度为:
$$
\frac {\partial J}{\partial W} = \sum_{t=1}^T\sum_{k=1}^t \frac {\partial h_k}{\partial W}(\prod_{i=k+1}^t U^Tdiag[f^{\prime}(h_{i-1})])\frac {\partial y_t}{\partial h_t}\frac {\partial J_t}{\partial y_t}
$$

如果定义$\gamma=||U^T diag(f^{\prime}(h_{i-1})||$,则在上面公式中的括号里面$\gamma^{t-k}$。如果$\gamma > 1$,则当$t-k \rightarrow \infty$时,$\gamma^{t-k} \rightarrow \infty$,会造成系统的不稳定,也就是所谓的梯度爆炸问题;相反,如果$\gamma < 1$,$t-k \rightarrow \infty$,$\gamma^{t-k} \rightarrow 0$,会出现和深度前馈神经网络类似的梯度消失的问题。

因此,虽然简单循环网络可从理论上可以建立长时间间隔的状态之间的依赖关系,但是由于梯度爆炸或消失的存在,实际上只能学习到短期的依赖关系,这就是所谓的长期依赖问题。

坚持原创技术分享,您的支持将鼓励我继续创作!