Understanding LSTM Networks

理解长短期记忆网络

原文发表于 2015 年 8 月 27 日 · Christopher Olah

Recurrent Neural Networks

人类不会每一秒都从头开始思考。当你阅读这篇文章时,你对每个词的理解都建立在对前面词语的理解之上。你不会丢弃已有的一切认知,从零开始重新思考——你的思维具有持续性

传统神经网络做不到这一点,这似乎是一个重大缺陷。例如,假设你想对一部电影中每个时刻发生的事件进行分类,传统神经网络很难利用对电影前面事件的推理来帮助理解后面的事件。

循环神经网络(Recurrent Neural Networks)解决了这个问题。它们是带有循环的网络,允许信息持续存在。

A h_t x_t h_t

循环神经网络具有循环结构

在上图中,一个神经网络模块 \(A\) 接收输入 \(x_t\) 并输出 \(h_t\)。循环结构允许信息从网络的一个步骤传递到下一个步骤。

这些循环让循环神经网络看起来有些神秘。然而,仔细想想就会发现,它们与普通的神经网络并没有本质区别。可以将循环神经网络看作同一个网络的多个副本,每个副本将消息传递给下一个。看看展开循环后会是什么样子:

... A x_{t-1} h_{t-1} A x_t h_t A x_{t+1} h_{t+1} ...

展开的循环神经网络

这种链状结构揭示了循环神经网络与序列和列表的密切关系。它们是处理此类数据的天然架构。

近年来,RNN 在各种问题上取得了令人难以置信的成功:语音识别、语言建模、翻译、图像标注……而这些成功的关键在于使用了"LSTM"——一种非常特殊的循环神经网络,在许多任务上表现远优于标准版本。几乎所有基于循环神经网络的令人兴奋的成果都是通过 LSTM 实现的。本文将深入探讨 LSTM。

The Problem of Long-Term Dependencies

RNN 的一个吸引力在于,它们或许能够将先前的信息与当前任务联系起来。如果 RNN 能做到这一点,它们将非常有用。但事实如何?这取决于具体情况。

有时候,我们只需要查看最近的信息就能完成当前任务。例如,一个语言模型试图根据前面的词预测下一个词。如果我们要预测 "the clouds are in the ___" 的最后一个词,不需要更多上下文——很明显下一个词应该是 "sky"。在相关信息与需要它的地方之间的距离很小时,RNN 可以学会使用过去的信息。

thecloudsareinthe___ 相关信息距离近

当相关信息距离较近时,RNN 能正常学习

但在另一些情况下,我们需要更多上下文。考虑预测文本 "I grew up in France… I speak fluent ___" 的最后一个词。最近的信息暗示下一个词可能是某种语言的名称,但要确定具体是哪种语言,我们需要更早的 "France" 这个上下文。相关信息与需要使用它的位置之间的距离可能变得非常大。

不幸的是,随着距离的增长,RNN 变得无法学习如何连接这些信息。

Igrewupin France Ispeakfluent ___ 距离太远,信息难以传递

神经网络难以处理长期依赖

理论上,RNN 完全有能力处理这类"长期依赖"。人类可以精心挑选参数来解决这种形式的简单问题。但遗憾的是,在实践中,RNN 似乎无法学习到这些关系。Hochreiter (1991)Bengio, et al. (1994) 深入探讨了这个问题,并发现了一些相当根本的原因。

幸运的是,LSTM 没有这个问题!

LSTM Networks

长短期记忆网络(Long Short Term Memory networks)——通常简称为"LSTM"——是一种特殊的 RNN,能够学习长期依赖关系。它们由 Hochreiter & Schmidhuber (1997) 提出,并在后续工作中被许多人改进和推广。LSTM 在大量问题上表现出色,现已被广泛使用。

LSTM 被明确设计来避免长期依赖问题。长时间记住信息实际上是它们的默认行为,而不是它们需要努力学习的东西!

所有循环神经网络都有链式重复模块的形式。在标准 RNN 中,这个重复模块的结构非常简单,例如只有一个 tanh 层。

重复模块 tanh h_{t-1} h_t x_t

标准 RNN 的重复模块只包含一个 tanh 层

LSTM 也具有这种链式结构,但重复模块的内部结构不同。它不是只有一个神经网络层,而是有四个,并以一种非常特殊的方式交互。

LSTM 重复模块 C_{t-1} C_t σ σ tanh σ × + × tanh × h_{t-1} x_t h_t 遗忘门 输入门 候选值 输出门

LSTM 的重复模块包含四个交互层

神经网络层 Sigmoid 层 × 逐元素乘法 + 逐元素加法

在上图中,每条线传递一个完整的向量,从一个节点的输出到另一个节点的输入。粉色圆角矩形是 sigmoid 层,黄色方块是学习的神经网络层。线的合并表示向量拼接,线的分叉表示内容被复制并送往不同位置。

The Core Idea Behind LSTMs

LSTM 的关键是细胞状态(cell state),即图的顶部那条水平线。

细胞状态有点像传送带。它沿着整个链条直线运行,只有少量线性交互。信息可以很容易地沿着它不变地流动。

× + C_{t-1} C_t 细胞状态 —— 信息的传送带

LSTM 通过被称为"门"(gates)的结构来精心调控细胞状态,具备添加或移除信息的能力。

门是一种选择性让信息通过的方式。它们由一个 sigmoid 神经网络层和一个逐元素乘法操作组成。

sigmoid 层输出 0 到 1 之间的数值,描述每个组件应该让多少信息通过。0 表示"完全不让通过",1 表示"全部让通过"。

一个 LSTM 有三个这样的门来保护和控制细胞状态。

Step-by-Step LSTM Walk Through

1 遗忘门(Forget Gate)

LSTM 的第一步是决定从细胞状态中丢弃什么信息。这个决定由一个被称为"遗忘门层"的 sigmoid 层做出。它查看 \(h_{t-1}\) 和 \(x_t\),对细胞状态 \(C_{t-1}\) 中的每个数字输出一个 0 到 1 之间的值。1 表示"完全保留",0 表示"完全丢弃"。

$$ f_t = \sigma(W_f \cdot [h_{t-1}, x_t] + b_f) $$
C_{t-1} × σ h_{t-1} x_t f_t

遗忘门:决定从细胞状态中丢弃什么信息

回到语言模型的例子:细胞状态可能包含当前主语的性别信息,以便使用正确的代词。当我们看到新的主语时,就希望遗忘旧主语的性别。

2 输入门(Input Gate)

下一步是决定在细胞状态中存储什么新信息。这分两部分:首先,一个被称为"输入门层"的 sigmoid 层决定要更新哪些值;然后,一个 tanh 层创建一个新的候选值向量 \(\tilde{C}_t\),可以被添加到状态中。接下来,我们将这两者结合起来进行状态更新。

$$ i_t = \sigma(W_i \cdot [h_{t-1}, x_t] + b_i) $$ $$ \tilde{C}_t = \tanh(W_C \cdot [h_{t-1}, x_t] + b_C) $$
+ × σ i_t tanh C̃_t h_{t-1}, x_t

输入门:决定存储什么新信息

在语言模型的例子中,我们希望将新主语的性别添加到细胞状态中,以替换我们正在遗忘的旧信息。

3 更新细胞状态

现在是将旧细胞状态 \(C_{t-1}\) 更新为新细胞状态 \(C_t\) 的时候了。前面的步骤已经决定了该做什么,我们只需要执行。

我们将旧状态乘以 \(f_t\),遗忘之前决定要遗忘的内容。然后加上 \(i_t \ast \tilde{C}_t\),这是新的候选值,按我们决定的更新程度进行缩放。

$$ C_t = f_t \ast C_{t-1} + i_t \ast \tilde{C}_t $$
C_{t-1} × f_t + i_t * C̃_t C_t

细胞状态更新:遗忘旧信息,加入新信息

4 输出门(Output Gate)

最后,我们需要决定要输出什么。输出将基于细胞状态,但经过过滤。首先,运行一个 sigmoid 层来决定输出细胞状态的哪些部分。然后,将细胞状态通过 tanh(将值压缩到 -1 和 1 之间),再乘以 sigmoid 门的输出,这样我们只输出决定要输出的部分。

$$ o_t = \sigma(W_o \cdot [h_{t-1}, x_t] + b_o) $$ $$ h_t = o_t \ast \tanh(C_t) $$
C_t tanh × σ o_t h_{t-1}, x_t h_t

输出门:基于细胞状态生成过滤后的输出

在语言模型的例子中,由于刚看到了一个主语,可能需要输出与动词相关的信息。例如,它可能输出主语是单数还是复数,以便确定动词的正确形式。

Variants on Long Short Term Memory

到目前为止描述的是一个相当标准的 LSTM。但并非所有 LSTM 都相同。事实上,几乎每篇涉及 LSTM 的论文都使用了略有不同的版本。差异不大,但值得一提。

窥视孔连接(Peephole Connections)

Gers & Schmidhuber (2000) 引入的一个流行变体是添加"窥视孔连接"。这意味着让门层也能看到细胞状态。

$$ f_t = \sigma(W_f \cdot [C_{t-1}, h_{t-1}, x_t] + b_f) $$ $$ i_t = \sigma(W_i \cdot [C_{t-1}, h_{t-1}, x_t] + b_i) $$ $$ o_t = \sigma(W_o \cdot [C_t, h_{t-1}, x_t] + b_o) $$

上面的公式对所有门添加了窥视孔,但很多论文只对部分门添加。

耦合遗忘门和输入门

另一种变体是使用耦合的遗忘门和输入门。不再分别决定遗忘什么和添加什么新信息,而是将这些决定放在一起做出。我们只在要输入新内容时才遗忘旧内容,只在遗忘旧内容时才输入新值。

$$ C_t = f_t \ast C_{t-1} + (1 - f_t) \ast \tilde{C}_t $$

门控循环单元(GRU)

一个更显著的变体是由 Cho, et al. (2014) 引入的门控循环单元(Gated Recurrent Unit, GRU)。它将遗忘门和输入门合并为一个"更新门",还合并了细胞状态和隐藏状态,并做了其他一些改变。最终模型比标准 LSTM 更简洁,并且越来越流行。

$$ z_t = \sigma(W_z \cdot [h_{t-1}, x_t]) $$ $$ r_t = \sigma(W_r \cdot [h_{t-1}, x_t]) $$ $$ \tilde{h}_t = \tanh(W \cdot [r_t \ast h_{t-1}, x_t]) $$ $$ h_t = (1 - z_t) \ast h_{t-1} + z_t \ast \tilde{h}_t $$
GRU 单元 h_{t-1} σ z_t σ r_t tanh × 1-z_t × z_t + h_t x_t

GRU:合并了遗忘门和输入门的简化结构

这些只是最著名的几种 LSTM 变体。还有很多其他的,例如 Yao, et al. (2015) 的 Depth Gated RNNs,以及完全不同的处理长期依赖的方法,如 Koutnik, et al. (2014) 的 Clockwork RNNs。

哪种变体最好?这些差异重要吗?Greff, et al. (2015) 对流行的变体做了很好的比较,发现它们的表现基本相同。Jozefowicz, et al. (2015) 测试了超过一万种 RNN 架构,发现有些在某些任务上优于 LSTM。

Conclusion

前面提到了人们用 RNN 取得的非凡成果。基本上所有这些成果都是通过 LSTM 实现的。对于大多数任务来说,它们确实好用得多!

写成一组方程式时,LSTM 看起来相当令人生畏。希望通过这篇文章的逐步讲解,能让它们变得更加平易近人。

LSTM 是我们用 RNN 所能完成之事的一大进步。很自然会问:还有下一个大的飞跃吗?研究者们普遍认为:"有!下一步就是注意力机制(Attention)!" 其核心思想是让 RNN 的每一步都从更大的信息集合中挑选要关注的内容。例如,如果用 RNN 生成图像描述,它可能会针对输出的每个词选择图像的一个部分来关注。事实上,Xu, et al. (2015) 正是这样做的——如果你想探索注意力机制,这是一个有趣的起点!

注意力机制并不是 RNN 研究中唯一令人兴奋的方向。例如,Kalchbrenner, et al. (2015) 的 Grid LSTMs 看起来非常有前途。在生成模型中使用 RNN 的工作——如 Gregor, et al. (2015)Chung, et al. (2015) 或 Bayer & Osendorfer (2015) ——也非常有趣。

过去几年对于循环神经网络来说是一段激动人心的时期,而未来只会更加精彩!

核心要点总结

1

RNN 通过循环结构让信息持续存在,适合处理序列数据

2

标准 RNN 存在长期依赖问题,难以学习远距离信息

3

LSTM 通过细胞状态门控机制解决了长期依赖问题

4

三个门——遗忘门、输入门、输出门——协同控制信息流

5

GRU 是 LSTM 的简化变体,合并了部分门和状态

6

注意力机制是 LSTM 之后的下一个重要突破

References

本文内容翻译整理自 Christopher Olah 的博客文章,原文链接:

Understanding LSTM Networks — colah's blog

除原作者外,许多人对现代 LSTM 做出了贡献。一个不完整的名单包括:Felix Gers、Fred Cummins、Santiago Fernandez、Justin Bayer、Daan Wierstra、Julian Togelius、Faustino Gomez、Matteo Gagliolo 和 Alex Graves。