第 15 天 · 别把整句塞进一个向量:注意力的起点
一句话
论文指出,编码器-解码器把整句压成一个固定长度的向量,这是长句翻译变差的原因。作者让解码器每生成一个词,都对源句所有位置算一组权重,再取加权和。这就是后来所说的注意力机制,它还顺带学会了词对齐。
论文讲了什么
问题。2014 年,Cho 等人和 Sutskever 等人先后提出用 RNN 编码器-解码器做翻译。编码器读完源句,输出一个固定长度的向量。解码器只凭这个向量生成译文。作者观察到:句子越长,BLEU 下降越明显。一个固定长度的向量,很难装下一个 50 词长句的全部信息。
方法。论文把新模型叫 RNNsearch,把对照模型叫 RNNencdec。新模型有 2 处改动:
- 双向编码器:一个 RNN 从左读到右,另一个从右读到左。第 j 个词的注解
h_j是两个方向隐状态的拼接,同时包含左边和右边的上下文。 - 对齐模型:解码器生成第 i 个目标词之前,用上一步的状态
s_{i-1}给每个h_j打分:e_ij = v^T tanh(W s_{i-1} + U h_j)。分数经过 softmax 得到权重a_ij。上下文向量c_i = sum_j a_ij h_j。
关键在于:每个目标词都有自己的上下文向量 c_i,不再共用一个向量。对齐模型是一个小型前馈网络,和整个翻译模型一起用反向传播训练,不需要人工标注的对齐数据。
结果。实验用 WMT 2014 英法翻译数据,词表 30000 词。用最长 50 词的句子训练时,RNNsearch-50 的 BLEU 是 26.75,RNNencdec-50 是 17.82。在不含未登录词的句子上,训练更久的 RNNsearch-50* 得到 36.15,超过短语统计翻译系统 Moses 的 35.63。论文还按句长画了 BLEU 曲线:RNNencdec 随句长增加快速下降,RNNsearch-50 在 50 词以上的长句上几乎不掉分。
对齐图。作者把权重 a_ij 画成热力图,横轴是英文,纵轴是法文。大部分权重落在对角线上,因为英法语序接近。例外出现在形容词和名词的顺序上:英文 "European Economic Area" 在法文里是 "zone économique européenne",词序反过来。热力图在这一段出现反向的斜线。没有人告诉模型要调序,它从数据里自己学会了。
直觉。人工翻译长句时,不会先背下整句再动笔。译者写每个词时,眼睛都会回到原文的对应位置。这篇论文让模型也学会了"回看"。
关键概念
- 注解(Annotation)
- 论文对编码器每个位置输出向量的叫法,即双向隐状态的拼接 h_j。后来的文献多称为编码器隐状态,或注意力里的键和值。
- 对齐模型(Alignment Model)
- 一个小型前馈网络,输入解码器上一步状态和某个注解,输出一个标量分数,表示两者匹配程度。
- 加性注意力(Additive Attention)
- 打分函数为 v^T tanh(W s + U h),先各自线性变换再相加。与之对应的是第 13 天用的点积注意力。
- 上下文向量(Context Vector)
- 注解按注意力权重的加权和 c_i。它随目标位置 i 变化,取代了旧模型中唯一的固定长度向量。
- 双向 RNN(Bidirectional RNN)
- 两个方向相反的 RNN 读同一个句子,把同一位置的两个隐状态拼接。每个位置都能看到整句的上下文。
- 软对齐(Soft Alignment)
- 每个目标词对所有源词给出一个概率分布,而不是只选一个源词。分布可导,所以能用梯度下降端到端训练。
历史位置:为什么值得读
2014 年之前,机器翻译的主力是短语统计系统,代表是 Moses。同年,Sutskever、Vinyals 和 Le 发表了序列到序列(seq2seq)模型。Cho 等人也提出了 RNN 编码器-解码器和后来叫 GRU 的门控单元。神经翻译刚起步,长句是最大短板。
本文补上了这块短板,影响分 3 条线:
- 翻译:2015 年 Luong 等人比较了多种打分函数。2016 年 Google 神经机器翻译系统(GNMT)上线,核心就是带注意力的编码器-解码器。
- 其他领域:2015 年的 Show, Attend and Tell 让图像描述模型在生成每个词时关注图片的不同区域。
- 结构:第 18 天的指针网络把注意力权重直接当输出。第 13 天的 Transformer 把注意力变成唯一的计算方式。
论文正文主要用"对齐"这个词,只在少数地方说这相当于解码器里的注意力机制。"注意力"后来成了整个领域的通用名词。读原文能看到这个概念最初的样子:一个为了解决长句问题而加的小模块。
学前准备
- 理解 RNN 和 LSTM 的循环计算,见第 1、2 天
- 知道 seq2seq 编码器-解码器怎么翻译
- 会算 softmax 和加权平均
- 会写 PyTorch 的 nn.GRU 或 nn.LSTM
在原仓库怎么学
- 读 README.md,找到它标注的论文章节号,然后打开原论文第 3 节。
- 对照 PAPER_NOTES.md 读论文第 3 节和第 5 节的实验图表。
- 读 implementation.py,依次看
BahdanauAttention、Encoder、AttentionDecoder和Seq2SeqWithAttention4 个类。 - 做 exercises/ 里的 5 个练习:
exercise_1.py实现加性注意力,exercise_2.py写双向编码器,exercise_3.py写注意力解码器,exercise_4.py在数字倒序任务上训练,exercise_5.py画注意力图。答案在 exercises/solutions/。 - 运行 train_minimal.py,在数字倒序任务上训练完整模型,可以用
--hidden-size和--epochs调参。数据说明见 data/README.md。 - 用 visualization.py 画训练后的注意力矩阵。倒序任务训练成功时,应该看到一条反对角线。
- 用 notebook.ipynb 串一遍,用 CHEATSHEET.md 复习。
今天再看
这篇论文的模块今天仍然随处可见,只是换了形式:
- 交叉注意力:编码器-解码器模型里,解码器读编码器输出的那一层,就是本文思想的直接后代。语音识别、翻译和图文多模态模型都在用。
- 打分函数:加性打分大多被缩放点积取代。点积可以写成一次矩阵乘法,在 GPU 上快得多。
- 大语言模型:每个新词都对之前所有词算注意力。推理时缓存的 K 和 V,相当于本文的注解向量。
"注意力权重能不能当作解释"有过争论。2019 年 Jain 和 Wallace 发表 Attention is not Explanation,同年 Wiegreffe 和 Pinter 发表了反驳。结论是:权重提供线索,但不等于模型的因果理由。读对齐热力图时要记住这一点。
容易卡住的地方
- 打分时用错解码器状态:论文用上一步的 s_{i-1} 计算第 i 步的权重,再用 c_i 更新到 s_i。用 s_i 会形成循环依赖,代码里常表现为维度或顺序错乱。
- 双向编码器的注解是 2n 维,解码器状态是 n 维。W 和 U 的输入维度不同,初始化线性层时最容易写错。
- 批量训练时句子长度不同,填充位置要在 softmax 前设成负无穷。否则模型会把注意力放到填充符上。
- 倒序任务的注意力图如果是一片均匀颜色,说明模型没在用注意力。先检查注意力输出是否真的接入了解码器,再检查学习率和训练轮数。
延伸阅读
- 原论文:Neural Machine Translation by Jointly Learning to Align and Translate
- 原仓库第 15 天目录:15_bahdanau_attention/ —— 代码、笔记本、练习与答案(英文)
- Effective Approaches to Attention-based NMT(Luong et al. 2015) —— 比较点积、一般式和拼接式打分函数
- Attention and Augmented Recurrent Neural Networks(Distill) —— 交互图解注意力和神经图灵机
- Attention? Attention!(Lilian Weng) —— 注意力机制发展脉络综述
- Show, Attend and Tell(Xu et al. 2015) —— 注意力用于图像描述