Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

14.1 循环神经网络

循环神经网络(recurrent neural network,RNN)是指网络连接中包含环路的任何网络,也就是说,某个单元的值直接或间接地依赖于它自己更早的输出,并将该输出作为输入。这类网络虽然功能强大,却很难推理和训练。不过,在循环网络这一大类中,有一些受约束的架构在语言任务上已被证明极其有效。本节考察一类称为 Elman 网络(Elman, 1990)或简单循环网络的循环网络。这些网络本身很有用,也构成了本章后面讨论的更复杂方法(如长短期记忆网络,Long Short-Term Memory,LSTM)的基础。在本章中,RNN 一词特指这些更简单、约束更多的网络(尽管你经常会看到 RNN 被用来指代所有具有循环性质的网络,包括 LSTM)。

图 14.1 展示了 RNN 的结构。与普通前馈网络一样,表示当前输入的输入向量 xt\mathbf{x}_t 会乘以权重矩阵,然后通过非线性激活函数,以计算隐藏单元层的值。随后利用该隐藏层计算相应的输出 yt\mathbf{y}_t。不同于前面基于窗口的方法,序列是通过每次向网络呈现一个元素来处理的。我们用下标表示时间,因此 xt\mathbf{x}_t 表示时间 tt 的输入向量。RNN 与前馈网络的关键区别在于图中虚线所示的循环连接。该连接把前一时刻隐藏层的值加入隐藏层计算的输入中。

图 14.1 Elman(1990)提出的简单循环神经网络。隐藏层将循环连接作为其输入的一部分。也就是说,隐藏层的激活值既取决于当前输入,也取决于前一个时间步隐藏层的激活值。

前一个时间步的隐藏层提供了一种记忆或上下文,其中编码了较早的处理结果,并为之后时刻要做出的决策提供信息。关键在于,这种方法没有对先前上下文施加固定长度限制;前一隐藏层所包含的上下文可以包括一直追溯到序列开头的信息。

加入时间维度后,RNN 看起来似乎比非循环架构复杂。但实际上,它们并没有那么不同。给定一个输入向量和前一时间步隐藏层的值,我们仍然是在执行第 6 章介绍的标准前馈计算。图 14.2 阐明了循环的性质以及它如何参与隐藏层的计算。最重要的变化在于新增了一组权重 UU,用于把前一时间步的隐藏层连接到当前隐藏层。这些权重决定了网络在计算当前输入的输出时如何利用过去的上下文。与网络中的其他权重一样,这些连接也通过反向传播进行训练。

图 14.2 将简单循环神经网络表示为前馈网络。先前时间步的隐藏层 ht1\mathbf{h}_{t-1} 乘以权重矩阵 UU,然后加到当前时间步的前馈部分上。

14.1.1 RNN 中的推理

RNN 中的前向推理(把输入序列映射为输出序列)与前馈网络中的过程几乎完全相同。为了根据输入 xt\mathbf{x}_t 计算输出 yt\mathbf{y}_t,我们需要隐藏层 ht\mathbf{h}_t 的激活值。为此,将输入 xt\mathbf{x}_t 与权重矩阵 WW 相乘,将前一时间步的隐藏层 ht1\mathbf{h}_{t-1} 与权重矩阵 UU 相乘,把两者相加后通过合适的激活函数 gg,得到当前隐藏层的激活值 ht\mathbf{h}_t。得到隐藏层的值后,再按照通常的计算过程生成输出向量。

ht=g(Uht1+Wxt)(14.1)\mathbf {h} _ {t} = g \left(\mathbf {U h} _ {t - 1} + \mathbf {W x} _ {t}\right)\tag{14.1}
yt=f(Vht)(14.2)\mathbf {y} _ {t} = f (\mathbf {V h} _ {t})\tag{14.2}

分别将输入层、隐藏层和输出层的维度记为 dind_{in}dhd_hdoutd_{out}。于是,三个参数矩阵为:WRdh×din\boldsymbol{\mathsf{W}} \in \mathbb{R}^{d_h \times d_{in}}URdh×dh\boldsymbol{\mathsf{U}} \in \mathbb{R}^{d_h \times d_h}VRdout×dh\mathbf{V} \in \mathbb{R}^{d_{out} \times d_h}

我们通过 softmax 计算 yt\mathbf{y}_t,从而得到关于可能输出类别的概率分布。

yt=softmax(Vht)(14.3)\mathbf {y} _ {t} = \operatorname{softmax} (\mathbf {V h} _ {t})\tag{14.3}

由于时间 tt 的计算需要时间 t1t-1 的隐藏层值,因此推理算法必须从序列开头逐步进行到结尾,如图 14.3 所示。将网络沿时间展开,如图 14.4 所示,也可以看出简单循环网络的序列性质。在该图中,每个时间步都复制了不同的单元层,以说明它们的值会随时间变化;但各个权重矩阵在不同时间步之间共享。

图 14.3 简单循环网络中的前向推理。矩阵 UUVVWW 在不同时间步之间共享,而每个时间步都会计算新的 hhyy 值。

14.1.2 训练

与前馈网络一样,我们使用训练集、损失函数和反向传播来获得调整这些循环网络权重所需的梯度。如图 14.2 所示,现在需要更新三组权重:WW 是从输入层到隐藏层的权重,UU 是从前一隐藏层到当前隐藏层的权重,最后 VV 是从隐藏层到输出层的权重。

图 14.4 突出了两个在前馈网络反向传播中无需考虑的问题。第一,为了计算时间 tt 输出的损失函数,我们需要时间 t1t-1 的隐藏层。第二,时间 tt 的隐藏层既影响时间 tt 的输出,也影响时间 t+1t+1 的隐藏层(因而还影响 t+1t+1 时刻的输出和损失)。因此,要评估 hth_t 所产生的误差,就需要知道它对当前输出以及所有后续输出的影响。

图 14.4 沿时间展开的简单循环神经网络。网络层在每个时间步重新计算,而权重 UUVVWW 在所有时间步之间共享。

针对这种情况调整反向传播算法,就得到一个用于训练 RNN 权重的两遍算法。第一遍执行前向推理,计算 hth_tyty_t,累加每个时间步的损失,并保存每一步的隐藏层值,供下一个时间步使用。第二遍反向处理序列,边处理边计算所需的梯度,同时计算并保存每一步隐藏层的误差项,以便沿时间向后传递。这种一般方法通常称为随时间反向传播(backpropagation through time,BPTT)(Werbos, 1974;Rumelhart et al., 1986;Werbos, 1990)。

幸运的是,借助现代计算框架和充足的计算资源,无需采用专门的方法来训练 RNN。如图 14.4 所示,将循环网络显式展开为前馈计算图后,所有显式循环都会消失,网络权重就可以直接训练。在这种方法中,我们提供一个模板,指定网络的基本结构,包括输入层、输出层和隐藏层所需的全部参数、权重矩阵,以及要使用的激活函数和输出函数。随后,给定一个具体输入序列,就能生成针对该输入的展开式前馈网络,并使用普通反向传播进行前向推理或训练。

对于语音识别、字符级处理或连续流式输入等涉及更长输入序列的应用,展开整个输入序列可能并不可行。这时,可以将输入展开为若干可管理的固定长度片段,并把每个片段视为独立的训练样本。