了解LSTM网络(英文博客汉化)
Understanding LSTM Networks-了解LSTM网络
原文来自于大神Cristopher Colah于2015年在Github上发布的一篇博客, 窃以为此文不失为一篇入门神经网络的经典文章, 遂产生了汉化的想法, 附原文链接Understanding LSTM Networks
什么是RNN
人类不会时时刻刻都从头开始思考。譬如当你读到这篇文章时, 由于思路具有持续性, 你对于文章中每个词的理解, 都建立在对前文理解的基础之上, 而不是每看见一个词就抛开一切重新开始。
传统的神经网络无法体现这种持续性, 这似乎是传统神经网络的一个主要缺陷。举个例子, 假设你要为一部电影中每个时间点发生的事情进行分类, 这时传统的神经网络结构便难以根据影片中的前序事件推断出下一刻会发生什么。
循环神经网络(Recurrent Neural Network, 简称RNN)的出现解决了这一问题, 由于网络内部存在循环结构, 因此信息可以在网络中持续存在。
如上图所示, RNN的结构包含一块神经网络\(A\), 输入量\(x_{t}\)和输出量\(h_{t}\)组成, 网络中的循环结构允许信息从上一周期传播到下一周期。
这种循环结构使得RNN看起来有些玄学。但是细想一下就会发现, RNN的本质结构其实和传统的神经网络没有太大区别。我们不妨将RNN内部的循环结构展开, 看看会发生什么。
如上图所示, RNN可以被看作是多个基础模块的叠加, 在 \(t\) 时刻,输入变量 \(x_{t}\) , 通过 RNN 的基础模块 A , 输出 \(h_{t}\) , 而\(t\)时刻的信息, 将会传递到下一个时刻 \(t+1\)。
这种链式法则表明RNN与序列结构或列表结构存在密切的联系, 这类结构是RNN的最佳使用场景。毫无疑问, 将RNN用于处理序列数据正是业界的主流做法,例如语音识别、语言模型、翻译、图片标题等任务。事实表明RNN在这些领域的应用都取得了较大成功, 关于RNN的应用可以参考另一位大佬Andrej Karpathy的博客文章The Unreasonable Effectiveness of Recurrent Neural Networks, 文章中针对RNN及其应用给出了详细的说明, 这里不再赘述。
RNN的缺点-长时序依赖问题
前面讲过, RNN的一大特点是在网络中引入了时序特性, 譬如当使用RNN读取视频时, 它或许能够根据视频中的信息推断出下一帧的事件。如果RNN能够做到这一点, 那么它将非常有用。
然而RNN能否像我们期望的那样完全解决数据中的时序依赖问题呢? 事实是存疑的。
有时候,我们只需知道近期的历史信息即可执行任务。例如,我们有一个语言模型, 它基于先前的词来预测下一个词。如果我们试着预测“the clouds are in the sky”这句话最后的词“sky”,这时无需更多的上下文信息,因为很显然下一个词应该是sky。在这样的场景中,相关的信息和预测的词位置之间的间隔是非常小的,RNN可以学会使用先前的信息。
但有时也需要更多的上下文才能完成预测任务, 假如我们要预测“I grew up in France… I speak fluent French.”这句话中的最后一个词“French”, 邻近的前文信息会表明这里应该是某种语言的名称, 但我们需要从更远的位置获取更多的上下文信息, 才能确定这里究竟是哪种语言。
在某些情况下, 预测点和上下文提示的距离有可能会非常远。不幸的是, 当这个距离不断增大时, RNN会逐渐丧失学习前文信息的能力。Hochreiter (1991)与Bengio, et al. (1994)揭漏了RNN难以处理长序列问题的本质原因, 即梯度消失。
神经网络会根据输出与期望值的误差大小和方向来更新网络中各节点的权值, 使误差在迭代中逐渐减小,这样的过程称之为反向传播。所谓梯度, 就是用于更新节点权重的一个值
(新权重=旧权重-学习率*梯度), 梯度会随着时间的推移不断减小, 当梯度的值变得非常小时, 神经网络的节点权重便会停止更新, 学习过程也将中断。
RNN的一个重要变体是长短期记忆网络(Long Short Term Memory networks, 简称LSTM), 它的出现就是为了解决RNN在处理长序列任务时出现的梯度消失问题。
什么是LSTM
长短期记忆网络, 一般被简称为LSTM, 它是一种特殊的RNN。由Hochreiter&Schmidhuber于1997年提出, 并在随后被广泛应用。
LSTM从结构上解决了长时序依赖的问题, 换言之, 长时间记忆信息是LSTM结构自带的特性, 无需学习即可获得!
所有的RNN都可以被表示为下图所示的链状形式, 这个问题我们之前提到过。普通RNN的链状形式中, 神经网络模块 \(A\) 具有较为简单的形式, 以单层 \(\tanh\) 为例:
LSTM也可以表示与之类似的链状形式, 不同的是, LSTM内部的神经网络模块 \(A\) 更加复杂, 由四个神经网络层组成, 且彼此之间以一种特殊的方式进行交互。
这里暂时无需在意模块的内部细节, 关于LSTM的机理我们后面会逐步给出解释。在此之前, 我们先对后续需要用到的一些图示给出说明。
- Neural Network Layer: 黄色矩形表示神经网络层, 其本质是函数, 输入\(x\),经过变换\(Wx+b\)和激活函数\(f\),得到输出\(y=f(Wx+b)\), 区别在于\(W\)和\(b\)可以通过学习进行调整, 称为反向传播
- Pointwise Operation: 粉色圆圈表示逐点运算符, 含义是将两个相同大小的数组中, 处于相同位置的元素进行运算的一种操作, 如向量的加减法
- Vector Transfer: 黑色箭头表示数据流向, 每条箭头都带有一个完整的向量, 按箭头指向在网络内部流动
- Concatenate: 箭头汇聚处表示合并, 可以理解成将两个数组连接成一个更长的数组
- Copy: 箭头分叉处表示拷贝, 即将同一份数据复制后分发至不同位置
激活函数
本节不是原文内容, 系笔者自行补充, 仅作为了解LSTM机理的前置知识
LSTM中的\(\sigma\)表示 sigmoid 函数, 与上面的双曲正切\(\tanh\)同属于激活函数的范畴, 更多信息请参考激活函数。
tanh 函数的作用在于“限流”, 将流经神经网络的值始终限定在-1和1之间
sigmoid 函数的作用则在于“筛选”, 它的值域在0到1之间, 有助于更新或忘记信息
其实从这里我们已经可以窥见深度学习网络“搭积木”的本质了, 就是将具有特定功能的函数(预制件)通过串/并联形成模块, 再将多个模块相连就能搭出一个比较复杂的模型了
莫名想到了乐高(笑)
LSTM的核心思想
LSTM的关键在于模块\(A\)的状态, 称为细胞状态(cell state), 记作\(C_{t}\), 如下图所示, 用一条贯穿图上方的水平线来表达细胞状态的更新
通过精心设计的“门”结构, LSTM有能力向细胞状态中添加或移除信息。“门”是一种允许信息选择性通过的的通道, 由一个 sigmoid 函数和一个逐点乘法运算符构成
Sigmoid 层输出 0 到 1 之间的数字,值为 0 表示“不让任何东西通过”,而值为 1 表示“让所有东西通过”(因为任何数乘0都为0,乘1等于自身,乘一个0到1之间的数会变小)
LSTM 有三个这样的门,用于保护和控制单元状态,作用相当于在记忆力有限的情况下,记住主要的,忘记次要的。
逐步理解LSTM
LSTM的第一步需要决定在当前周期内忘记什么信息, 这一步骤由一个被称为“忘记门”的 sigmoid 层组成。忘记门会读取上一周期的历史信息\(h_{t-1}\)和当前输入\(x_{t}\), 做一个Sigmoid 的非线性映射,然后输出一个向量\(f_{t}\)(该向量每一个维度的值都在0到1之间), 这样当返回值趋近1时, 表示保持当前状态, 当返回值趋近0时, 表示忘记当前状态。
回到我们之前提到的语言模型的例子, 试着基于前文的输入来预测下一个词。文本由多句话组成, 每句话都有一个主语, 细胞状态可能包含着当前主语的性别, 因此我们可以选出正确的代词。而当我们看到一个新的主语时, 我们就要忘记旧主语的性别。
在确定了哪些旧信息可以被忘记后, 下一步需要确定哪些新信息应当被储存到细胞状态中。这一过程分两步来实现, 首先使用一个被称作“输入门”的 sigmoid 层来确定哪些值需要更新, 得到向量\(i_{t}\), 再使用 tanh 层创建一个候选值向量\(\tilde{C}_{t}\)。
在前文给出的语言模型的例子中, 我们希望向细胞状态中添加新主语的性别, 从而替换掉旧主语的性别信息。这时将遗忘门的输出向量\(f_{t}\)与\(C_{t-1}\)相乘, 表示状态更新时需要忘掉的信息, 再加上\(i_{t}*\tilde{C_{t}}\)表示状态更新时所需的新信息。
在语言模型的案例中, 我们就是根据上面的步骤, 向细胞状态中添加新主语的性别信息, 并替换掉旧主语信息的。
最后, 我们需要确定输出值, 这个输出值取决于我们的细胞状态, 但这个状态是一个由激活函数“过滤”后的版本。
首先使用一个被称为“输出门” sigmoid 层确定细胞状态中哪些部分可以输出, 接着将细胞状态\(C_{t}\)经由 tanh 映射得到一个介于-1和1之间的值, 并将它和 sigmoid 层的输出\(o_{t}\)相乘, 以确定最终输出的那部分值。
还是以前面的语言模型为例, 由于它刚刚看到一个主语,因此它可能希望输出与动词相关的信息。例如,人称代词可能是单数,也可能是复数,对于后面的动词来说,我们也知道动词需要进行的词形变化,进而输出信息。
公式写了一堆, 我们究竟如何用大白话来理解“长短期记忆”呢?笔者认为, 我们可以用上课听讲来理解。对于RNN来说, 它只具备“听讲”的能力, 而LSTM相比RNN多了一项“记笔记”的能力。常言道“好记性不如烂笔头”, 所以LSTM能够避免RNN长时序依赖的缺陷(听过的知识点过一段时间会遗忘, 记笔记印象才能更深刻), 出院!
LSTM的变体
目前为止我们讨论的都是常规的LSTM结构, 但并不是所有的LSTM都遵循这种惯例。事实上, 几乎每一篇文章中所涉及到的LSTM都会对结构做一些细微的调整。这些调整微乎其微, 但是其中的一些变体也值得一提。
Gers&Schmidhuber提出了一种流行的LSTM变体, 这种变体在LSTM中增加了一种名为“猫眼”的结构。因此这种LSTM在状态更新时, 三个门(遗忘门、输入门、输出门)不仅可以接收上一周期的历史信息\(h_{t-1}\)和当前输入\(x_{t}\), 还可以结合上一周期的细胞状态\(C_{t-1}\)来更新, 进一步解决了长时序依赖的问题。
LSTM的另一种变体是将遗忘门和输入门进行整合, 传统LSTM的遗忘门和输入门是两个独立的结构, 分别决定哪些信息被遗忘, 哪些信息被新增。而在这一变体结构中, 我们使用一个统一的结构来同时完成这两件事。
LSTM有一个改动较大的变体结构, 称为门控循环单元(Gated Recurrent Unit, GRU), 由Cho et al.(2014)提出, 它将遗忘门和输入门整合在一起, 称为“更新门”, 并且整合了细胞状态和隐藏状态, 还做了其他一些改动。GRU的这些调整简化了LSTM的结构, 也是一种非常流行的变体
以上这些例子只是一小部分, 除此之外LSTM的变体还有很多, 例如Yao et al.(2015)提出的深度门控RNN。除LSTM以外, 也有一些学者采用其他的结构来解决RNN的长时序依赖问题, 例如Koutnik et al.(2014)提出的Clockwork RNNs。