第 3 天 · dropout 只加在层间,不加在时间方向
一句话
直接给 RNN 加 dropout 会破坏记忆,效果反而变差。这篇短论文只在层与层之间的非循环连接上加 dropout,时间方向的循环连接保持原样。这个改动让大 LSTM 可以放心加大:Penn Treebank 测试困惑度从无正则小模型的 114.5 降到 78.4。
论文讲了什么
问题。2014 年,dropout 已是前馈网络和卷积网络的标准正则化方法。但大家发现,它用在 RNN 上效果不好。结果是 RNN 只能用小模型,模型一大就过拟合。作者的目标很具体:让大 LSTM 也能用 dropout。
原因。假设在循环连接 h_{t-1} → h_t 上每一步都随机丢弃单元。噪声会随时间步累积。序列越长,记忆被破坏的次数越多,网络很难长时间保存信息。
方法。把多层 LSTM 的连接分成 2 类:
- 循环连接(recurrent connection):同一层内,从时间步
t-1到t。不加 dropout。 - 非循环连接(non-recurrent connection):同一时间步内,从第
l-1层到第l层。输入嵌入到第 1 层、最后一层到 softmax 也属于这一类。加 dropout。
写成公式:第 l 层在时间步 t 的下层输入从 h_t^{l-1} 改为 D(h_t^{l-1}),其中 D 是 dropout 算子。上一时间步的 h_{t-1}^l 原样输入。这样,一条信息从输入流到输出,不管跨越多少时间步,只穿过 L+1 次 dropout,L 是层数。
主实验:Penn Treebank 词级语言模型。测试困惑度如下:
- 最佳无正则 LSTM(2 层,每层 200 单元):114.5。更大的无正则模型会过拟合。
- 中型 LSTM(2 层,每层 650 单元,dropout 50%):82.7。
- 大型 LSTM(2 层,每层 1500 单元,dropout 65%):78.4。
- 38 个大型 LSTM 集成:68.7。
训练细节。中型和大型模型都沿时间展开 35 步。中型模型训练 39 轮,梯度范数裁剪到 5,在 1 块 NVIDIA K20 GPU 上约需半天。大型模型训练 55 轮,裁剪阈值为 10,约需 1 整天。
另外 3 个任务。作者用同一方法验证了通用性:
- 语音识别(Google 内部冰岛语数据集,9.3 万条语音):验证集帧准确率从 68.9% 升到 70.5%。训练集帧准确率反而下降,这是 dropout 的典型表现。
- 机器翻译(WMT'14 英译法):BLEU 从 25.9 升到 29.03。
- 图像描述生成(MSCOCO):BLEU 从 23.5 升到 24.3,接近 10 个无正则模型集成的 24.4。
论文没有理论推导。它的贡献是一个清楚的工程判断,加上 4 个领域的实验证据。
关键概念
- 丢弃法(dropout)
- 训练时以概率 p 把每个单元的输出置 0。网络因此不能依赖任何单个单元,相当于同时训练许多共享权重的子网络。测试时关闭 dropout。
- 循环连接与非循环连接(recurrent / non-recurrent connection)
- 循环连接沿时间方向传递记忆,从 h_{t-1} 到 h_t。非循环连接沿深度方向传递特征,从第 l-1 层到第 l 层。本文只在后者上加 dropout。
- 困惑度(perplexity)
- 语言模型的标准指标,等于每个词平均交叉熵的指数 exp(loss)。困惑度 78 可以理解为:模型每一步平均在 78 个候选词之间犹豫。越低越好。
- 过拟合(overfitting)
- 模型记住了训练数据的噪声和细节,训练损失很低,验证损失却很高。数据少、模型大时最容易发生,正则化就是为了抑制它。
- Penn Treebank(PTB)
- 语言模型的经典小数据集,训练集约 93 万词,词表 1 万词。小数据配大模型极易过拟合,所以它常用来检验正则化方法。
历史位置:为什么值得读
dropout 由 Hinton 团队 2012 年提出,Srivastava 等人 2014 年在 JMLR 发表完整论文(第 12 天)。它在卷积网络上效果显著,但在 RNN 上一直用不好。
这篇论文的作者是 Zaremba(当时在纽约大学)以及 Google Brain 的 Sutskever 和 Vinyals。同一时期,Sutskever 和 Vinyals 在做 seq2seq 机器翻译,需要训练更大的 LSTM。论文解决的是他们自己的实际问题:大 LSTM 怎样不过拟合。
这个方案成为 2015–2017 年 LSTM 语言模型的默认配置。PyTorch 的 nn.LSTM(dropout=...) 参数就只在层间加 dropout,最后一层不加。后续工作继续改进:
- Gal 和 Ghahramani 2016 年提出变分 dropout:所有时间步共用同一个掩码,因此也能安全地用在循环连接上。
- Merity 等人 2017 年的 AWD-LSTM 在循环权重上用 DropConnect,把 PTB 测试困惑度降到 60 以下。
和清单其他天的关系:它直接用到第 2 天的 LSTM 和第 12 天的 dropout。第 4 天会从信息论角度解释,为什么给权重加噪声能防止过拟合。
学前准备
- 先看第 2 天,能写出 LSTM 一步前向的全部公式
- 理解 dropout 在训练和测试时的区别(可先看第 12 天)
- 知道困惑度等于 exp(平均交叉熵)
- 能区分训练集、验证集和测试集的用途
在原仓库怎么学
原仓库第 3 天用 NumPy 实现带正则化的 LSTM。注意:练习 1 来自论文,练习 2–5 是仓库作者补充的通用正则化方法。建议按下面的顺序学:
- 先读论文第 3 节和表 1,再打开 README.md 看本天的结构。
- 读 implementation.py。先看
dropout_forward和dropout_backward,再看RegularizedLSTM把 dropout 放在了哪几条路径上。 - 运行 train_minimal.py,用 data/sample_text.txt 训练,观察验证损失和早停的触发时机。
- 打开 notebook.ipynb,用 visualization.py 画训练与验证损失曲线、dropout 对激活值的影响、权重分布。
- 做 exercises/ 里的 5 个练习:dropout、层归一化、权重衰减、早停、完整训练流程。
- 对照 exercises/solutions/ 检查答案,最后用 CHEATSHEET.md 复习。
建议:做练习 1 时,把 dropout 分别放在循环连接和非循环连接上,各训练一次,比较验证损失。这一组对照就是论文的核心论点。自己跑出来的结果,比读结论更有说服力。
今天再看
还活着的:“只在一部分路径上加噪声”的思路一直在用。Transformer 的标准配置在残差分支、注意力权重和嵌入上加 dropout,不在残差主干上加。原理和本文相同:不要破坏需要长距离传递信息的通道。
变化了的:大语言模型预训练通常把 dropout 设为 0。数据量远大于模型能记住的量,训练只过一遍或几遍数据,过拟合不是主要矛盾。微调(fine-tuning)和小数据任务仍常用 dropout,例如 LoRA 的 lora_dropout 参数。
值得记住的教训:评估一个正则化方法,要先看它作用在哪条路径上。同一个 dropout,放对位置是改进,放错位置是破坏。
容易卡住的地方
- 测试时忘了关 dropout,困惑度会明显变高。NumPy 实现里要显式传入 training=False;PyTorch 里要调用 model.eval()。
- 使用反向 dropout(inverted dropout)时,训练阶段除以保留概率,测试阶段不再缩放。两处都缩放或都不缩放,输出尺度都会错。
- 隐藏状态跨 batch 传递时(截断 BPTT),要保留数值、切断梯度。否则计算图无限增长,内存很快耗尽。
- 小模型加 dropout 可能更差,论文的最佳无正则模型只有 200 单元。先确认训练损失明显低于验证损失,再加 dropout。
延伸阅读
- 原论文:Recurrent Neural Network Regularization
- 原仓库第 3 天目录:03_RNN_Regularization/ —— 代码、笔记本、练习与答案(英文)
- Dropout: A Simple Way to Prevent Neural Networks from Overfitting —— Srivastava 等人 2014 年,dropout 完整论文
- A Theoretically Grounded Application of Dropout in Recurrent Neural Networks —— Gal 和 Ghahramani,变分 dropout
- Regularizing and Optimizing LSTM Language Models —— Merity 等人 2017 年,AWD-LSTM