RNN 循环神经网络(下):长期依赖的挑战与长短期记忆

对 LSTM 和 GRU 的简单介绍

Posted by Xiaosheng on June 26, 2017

本文内容摘取自 《Deep Learning》,部分内容有修改。向辛勤翻译本书的 Exacity 团队致敬。

1. 长期依赖的挑战

长期依赖

在前馈网络或循环网络中,当计算图变得极深时,神经网络优化算法会面临的一个难题就是长期依赖问题——由于变深的结构使模型丧失了学习到先前信息的能力,让优化变得极其困难。因为循环网络要在很长时间序列的各个时刻重复应用相同操作来构建非常深的计算图,并且模型参数共享,这使问题更加凸显。

例如,假设某个计算图中包含一条反复与矩阵 $\boldsymbol{W}$ 相乘的路径,那么 $t$ 步后,相当于乘以 $\boldsymbol{W}^t$ 。假设 $\boldsymbol{W}$ 有特征值分解 $\boldsymbol{W} = \boldsymbol{V}\text{diag}(\boldsymbol{\lambda})\boldsymbol{V}^{−1}$。在这种简单的情况下,很容易看出:

当特征值 $\lambda_i$ 不在 $1$ 附近时,若在量级上大于 $1$ 则会爆炸;若小于 $1$ 时则会消失。 梯度消失与爆炸问题(vanishing and exploding gradient problem)是指该计算图上的梯度也会因为 $\text{diag}(\boldsymbol{\lambda})^t$ 大幅度变化。梯度消失使得我们难以知道参数朝哪个方向移动能够改进代价函数,而梯度爆炸会使得学习不稳定。

此处描述的在各时间步重复与 $\boldsymbol{W}$ 相乘非常类似于寻求矩阵 $\boldsymbol{W}$ 的最大特征值及对应特征向量的幂方法(power method)。从这个观点来看,$\boldsymbol{x}^\top \boldsymbol{W}^t$ 最终会丢弃 $\boldsymbol{x}$ 中所有与 $\boldsymbol{W}$ 的主特征向量正交的成分。

循环网络在各时间步上使用相同的矩阵 $\boldsymbol{W}$,而前馈网络并没有。因而即使是非常深层的前馈网络也能一定程度上避免梯度消失与爆炸问题。

长期依赖的挑战

正如之前所说,在学习循环网络的过程中,长期依赖面临着挑战。其根本问题是,经过许多阶段传播后的梯度倾向于消失(大部分情况)或爆炸(很少,但对优化过程影响很大)。即使我们假设循环网络是参数稳定的(可存储记忆,且梯度不爆炸),但长期依赖的困难来自比短期相互作用指数小的权重(涉及许多 $\text{Jacobian}$ 相乘)。

循环网络涉及相同函数的多次组合,每个时间步一次,这些组合可以导致极端非线性行为,如下图所示。

1

当组合许多非线性函数(如这里所示的线性 $\tanh$ 层)时,结果是高度非线性的,通常大多数值与微小的导数相关联,也有一些具有大导数的值,以及在增加和减小之间的多次交替。此处,我们绘制从 $100$ 维隐藏状态降到单个维度的线性投影,绘制于 $y$ 轴上。$x$ 轴是 $100$ 维空间中沿着随机方向的初始状态的坐标。因此,我们可以将该图视为高维函数的线性截面。曲线显示每个时间步之后的函数,或者等价地,转换函数被组合一定次数之后。

特别地,循环神经网络所使用的函数组合有点像矩阵乘法。我们可以认为,循环联系:

是一个非常简单的、缺少非线性激活函数和输入 $\boldsymbol{x}$ 的循环神经网络。如长期依赖中描述的那样,这种递推关系本质上描述了幂法。它可以被简化为:

而当 $\boldsymbol{W}$ 符合下列形式的特征分解:

其中 $\boldsymbol{Q}$ 正交,循环性可进一步简化为:

特征值提升到 $t$ 次后,导致幅值不到一的特征值衰减到零,而幅值大于一的就会激增。任何不与最大特征向量对齐的 $\boldsymbol{h}^{(0)}$ 的部分将最终被丢弃。

有人可能会希望通过简单地停留在梯度不消失或爆炸的参数空间来避免这个问题。不幸的是,为了储存记忆并对小扰动具有鲁棒性,$\text{RNN}$ 必须进入参数空间中的梯度消失区域。具体来说,每当模型能够表示长期依赖时,长期相互作用的梯度幅值就会变得指数小(相比短期相互作用的梯度幅值)。这并不意味着这是不可能学习的,由于长期依赖关系的信号很容易被短期相关性产生的最小波动隐藏,因而学习长期依赖可能需要很长的时间。实验表明,当我们增加了需要捕获的依赖关系的跨度, 基于梯度的优化变得越来越困难,$\text{SGD}$ 在长度仅为 $10$ 或 $20$ 的序列上成功训练传统 $\text{RNN}$ 的概率迅速变为 $0$。

2. 渗漏单元和其他多时间尺度的策略

处理长期依赖的一种方法是设计工作在多个时间尺度的模型,使模型的某些部分在细粒度时间尺度上操作并能处理小细节,而其他部分在粗时间尺度上操作并能把遥远过去的信息更有效地传递过来。

时间维度的跳跃连接

增加从遥远过去的变量到目前变量的直接连接是得到粗时间尺度的一种方法。在普通的循环网络中,循环从时刻 $t$ 的单元连接到时刻 $t + 1$ 单元。

正如之前所说,梯度可能关于时间步数呈指数消失或爆炸。有人引入了 $d$ 延时的循环连接以减轻这个问题。现在导数指数减小的速度与 $\frac{\tau}{d}$ 相关而不是 $\tau$。既然同时存在延迟和单步连接,梯度仍可能成 $t$ 指数爆炸。这允许学习算法捕获更长的依赖性,但不是所有的长期依赖都能在这种方式下良好地表示。

渗漏单元和一系列不同时间尺度

获得导数乘积接近 $1$ 的另一方式是设置线性自连接单元,并且这些连接的权重接近 $1$。

我们对某些 $v$ 值应用更新 $\mu^{(t)} \leftarrow \alpha \mu^{(t−1)} + (1-\alpha)v^{(t)}$ 累积一个滑动平均值 $\mu^{(t)}$, 其中 $\alpha$ 是一个从 $\mu^{(t−1)}$ 到 $\mu^{(t)}$ 线性自连接的例子。当 $\alpha$ 接近 $1$ 时,滑动平均值能记住过去很长一段时间的信息,而当 $\alpha$ 接近 $0$,关于过去的信息被迅速丢弃。线性自连接的隐藏单元可以模拟滑动平均的行为,这种隐藏单元称为渗漏单元(leaky unit)

$d$ 时间步的跳跃连接可以确保单元总能被先前的 $d$ 个时间步值影响。使用权重接近 $1$ 的线性自连接是确保该单元可以访问过去值的不同方式。线性自连接通过调节实值 $\alpha$ 更平滑灵活地调整这种效果,而不是调整整数值的跳跃长度。

我们可以通过两种基本策略设置渗漏单元使用的时间常数。一种策略是手动将其固定为常数,例如在初始化时从某些分布采样它们的值。另一种策略是使时间常数成为自由变量,并学习出来。在不同时间尺度使用这样的渗漏单元似乎能帮助学习长期依赖。

删除连接

处理长期依赖另一种方法是在多个时间尺度组织 $\text{RNN}$ 状态的想法,信息在较慢的时间尺度上更容易长距离流动。

这个想法与之前讨论的时间维度上的跳跃连接不同,因为它涉及主动删除长度为一的连接并用更长的连接替换它们。以这种方式修改的单元被迫在长时间尺度上运作。收到这种新连接的单元,可以学习在长时间尺度上运作,但也可以选择专注于自己其他的短期连接。

强制一组循环单元在不同时间尺度上运作有不同的方式。一种选择是使循环单元变成渗漏单元,但不同的单元组关联不同的固定时间尺度。另一种选择是使显式且离散的更新发生在不同的时间,不同的单元组有不同的频率。

3. 长短期记忆和其他门控RNN

目前实际应用中最有效的序列模型称为门控 RNN(gated RNN)。 包括基于长短期记忆(long short-term memory, LSTM)和基于门控循环单元(gated recurrent unit)的网络。

像渗漏单元一样,门控 $\text{RNN}$ 想法也是基于生成通过时间的路径,其中导数既不消失也不发生爆炸。渗漏单元通过手动选择常量的连接权重或参数化的连接权重来达到这一目的。门控 $\text{RNN}$ 将其推广为在每个时间步都可能改变的连接权重。

渗漏单元允许网络在较长持续时间内积累信息(诸如用于特定特征或类的线索)。然而,一旦该信息被使用,让神经网络遗忘旧的状态可能是有用的。例如,如果一个序列是由子序列组成,我们希望渗漏单元能在各子序列内积累线索,我们需要将状态设置为 $0$ 以忘记旧状态的的机制。我们希望神经网络学会决定何时清除状态,而不是手动决定,这就是门控 $\text{RNN}$ 要做的事。

LSTM

引入自循环的巧妙构思,以产生梯度长时间持续流动的路径是初始长短期记忆(long short-term memory, LSTM)模型的核心贡献。其中一个关键扩展是使自循环的权重视上下文而定,而不是固定的。门控此自循环(由另一个隐藏单元控制)的权重,累积的时间尺度可以动态地改变。在这种情况下,即使是具有固定参数的 $\text{LSTM}$,累积的时间尺度也可以因输入序列而改变,因为时间常数是模型本身的输出。

$\text{LSTM}$ 已经在许多应用中取得重大成功,如无约束手写识别、语音识别、手写识别、机器翻译、为图像生成标题和解析。

$\text{LSTM}$ 块如下图所示:

2

上图为 $\text{LSTM}$ 循环网络“细胞”的框图。细胞彼此循环连接,代替一般循环网络中普通的隐藏单元。这里使用常规的人工神经元计算输入特征。如果 $\text{sigmoid}$ 输入门允许,它的值可以累加到状态。状态单元具有线性自循环,其权重由遗忘门控制。细胞的输出可以被输出门关闭。所有门控单元都具有 $\text{sigmoid}$ 非线性,而输入单元可具有任意的压缩非线性。状态单元也可以用作门控单元的额外输入。黑色方块表示单个时间步的延迟。

$\text{LSTM}$ 循环网络除了外部的 $\text{RNN}$ 循环外, 还具有内部的“$\text{LSTM}$ 细胞”循环(自环),因此 $\text{LSTM}$ 不是简单地向输入和循环单元的仿射变换之后施加一个逐元素的非线性。与普通的循环网络类似,每个单元有相同的输入和输出,但也有更多的参数和控制信息流动的门控单元系统。最重要的组成部分是状态单元 $s_i^{(t)}$,与前一节讨论的渗漏单元有类似的线性自环。然而,此处自环的权重(或相关联的时间常数)由遗忘门(forget gate) $f_i^{(t)}$ 控制(时刻 $t$ 和细胞 $i$),由 $\text{sigmoid}$ 单元将权重设置为 $0$ 和 $1$ 之间的值:

其中 $\boldsymbol{x}^{(t)}$ 是当前输入向量,$\boldsymbol{h}^t$ 是当前隐藏层向量,$\boldsymbol{h}^t$ 包含所有 $\text{LSTM}$ 细胞的输出。$\boldsymbol{b}^f , \boldsymbol{U}^f , \boldsymbol{W}^f$ 分别是偏置、输入权重和遗忘门的循环权重。因此 $\text{LSTM}$ 细胞内部状态以如下方式更新,其中有一个条件的自环权重 $f_i^{(t)}$:

其中 $\boldsymbol{b}, \boldsymbol{U}, \boldsymbol{W}$ 分别是 $\text{LSTM}$ 细胞中的偏置、输入权重和遗忘门的循环权重。外部输入门(external input gate) 单元 $g_i^{(t)}$ 以类似遗忘门(使用 $\text{sigmoid}$ 获得一个 $0$ 和 $1$ 之间的值)的方式更新,但有自身的参数:

$\text{LSTM}$ 细胞的输出 $h_i^{(t)}$ 也可以由输出门(output gate) $q_i^{(t)}$ 关闭(使用 $\text{sigmoid}$ 单元作为门控):

其中 $\boldsymbol{b}^o , \boldsymbol{U}^o , \boldsymbol{W}^o$ 分别是偏置、输入权重和遗忘门的循环权重。在这些变体中,可以选择使用细胞状态 $s_i^{(t)}$ 作为额外的输入(及其权重),输入到第 $i$ 个单元的三个门, 如上图所示。这将需要三个额外的参数。

$\text{LSTM}$ 网络比简单的循环架构更易于学习长期依赖,目前各种 $\text{LSTM}$ 的变体和替代也已经被研究和使用。

其他门控 RNN

$\text{LSTM}$ 架构中哪些部分是真正必须的?还可以设计哪些其他成功架构允许网络动态地控制时间尺度和不同单元的遗忘行为?

最近关于门控 $\text{RNN}$ 的工作给出了这些问题的某些答案,其单元也被称为门控循环单元或 $\text{GRU}$。与 $\text{LSTM}$ 的主要区别是,单个门控单元同时控制遗忘因子和更新状态单元的决定。更新公式如下:

其中 $\boldsymbol{u}$ 代表“更新”门,r 表示 ‘‘复位’’ 门。它们的值就如通常所定义的:

复位和更新门能独立地“忽略”状态向量的一部分。更新门像条件渗漏累积器一样可以线性门控任意维度,从而选择将它复制(在 $\text{sigmoid}$ 的一个极端)或完全由新的“目标状态”值(朝向渗漏累积器的收敛方向)替换并完全忽略它(在另一个极端)。 复位门控制当前状态中哪些部分用于计算下一个目标状态,在过去状态和未来状态之间引入了附加的非线性效应。

围绕这一主题可以设计更多的变种。例如复位门(或遗忘门)的输出可以在多个隐藏单元间共享。或者,全局门的乘积(覆盖一整组的单元,例如整一层)和一个局部门(每单元)可用于结合全局控制和局部控制。然而,一些调查发现这些 $\text{LSTM}$ 和 $\text{GRU}$ 架构的变种,在广泛的任务中难以明显地同时击败这两个原始架构。

本文内容摘取自 《Deep Learning》,部分内容有修改。向辛勤翻译本书的 Exacity 团队致敬。