第 13 天 · 去掉循环,只留注意力:大模型的底座
一句话
论文提出 Transformer:编码器和解码器只用注意力层和前馈层,不用循环,也不用卷积。它在 WMT 2014 英德、英法翻译上超过当时最好的模型,训练时间短得多。今天几乎所有大语言模型都建在这个结构上。
论文讲了什么
问题。2017 年,机器翻译的主流是 RNN 编码器-解码器加注意力。RNN 必须逐词计算,第 t 步要等第 t-1 步算完,GPU 的并行能力用不上。两个相距很远的词,信息要穿过很多步才能相遇,路上容易衰减。
方法。作者拿掉全部循环,只保留注意力。模型由 4 类部件组成:
- 缩放点积注意力:
Attention(Q, K, V) = softmax(Q K^T / sqrt(d_k)) V。每个位置用查询 Q 和所有位置的键 K 算相似度,再按权重汇总值 V。除以sqrt(d_k)是为了让点积不要太大。点积太大时,softmax 会进入梯度接近 0 的饱和区。 - 多头注意力:把 512 维拆成 8 个头,每个头 64 维。每个头独立做注意力,最后拼接。不同的头可以学不同的关系,例如一个头跟踪主谓关系,另一个头跟踪代词指向。
- 位置编码:注意力本身不区分顺序。作者给每个位置加上一组不同频率的正弦和余弦信号,让模型知道每个词在第几位。
- 前馈层、残差连接和层归一化:每个子层的输出是
LayerNorm(x + Sublayer(x))。前馈层把 512 维升到 2048 维,再降回 512 维。
编码器和解码器各堆叠 6 层。解码器的自注意力带掩码:第 i 个位置只能看第 1 到第 i 个位置,生成时不能偷看后面的答案。解码器还多一层编码器-解码器注意力,用来读取源句子。
结果。大模型在 WMT 2014 英德翻译上得到 28.4 BLEU,比此前最好的结果(包括集成模型)高 2 BLEU 以上。英法翻译得到 41.8 BLEU,用 8 块 P100 GPU 训练 3.5 天。基础模型约 6500 万参数,在同样 8 块 GPU 上只训练 12 小时。作者还把模型用于英语句法分析,结果同样有竞争力。这说明结构不只适用于翻译。
直觉例子。句子"小明把书还给小红,因为她明天考试"。模型处理"她"时,一层注意力就能把权重放到"小红"上。RNN 要把"小红"的信息携带好几步,才能在"她"这里用上。
关键概念
- 自注意力(Self-Attention)
- 同一个序列里,每个位置都对所有位置算权重,再加权汇总。任意两个位置之间只隔 1 步,适合捕捉远距离依赖。
- 缩放点积注意力(Scaled Dot-Product Attention)
- 用 Q 和 K 的点积当相似度,除以 sqrt(d_k) 后过 softmax,再乘 V。整个计算是几次矩阵乘法,GPU 上很快。
- 多头注意力(Multi-Head Attention)
- 把向量切成 h 份,每份各做一次注意力,再拼接并线性变换。论文用 h = 8。多个头可以同时关注不同类型的关系。
- 位置编码(Positional Encoding)
- 给词向量加上随位置变化的正弦、余弦信号。没有它,打乱词序后注意力的输出只是跟着重新排列,模型分不出语序。
- 因果掩码(Causal Mask)
- 解码器中把未来位置的分数设成负无穷,softmax 后权重为 0。训练时可以并行算所有位置,又不泄露答案。
- 学习率预热(Warmup)
- 前 4000 步学习率线性上升,之后按步数的平方根倒数下降。没有预热时,这种结构的训练早期容易发散。
历史位置:为什么值得读
2014 年的 Bahdanau 注意力(第 15 天)让 RNN 解码器能回看源句,但主干仍是 RNN。本文把注意力从配角变成全部。它还用到了清单里的其他工具:残差连接来自 ResNet(第 9 天),dropout 来自第 12 天。
这篇论文的影响几乎覆盖了之后的整个深度学习:
- 2018 年,BERT 只用编码器,GPT 只用解码器,开启了预训练语言模型。
- 2020 年,ViT 把图片切成小块当词,Transformer 进入视觉领域。
- 结构统一以后,规模成了主要变量。第 24 天的 GPipe 解决大模型怎么切分训练,第 25 天的缩放定律研究模型变大后损失怎么下降。
- 第 30 天的 RLHF 训练的对象,也是 Transformer 语言模型。
值得读原文的理由:论文篇幅不长,结构清楚。很多今天习以为常的细节都在这里成套出现:多头、缩放、预热和标签平滑。第 14 天的 The Annotated Transformer 是本文的代码版,建议两天连着读。
学前准备
- 会用 numpy 写矩阵乘法、softmax 和广播
- 理解编码器-解码器翻译模型,建议先读第 15 天
- 知道残差连接的作用,见第 9 天
- 知道 dropout 和层归一化各解决什么问题
在原仓库怎么学
- 先读 README.md,看清整体结构和超参数表的位置。
- 打开原论文,对照 paper_notes.md 读第 3 节模型结构。
- 读 implementation.py。这是纯 numpy 实现,包含
ScaledDotProductAttention、MultiHeadAttention、PositionalEncoding、EncoderBlock、DecoderBlock和两个掩码函数。 - 按顺序做 exercises/ 里的 5 个练习:
exercise_01_scaled_dot_product.py写缩放点积注意力,exercise_02_multi_head_attention.py写多头注意力,exercise_03_positional_encoding.py写正弦位置编码,exercise_04_encoder_block.py组装编码器块,exercise_05_full_transformer.py组装完整模型。卡住时再看 exercises/solutions/。 - 运行 train_minimal.py,用
--task copy或--task reverse训练一个小模型,观察损失下降。 - 在浏览器打开 visualizations/transformer_interactive.html,再用 visualization.py 画注意力热力图。
- 最后用 notebook.ipynb 串一遍,用 CHEATSHEET.md 复习公式。
今天再看
2026 年回头看,核心结构几乎原样保留:Q/K/V 注意力、多头、残差、逐位置前馈层。变化主要在细节:
- 结构:大语言模型几乎都只用解码器,编码器-解码器主要留在翻译和语音模型里。
- 位置:正弦位置编码大多被旋转位置编码(RoPE)取代,长上下文更容易外推。
- 归一化:论文把层归一化放在残差之后。现在普遍放在子层之前,或换成 RMSNorm,深层训练更稳。
- 前馈层:ReLU 常被 SwiGLU 一类门控激活取代。
- 效率:注意力的计算量随长度平方增长。FlashAttention 改进了显存读写,分组查询注意力(GQA)减小了推理时的 KV 缓存。
读这篇论文,等于读懂今天每个大语言模型的骨架。后来的改进都是在这个骨架上换零件。
容易卡住的地方
- 多头的形状变换最容易错:(batch, seq, 512) 要变成 (batch, 8, seq, 64)。建议每一步打印 shape,并用 seq 长度不同于 64 的输入测试。
- 掩码要在 softmax 之前加负无穷(或 -1e9),不是在 softmax 之后乘 0。另外分清填充掩码和因果掩码,解码器自注意力两种都要。
- 不理解为什么除以 sqrt(d_k):生成两个 64 维标准正态随机向量,统计点积的方差,会得到约 64。除以 8 后方差回到约 1。
- 位置编码是与词向量相加,不是拼接。论文还把词向量乘以 sqrt(d_model),漏掉这一步时位置信号会盖过词义。
延伸阅读
- 原论文:Attention Is All You Need
- 原仓库第 13 天目录:13_attention/ —— 代码、笔记本、练习与答案(英文)
- The Illustrated Transformer(Jay Alammar) —— 图解每一步张量怎么流动
- Let's build GPT: from scratch(Andrej Karpathy) —— 视频,从零写一个只有解码器的模型
- On Layer Normalization in the Transformer Architecture —— 解释归一化前置为什么能省掉预热