循环神经网络(RNN)
循环神经网络属于前馈神经网络的一个子集,可以接受(时间)序列数据作为输入
A wellknown result by Siegelman and Sontag from 1991 demonstrated that
a nite sized recurrent neural network with sigmoidal activation
functions can simulate a universal Turing machine
循环神经网络可以学习到序列间的依赖关系。常规监督学习方法,如支持向量机,基于树的方法,前馈神经网络等都是非常有效的方法。但是这些方法也通常基于输入数据间的独立性假设,因此对于序列间的关系无能为力。
直观的讲,这种循环结构可以“记忆”先前输入的信息,并将它们保存在state中,最终影响网络的输出。
马尔科夫链虽然也能够学习依赖关系,但是相比DL有以下缺点
- 设计DL时一般不会为每个节点定义特别的意义,训练结束后通过可视化的方法才可能看出某些节点的特征;而PGM的节点一般要精心设计
- HMM假设t时刻的隐状态至于t-1时刻的隐状态有关,尽管可以通过每个时间点t之间的叉积来构造新的状态空间,但是这个状态空间的维度会随着上下文关系(context window)呈指数级增长。这使得HMM不适合学习长距离的依赖关系。
而相较HMM,RNN - RNN的隐状态节点可能包含了任意长度序列间的信息。即使假设每个节点只取1/0,设隐层有n个节点,则这个隐层可以表示的状态有2^n种。
RNN的结构
RNN的结构初看让人一头雾水,但是只要展开就很好理解
[图片上传失败...(image-bf3779-1531903263115)]
unfolding
[图片上传失败...(image-2c7572-1531903263115)]
or
[图片上传失败...(image-386829-1531903263115)]
以一个包含了一个隐藏层的RNN为例
h^t=\sigma\left ( W_{hx}x+W_{hh}h^{t-1}+b_h \right )\cdot\cdot\cdot时刻t隐藏层的计算
\hat{y}^{\left ( t \right )} = softmax\left ( W_{yh}h^t +b_y \right )\cdot\cdot\cdot输出层的计算
其他的一些结构
如Jordan network(1986)
[图片上传失败...(image-902d23-1531903263115)]
如 ELman network described in finding structure in Time(1990)
[图片上传失败...(image-90a53b-1531903263115)]
RNN的训练
RNN的微分的计算可以通过backpropagation through time (BPTT)来计算
Forward Pass
前向过程,对于t时刻的隐层的h个结点,它的输入来源有两个,一个是t时刻的输入,另一个是t-1时刻的历史信息
符号约定: 有一个长度为T的序列\left ( x^1,x^2,...x^T \right),每个向量的维度为I,隐层有H个结点。x^t_i表示网络t时刻的输入向量x^t的第i个结点的值。输出层有K个结点。x^t_i表示网络t时刻的输入向量x^t的第i个结点的值,a^t_j和b^t_j分别表示t时刻网络某一层第j个结点的净输入(激活前的值)和激活值。这里用不同的下标区分不同的层:i特指输入层,h特指当前时刻的隐层,{h}'特指前一时刻或者后一时刻的隐层,k特指输出层。用w_{ih},w_{h{h}'},w_{hk}分别表示输入层到隐层,隐层到隐层,隐层到输入层的权重。
[图片上传失败...(image-60932f-1531903263115)]
a^t_h = \sum_{I}^{i=1}w_{ih}x^t_i+\sum_{{h}'=1}^{H}w_{{h}'h}b_{{h}'}^{t-1}.......(1)
b^t_h = \theta \left ( a^t_h \right )......(2)
a^t_k = \sum_{h=1}^{H}w_{hk}b_h^t......(3)
L = -\sum_{t=1}^{T}\sum_{k=1}^{K}w_{hk}z^t_klny^t_k......(4)
Bakcward Pass
从t=T开始到t=0,与传统的反向传播类似,逐层计算梯度
输出层的error signal为
接着考虑隐藏层 w_{ih},w_{h'h}
首先要计算损失函数对于各个隐层的一度,这里分为两种情况,如下图a,b
[图片上传失败...(image-8b938d-1531903263115)]
对于情况a,T时刻的隐层误差来自于最后一个输出层
\delta ^t_k = \frac{\partial L}{\partial a^t_k} ......(5)
则对于W_{hk}的梯度为(这里的b^t_h参考等式2,不是值bias)
\frac{\partial L}{\partial w_{hk}} = \sum_{t=1}^{T}\frac{\partial L}{\partial a^t_k}\frac{\partial a^t_k}{\partial w_{hk}}=\sum_{t=1}^{T}\delta ^t_kb^t_h......(6)
\frac{\partial L}{\partial a^T_h} = \frac{\partial L}{\partial b^T_h}\frac{\partial b^T_h}{\partial a^T_h} = \frac{\partial b^T_h}{\partial a^T_h}\sum_{k=1}^{K}\frac{\partial L }{\partial a^T_k}\frac{\partial a^T_k}{\partial b^T_h} = {\theta}'\left ( a^T_h \right )\sum_{k=1}^{K}\delta ^T_kw_{hk}......(7)
对于情况b,误差不仅来自输出层,还来自于下一时刻的隐层,所以\delta ^t_h定义为如下
\delta ^t_h = \frac{\partial L}{\partial a^t_h}......(8)
\frac{\partial L}{\partial a^T_h} = \frac{\partial b^T_h}{\partial a^T_h}\sum_{k=1}^{K}\frac{\partial L }{\partial a^T_k}\frac{\partial a^T_k}{\partial b^T_h} + \frac{\partial b^T_h}{\partial a^T_h}\sum_{{h}'=1}^{H}\frac{\partial L }{\partial a^{t+1}_{{h}'}}\frac{\partial a^{t+1}_{{h}'}}{\partial b^t_n}
={\theta }'\left ( a^t_h \right )\left ( \sum_{k-1}^{K} \delta ^t_kw_{hk} +{\color{Red} \sum_{{h}'=1}^{H}\delta^{t+1}_{{h}'}w_{h{h}'} } \right )......(9)
求得\delta ^t_h后,w_{ih}和w_{h{h}'} 就容易得出
\frac{\partial L}{\partial w_{ih}} = \sum_{t=1}^{T}\frac{\partial L}{\partial a^t_h}\frac{\partial a^t_h}{\partial w_{ih}}= \sum_{t=1}^{T}\delta^t_hx^t_i ......(10)
\frac{\partial L}{\partial w_{h{h}'}} = \sum_{t=1}^{T}\frac{\partial L}{\partial a^t_h}\frac{\partial a^t_h}{\partial w_{h{h}'}}=\sum_{t=1}^{T}\delta ^t_hb^{t-1}_{{h}'}......(11)
信息失真和梯度消失(或爆炸)
假设用RNN来模拟一个复杂的模型,即拥有非常长的输入序列。假设我们用这个RNN来模拟整个世界的进程,假设这个世界的每一刻的状态,通过时间这个非常复杂的循环函数,都在被前一刻的时间所影响。这时如果改变过去几百年的事情,会对现在的世界发生什么影响呢。假设当初爱因斯坦没有发现相对论,那么可能会对十九世纪50年代会产生很大的影响,但是后来又有其他物理学家发现了相对论,那么这个变化带来的影响会在二十世纪初就不那么明显了,可能到了2050年,这个变化对世界的影响已经微乎其微,只是在这期间对世界的变化造成了一些波动。
在这个例子中,过去某一时刻的状态的变化可能会在循环函数中像滚雪球一样越滚越大,也有可能在循环中渐渐消失。但是显然世界的运行方式要比RNN复杂的多。在RNN中在我们企图学习非常长的序列依赖关系时,RNN对过去时刻的变化要么非常敏感(梯度爆炸),要么极度的不敏感(梯度消失)。这导致了在学习过程中
导致发生这些问题的主要原因有以下两点。
信息的变形
首先,如果信息在传递过程中不断的变形,那么当我们在当前时刻需要过去某时刻的信息时,可能很难再找回并且加以利用。
很容易证明RNN中发生了信息的变形,假设RNN在没有外部输入的情况下,能完整的在循环中保存信息。那么状态的变换方程F\left ( x \right ) = \phi \left ( Ws_{t-1}+b \right )应该是一个恒等变换,但是恒等变换应该是一个线性函数,而F(x)是非线性的。所以这与我们的假设矛盾。梯度消失或者爆炸 RNN使用反向传播来计算梯度,梯度的爆炸会使得我们无法训练模型,而梯度消失会导致我们无法学到长时间的依赖关系,因为bp会对序列最近的变换非常敏感,早期的变化的影响微乎其微。
梯度消失的证明:
RNN隐层的梯度计算公式为
\frac{\partial L}{\partial a^T_h} ={\theta }'\left ( a^t_h \right )\left ({\color{Red} \sum_{{h}'=1}^{H}\delta^{t+1}_{{h}'}w_{h{h}'} } \right )......(12)
为了简化,我们先不考虑输入,只看隐层的更新
现在另t=1,对\theta^1_h展开
[图片上传失败...(image-492d23-1531903263115)]
=......
=\sum_{h_2=1}^{H}\cdot \cdot \cdot \sum_{h^T=1}^{H}\left (\prod_{m=1}^{T-1} {\theta}'\left ( a^m_{hm} \right )w_{{h_m}{h_{m+1}}}\right )...(14)
所以等式里有T个{\theta}'w形式的连成,那么当T越大的时候,会出现以下两种情况:
\begin{cases} & \text{ if } {\left |{\theta}'w \right | >1.0}\cdot \cdot \cdot \cdot \cdot \cdot \delta^t_h\rightarrow \infty \\ & \text{ if } \left |{\theta}'w \right | >1.0\cdot \cdot \cdot \cdot \cdot \cdot \delta^t_h\rightarrow 0 \end{cases}