循环神经网络 (Recurrent Neural Networks, RNN) 是序列建模的主力,驱动了从机器翻译到文本生成的各种应用。提升其能力的一个常用策略是通过堆叠多个循环层来加深网络结构。这种堆叠方法很直观: 底层处理低级、快速变化的特征,高层则学习更抽象、变化缓慢的概念。在传统设计中,信息在层级结构中只向上流动。
但如果这种单向流动过于限制呢?如果高层的理解能够为低层提供关键的上下文会怎样?
想象一个正在写故事的网络: 高层可能在追踪整体情节要点 (角色正处于危险之中) ,而低层则在生成具体的词语。了解情节要点对于在字符层面选择正确的词汇 (“疯狂地”、“拼命地”) 将非常有帮助。
这就是 2015 年论文 Gated-Feedback Recurrent Neural Networks 的核心思想。研究人员提出了一种全新的架构——门控反馈 RNN (GF-RNN) ——它打破了堆叠式 RNN 中僵化的、仅向上的信息流。通过增加从高层返回低层的连接,并且——至关重要的是——将这些连接设计成可学习的门控,他们创造了一个更加动态且强大的模型,能够实时调整其内部信息流。
在本文中,我们将探讨 GF-RNN 的工作原理、它的优势,以及它在字符级语言建模甚至 Python 代码求值等挑战性任务中如何超越传统模型。
快速回顾 RNN
在深入了解 GF-RNN 之前,让我们先回顾一下 RNN 及其高级变体 LSTM 和 GRU 的基础知识。
RNN 一次处理序列中的一个时间步。在每个时间步 \(t\),它接收一个输入向量 \(\mathbf{x}_t\) 和前一时间步的隐藏状态 \(\mathbf{h}_{t-1}\),计算新的隐藏状态 \(\mathbf{h}_t\):
\[ \mathbf{h}_{t} = f\left(\mathbf{x}_{t}, \mathbf{h}_{t-1}\right) \]通常,\(f\) 是对 \(\mathbf{x}_t\) 和 \(\mathbf{h}_{t-1}\) 进行仿射变换,再经过非线性激活函数,如 tanh
:
这种循环结构让网络能够维持对过去信息的“记忆”。然而,标准 RNN 难以学习长期依赖关系,这是因为存在梯度消失问题——来自较久之前时间步的影响会逐渐减弱,变得难以捕捉。
门控 RNN: LSTM 和 GRU
为了解决上述问题,研究人员开发了带有门控机制的架构——其中最著名的是长短期记忆网络 (LSTM) 和门控循环单元 (GRU) 。这些门控让网络能够显式地控制记住、遗忘和输出哪些信息。
LSTM 的特色包括:
- 遗忘门 (\(f_t\)): 决定从细胞状态中丢弃哪些信息。
- 输入门 (\(i_t\)): 决定存储哪些新信息。
- 输出门 (\(o_t\)): 控制从细胞状态中输出哪些信息。
记忆单元的更新平衡了新旧信息:
\[ c_t^j = f_t^j c_{t-1}^j + i_t^j \tilde{c}_t^j \]GRU 则结构更精简,仅包含:
- 重置门 (\(r_t\)): 在创建新的候选状态时,控制遗忘多少过去的信息。
- 更新门 (\(z_t\)): 将旧的隐藏状态与新的候选状态融合。
GRU 的更新规则:
\[ h_t^j = (1 - z_t^j)h_{t-1}^j + z_t^j \tilde{h}_t^j \]LSTM 和 GRU 都比普通 RNN 更有效地处理长程依赖,也是 GF-RNN 的构建基础。
核心思想: 门控反馈连接
在传统的深度 RNN 中,堆叠层形成了一个层次结构: 在同一时间步,低层向高层提供信息,信息流仅向上。
GF-RNN 架构改变了这一点。如下图所示,它增加了从前一时间步 (\(t-1\)) 的所有层到当前时间步 (\(t\)) 的所有层的连接,从而实现了高层向低层的反馈连接。
图 1. 传统堆叠式 RNN (a) 与提出的门控反馈 RNN (b) 的视觉比较。圆点表示控制反馈连接的全局重置门。
使用全局重置门实现自适应反馈
简单地增加这些密集连接可能导致信息流混乱或冗余。GF-RNN 通过全局重置门解决这一问题,每个门控制跨时间步的一对层之间的连接。
门 \(g^{i \to j}\) 是一个介于 0 和 1 之间的标量:
- 0: 完全关闭连接。
- 1: 完全打开连接。
它在每个时间步动态计算:
\[ g^{i \to j} = \sigma \left( \mathbf{w}_g^{i \to j} \mathbf{h}_t^{j-1} + \mathbf{u}_g^{i \to j} \mathbf{h}_{t-1}^* \right) \]其中 \(\mathbf{h}_{t-1}^*\) 是来自 \(t-1\) 的所有隐藏状态,而 \(\mathbf{h}_t^{j-1}\) 是第 \(j\) 层的输入。
与不同 RNN 单元的结合
对于 tanh-RNN: 门控直接调节所有前一层对当前隐藏状态的贡献:
\[ \mathbf{h}_{t}^{j} = \tanh\left(W^{j-1 \to j}\mathbf{h}_{t}^{j-1} + \sum_{i=1}^{L} g^{i \to j} U^{i \to j}\mathbf{h}_{t-1}^{i}\right) \]对于 LSTM/GRU: 单元内部的门控 (遗忘门、输入门、重置门等) 保持不变。全局门控仅影响候选状态或候选记忆单元的计算。
LSTM 候选记忆:
\[ \tilde{\mathbf{c}}_t^j = \tanh\left(W_c^{j-1\to j}\mathbf{h}_t^{j-1} + \sum_{i=1}^L g^{i\to j}U_c^{i\to j}\mathbf{h}_{t-1}^i\right) \]GRU 候选状态:
\[ \tilde{\mathbf{h}}_t^j = \tanh\left(W^{j-1\to j}\mathbf{h}_t^{j-1} + \mathbf{r}_t^j \odot \sum_{i=1}^L g^{i\to j} U^{i\to j}\mathbf{h}_{t-1}^i\right) \]这种设计让 GF-RNN 能够学习在不同时间尺度上,高层上下文应在何时以及如何影响低层处理。
实验
作者在两个具有挑战性的序列任务上测试了 GF-RNN:
- 字符级语言建模 —— 在大型文本语料库 (Hutter Prize Wikipedia 数据集) 中预测下一个字符,用每字符比特数 (Bits-Per-Character, BPC) 来衡量。
- Python 程序求值 —— 将 Python 代码作为字符序列输入,预测其
print
语句的输出,用以测试逻辑和结构推理能力。
语言建模结果
使用 GRU 和 LSTM 单元的 GF-RNN,即使在参数数量相当的情况下,也优于单层和堆叠式 RNN。
表 2. 使用 GRU/LSTM 单元的 GF-RNN 达到了最低的 BPC。tanh-RNN 并未从该架构中受益。
GF-LSTM 获得了 1.842 BPC,而堆叠式 LSTM 为 1.868。更大的 GF-LSTM (每层单元数与堆叠式相同) 达到了 1.789 BPC。
训练效率也有所提升:
图 2. GF-RNN 收敛更快,且 BPC 更低。
门控效果
将所有全局重置门固定为 1 (始终打开) 会使 GF-LSTM 的性能下降至 1.854 BPC——虽然仍优于堆叠式 LSTM,但比完整的 GF-LSTM 差——这证明了自适应门控的必要性。
定性分析: 文本生成
使用 Wikipedia XML 标记作为种子进行文本生成显示,GF-LSTM 成功闭合了 XML 标签 (</username>
、</contributor>
) ,而堆叠式 LSTM 常常失败。
表 3. 得益于自上而下的上下文反馈,GF-LSTM 更好地捕捉了标记结构。
大型 5 层 GF-LSTM 实现了 1.58 BPC,当时的最新最佳结果:
表 4. 大型 GF-LSTM 超越了此前的最佳结果。
Python 程序求值结果
难度通过嵌套深度和目标输出长度控制。GF-RNN 在所有复杂度下均优于堆叠式 RNN。
图 3. GF-RNN 在最复杂的程序上表现提升最显著。
差距图 (c, f) 显示,在深度嵌套或长输出的情况下——即长程推理最重要的场景中——性能提升最大。
结论与启示
GF-RNN 对深度 RNN 架构进行了强有力的改进:
- 自上而下的反馈很强大 —— 高层能用关键的上下文指导低层,从而提升复杂序列建模能力。
- 自适应门控是关键 —— 全局重置门让网络能够动态学习最优信息流。
- 效率更高 —— 在相同容量下,GF-RNN 训练更快,效果更佳。
- 可扩展性优势明显 —— 在具备长期依赖的复杂任务中,性能提升尤为显著。
该架构通过让网络学习内部连接模式,打破了堆叠式 RNN 僵化的层次结构。结果是: 模型可以动态调整结构以适应数据,表明灵活的通信渠道能够显著提高神经网络在困难的长程推理任务中的能力。