LSTM与GRU数学推导
一、
RNN 的关键点之一就是他们可以用来连接先前的信息到当前的任务上,例如使用过去的视频段来推测对当前段的理解。如果 RNN 可以做到这个,他们就变得非常有用。但是真的可以么?答案是,还有很多依赖因素。
有时候,我们仅仅需要知道先前的信息来执行当前的任务。例如,我们有一个语言模型用来基于先前的词来预测下一个词。如果我们试着预测 “the clouds are in the sky” 最后的词,我们并不需要任何其他的上下文 —— 因此下一个词很显然就应该是 sky。在这样的场景中,相关的信息和预测的词位置之间的间隔是非常小的,RNN 可以学会使用先前的信息。
![](https://img.haomeiwen.com/i5756726/3734ee488cdcbfc3.png)
但是同样会有一些更加复杂的场景。假设我们试着去预测“I grew up in France... I speak fluent French”最后的词。当前的信息建议下一个词可能是一种语言的名字,但是如果我们需要弄清楚是什么语言,我们是需要先前提到的离当前位置很远的 France 的上下文的。这说明相关信息和当前预测位置之间的间隔就肯定变得相当的大。
不幸的是,在这个间隔不断增大时,RNN 会丧失学习到连接如此远的信息的能力。
![](https://img.haomeiwen.com/i5756726/9e16f27a421b3f8f.png)
在理论上,RNN 绝对可以处理这样的 长期依赖 问题。人们可以仔细挑选参数来解决这类问题中的最初级形式,但在实践中,RNN 肯定不能够成功学习到这些知识。Bengio, et al. (1994)等人对该问题进行了深入的研究,他们发现一些使训练 RNN 变得非常困难的相当根本的原因。
然而,幸运的是,LSTM 并没有这个问题!
LSTM 网络
Long Short Term 网络—— 一般就叫做 LSTM ——是一种 RNN 特殊的类型,可以学习长期依赖信息。LSTM 由Hochreiter & Schmidhuber (1997)提出,并在近期被Alex Graves进行了改良和推广。在很多问题,LSTM 都取得相当巨大的成功,并得到了广泛的使用。
LSTM 通过刻意的设计来避免长期依赖问题。记住长期的信息在实践中是 LSTM 的默认行为,而非需要付出很大代价才能获得的能力!
所有 RNN 都具有一种重复神经网络模块的链式的形式。在标准的 RNN 中,这个重复的模块只有一个非常简单的结构,例如一个 tanh 层。
![](https://img.haomeiwen.com/i5756726/b4559bf76193107e.png)
LSTM 同样是这样的结构,但是重复的模块拥有一个不同的结构。不同于 单一神经网络层,这里是有四个,以一种非常特殊的方式进行交互。
![](https://img.haomeiwen.com/i5756726/27725bb8f08d334d.png)
不必担心这里的细节。我们会一步一步地剖析 LSTM 解析图。现在,我们先来熟悉一下图中使用的各种元素的图标。
![](https://img.haomeiwen.com/i5756726/e46cd31da40bbfe2.png)
在上面的图例中,每一条黑线传输着一整个向量,从一个节点的输出到其他节点的输入。粉色的圈代表 pointwise 的操作,诸如向量的和,而黄色的矩阵就是学习到的神经网络层。合在一起的线表示向量的连接,分开的线表示内容被复制,然后分发到不同的位置。
LSTM 的核心思想
LSTM 的关键就是细胞状态,水平线在图上方贯穿运行。
细胞状态类似于传送带。直接在整个链上运行,只有一些少量的线性交互。信息在上面流传保持不变会很容易。
![](https://img.haomeiwen.com/i5756726/fb0f5ff7342ea2ed.png)
LSTM 有通过精心设计的称作为“门”的结构来去除或者增加信息到细胞状态的能力。门是一种让信息选择式通过的方法。他们包含一个 sigmoid 神经网络层和一个 pointwise 乘法操作。
![](https://img.haomeiwen.com/i5756726/ff9276f24d7305db.png)
Sigmoid 层输出 0 到 1 之间的数值,描述每个部分有多少量可以通过。0 代表“不许任何量通过”,1 就指“允许任意量通过”!
LSTM 拥有三个门,来保护和控制细胞状态。
逐步理解 LSTM
在我们 LSTM 中的第一步是决定我们会从细胞状态中丢弃什么信息。这个决定通过一个称为忘记门层完成。该门会读取h_{t-1}和x_t,输出一个在 0 到 1 之间的数值给每个在细胞状态C_{t-1}中的数字。1 表示“完全保留”,0 表示“完全舍弃”。
让我们回到语言模型的例子中来基于已经看到的预测下一个词。在这个问题中,细胞状态可能包含当前主语的性别,因此正确的代词可以被选择出来。当我们看到新的主语,我们希望忘记旧的主语。
![](https://img.haomeiwen.com/i5756726/376f32cd1fbd7c4a.png)
下一步是确定什么样的新信息被存放在细胞状态中。这里包含两个部分。第一,sigmoid 层称 “输入门层” 决定什么值我们将要更新。然后,一个 tanh 层创建一个新的候选值向量,\tilde{C}_t,会被加入到状态中。下一步,我们会讲这两个信息来产生对状态的更新。
在我们语言模型的例子中,我们希望增加新的主语的性别到细胞状态中,来替代旧的需要忘记的主语。
![](https://img.haomeiwen.com/i5756726/85188816a2d09417.png)
现在是更新旧细胞状态的时间了,C_{t-1}更新为C_t。前面的步骤已经决定了将会做什么,我们现在就是实际去完成。
我们把旧状态与f_t相乘,丢弃掉我们确定需要丢弃的信息。接着加上i_t * \tilde{C}_t。这就是新的候选值,根据我们决定更新每个状态的程度进行变化。
在语言模型的例子中,这就是我们实际根据前面确定的目标,丢弃旧代词的性别信息并添加新的信息的地方。
![](https://img.haomeiwen.com/i5756726/cb52b11d3122ed73.png)
最终,我们需要确定输出什么值。这个输出将会基于我们的细胞状态,但是也是一个过滤后的版本。首先,我们运行一个 sigmoid 层来确定细胞状态的哪个部分将输出出去。接着,我们把细胞状态通过 tanh 进行处理(得到一个在 -1 到 1 之间的值)并将它和 sigmoid 门的输出相乘,最终我们仅仅会输出我们确定输出的那部分。
在语言模型的例子中,因为他就看到了一个 代词,可能需要输出与一个 动词 相关的信息。例如,可能输出是否代词是单数还是负数,这样如果是动词的话,我们也知道动词需要进行的词形变化。
![](https://img.haomeiwen.com/i5756726/1418eaf2cf0d5dac.png)
LSTM 的变体
我们到目前为止都还在介绍正常的 LSTM。但是不是所有的 LSTM 都长成一个样子的。实际上,几乎所有包含 LSTM 的论文都采用了微小的变体。差异非常小,但是也值得拿出来讲一下。
其中一个流形的 LSTM 变体,就是由 Gers & Schmidhuber (2000) 提出的,增加了 “peephole connection”。是说,我们让 门层 也会接受细胞状态的输入。
![](https://img.haomeiwen.com/i5756726/503496c049ccb0f3.png)
上面的图例中,我们增加了 peephole 到每个门上,但是许多论文会加入部分的 peephole 而非所有都加。
另一个变体是通过使用 coupled 忘记和输入门。不同于之前是分开确定什么忘记和需要添加什么新的信息,这里是一同做出决定。我们仅仅会当我们将要输入在当前位置时忘记。我们仅仅输入新的值到那些我们已经忘记旧的信息的那些状态 。
![](https://img.haomeiwen.com/i5756726/45c0d934c43ac57f.png)
另一个改动较大的变体是 Gated Recurrent Unit (GRU),这是由 Cho, et al. (2014) 提出。它将忘记门和输入门合成了一个单一的 更新门。同样还混合了细胞状态和隐藏状态,和其他一些改动。最终的模型比标准的 LSTM 模型要简单,也是非常流行的变体。
![](https://img.haomeiwen.com/i5756726/65b21be5c425f36f.png)
这里只是部分流行的 LSTM 变体。当然还有很多其他的,如Yao, et al. (2015) 提出的 Depth Gated RNN。还有用一些完全不同的观点来解决长期依赖的问题,如Koutnik, et al. (2014) 提出的 Clockwork RNN。
要问哪个变体是最好的?其中的差异性真的重要吗?Greff, et al. (2015) 给出了流行变体的比较,结论是他们基本上是一样的。Jozefowicz, et al. (2015) 则在超过 1 万种 RNN 架构上进行了测试,发现一些架构在某些任务上也取得了比 LSTM 更好的结果。
![](https://img.haomeiwen.com/i5756726/0619bc2f5bbc1e33.png)
结论
刚开始,我提到通过 RNN 得到重要的结果。本质上所有这些都可以使用 LSTM 完成。对于大多数任务确实展示了更好的性能!
由于 LSTM 一般是通过一系列的方程表示的,使得 LSTM 有一点令人费解。然而本文中一步一步地解释让这种困惑消除了不少。
LSTM 是我们在 RNN 中获得的重要成功。很自然地,我们也会考虑:哪里会有更加重大的突破呢?在研究人员间普遍的观点是:“Yes! 下一步已经有了——那就是注意力!” 这个想法是让 RNN 的每一步都从更加大的信息集中挑选信息。例如,如果你使用 RNN 来产生一个图片的描述,可能会选择图片的一个部分,根据这部分信息来产生输出的词。实际上,Xu,et al.(2015)已经这么做了——如果你希望深入探索注意力可能这就是一个有趣的起点!还有一些使用注意力的相当振奋人心的研究成果,看起来有更多的东西亟待探索……
注意力也不是 RNN 研究领域中唯一的发展方向。例如,Kalchbrenner,et al.(2015) 提出的 Grid LSTM 看起来也是很有前途。使用生成模型的 RNN,诸如Gregor,et al.(2015) Chung,et al.(2015) 和 Bayer & Osendorfer (2015) 提出的模型同样很有趣。在过去几年中,RNN 的研究已经相当的燃,而研究成果当然也会更加丰富!
二、
1. rnn 结构的BPTT学习算法存在的问题
先看一下比较典型的BPTT一个展开的结构,如下图,这里只考虑了部分图,因为其他部分不是这里要讨论的内容。
对于t时刻的误差信号计算如下:
这样权值的更新方式如下:
上面的公式在BPTT中是非常常见的了,那么如果这个误差信号一直往过去传呢,假设任意两个节点u, v他们的关系是下面这样的:
那么误差传递信号的关系可以写成如下的递归式:
n表示图中一层神经元的个数,这个递归式的大概含义不难理解,要求t-q时刻误差信号对t时刻误差信号的偏导,就先求出t-q+1时刻对t时刻的,然后把求出来的结果传到t-q时刻,递归停止条件是q = 1时,就是刚开始写的那部分计算公式了。将上面的递归式展开后可以得到:
论文里面说的是可以通过归纳来证明,我没仔细推敲这里了,把里面连乘展开看容易明白一点:
整个结果式对T求和的次数是n^(q-1), 即T有n^(q-1)项,那么下面看问题出在哪儿。
如果|T| > 1, 误差就会随着q的增大而呈指数增长,那么网络的参数更新会引起非常大的震荡。
如果|T| < 1, 误差就会消失,导致学习无效,一般激活函数用simoid函数,它的倒数最大值是0.25, 权值最大值要小于4才能保证不会小于1。
误差呈指数增长的现象比较少,误差消失在BPTT中很常见。在原论文中还有更详细的数学分析,但是了解到此个人觉的已经足够理解问题所在了。
2.最初的 LSTM 结构
为了克服误差消失的问题,需要做一些限制,先假设仅仅只有一个神经元与自己连接,简图如下:
根据上面的,t时刻的误差信号计算如下:
为了使误差不产生变化,可以强制令下式为1:
根据这个式子,可以得到:
这表示激活函数是线性的,常常的令fj(x) = x, wjj = 1.0,这样就获得常数误差流了,也叫做CEC。
但是光是这样是不行的,因为存在输入输出处权值更新的冲突(这里原论文里面的解释我不是很明白),所以加上了两道控制门,分别是input gate, output gate,来解决这个矛盾,图如下:
图中增加了两个控制门,所谓控制的意思就是计算cec的输入之前,乘以input gate的输出,计算cec的输出时,将其结果乘以output gate的输出,整个方框叫做block, 中间的小圆圈是CEC, 里面是一条y = x的直线表示该神经元的激活函数是线性的,自连接的权重为1.0
3.增加forget gate
最初lstm结构的一个缺点就是cec的状态值可能会一直增大下去,增加forget gate后,可以对cec的状态进行控制,它的结构如下图:
这里的相当于自连接权重不再是1.0,而是一个动态的值,这个动态值是forget gate的输出值,它可以控制cec的状态值,在必要时使之为0,即忘记作用,为1时和原来的结构一样。
4.增加Peephole的LSTM结构
上面增加遗忘门一个缺点是当前CEC的状态不能影响到input gate, forget gate在下一时刻的输出,所以增加了Peephole connections。结构如下:
这里的gate的输入部分就多加了一个来源了,forget gate, input gate的输入来源增加了cec前一时刻的输出,output gate的输入来源增加了cec当前时刻的输出,另外计算的顺序也必须保证如下:
1. input gate, forget gate的输入输出
2. cell的输入
3. output gate的输入输出
4. cell的输出(这里也是block的输出)
5. 一个LSTM的FULL BPTT推导(用误差信号)
我记得当时看论文公式推导的时候很多地方比较难理解,最后随便谷歌了几下,找到一个写的不错的类似课件的PDF,但是已经不知道出处了,很容易就看懂LSTM的前向计算,误差反传更新了。把其中关于LSTM的部分放上来,首先网络的完整结构图如下:
这个结构也是rwthlm源码包中LSTM的结构,下面看一下公式的记号:
-- wij表示从神经元i到j的连接权重(注意这和很多论文的表示是反着的)
-- 神经元的输入用a表示,输出用b表示
-- 下标 ι, φ 和 ω分别表示input gate, forget gate,output gate
-- c下标表示cell,从cell到 input, forget和output gate的peephole权重分别记做 wcι , wcφ and wcω
-- Sc表示cell c的状态
-- 控制门的激活函数用f表示,g,h分别表示cell的输入输出激活函数
-- I表示输入层的神经元的个数,K是输出层的神经元个数,H是隐层cell的个数
前向的计算:
误差反传更新:
此外,还有GRU结构同样是解决RNN的缺点,这里将LSTM和GRU进行对比。
LSTM与GRU:
1) LSTM:
2)GRU:
3)概括的来说,LSTM和GRU都能通过各种Gate将重要特征保留,保证其在long-term 传播的时候也不会被丢失;还有一个不太好理解,作用就是有利于BP的时候不容易vanishing:
3.实验结果:
实验用了三个unit,传统的tanh,以及LSTM和GRU:
可以发现LSTM和GRU的差别并不大,但是都比tanh要明显好很多,所以在选择LSTM或者GRU的时候还要看具体的task data是什么, 不过在收敛时间和需要的epoch上,GRU应该要更胜一筹:
相关博客和教程:
https://zybuluo.com/hanbingtao/note/581764
http://www.jianshu.com/p/9dc9f41f0b29
http://www.csdn.net/article/2015-06-05/2824880
http://blog.csdn.net/zdy0_2004/article/details/49977423
http://blog.csdn.net/a635661820/article/details/45390671
http://deeplearning.net/tutorial/lstm.html
https://www.zhihu.com/question/29411132
原文参考:http://www.cnblogs.com/taojake-ML/p/6272605.html