附录 B 关键节点拆解 Ⅰ:2017–2022,decoder-only 范式的确立¶
这一篇的任务:把 2017 到 2022 这六年里真正改变了架构的论文排成一条线,每一个都回答三个问题——它当时要解决什么问题、它给今天留下了哪个零件、这个零件在本书第几章。
怎么用:不必按顺序读完。读完正文某一章之后,回来看这里对应的那几节,你会知道那个设计是谁在什么压力下做出来的。
B.1 Transformer(2017):一次拆解,看清哪些活到了今天¶
论文:Attention Is All You Need(arXiv:1706.03762)
它当时要解决的问题:RNN 的序列依赖让训练无法并行,长距离依赖也传不动。CNN 类方案(ByteNet、ConvS2S)并行了但感受野随距离线性/对数增长。作者的主张是:只用注意力,把任意两个位置的路径长度降到 1,同时全序列并行。
原始配置(base 模型,约 65M 参数):6 层编码器 + 6 层解码器,d_model=512,h=8,d_k=d_v=64,d_ff=2048,Dropout 0.1,label smoothing 0.1。训练用 Adam(β2=0.98)配 4000 步 warmup 和 inverse-sqrt 衰减。
现在逐个零件判生死:
| 零件 | 今天的状态 | 说明 | 章节 |
|---|---|---|---|
缩放点积注意力 softmax(QKᵀ/√d)V |
原样保留 | 核心公式九年没变 | 第 2.2 节 |
| 多头 | 保留,但头的配置全变了 | MQA/GQA/MLA 重新分配了 K、V 的头数 | 第 7 章 |
| 残差 + 归一化 | 保留 | 归一化的种类和位置都换了 | 第 5 章 |
| FFN(升维再降维) | 保留,激活换了 | ReLU → GELU → SwiGLU | 第 5.3 节 |
| 因果掩码 | 保留 | 解码器侧的那一半成了全部 | 第 2.3 节 |
| Adam + warmup | 保留 | warmup 至今几乎必需 | 第二册第 8 章 |
| Post-LN | 淘汰 | 深层难训,被 Pre-LN 取代 | 第 5.1 节 |
| 正弦位置编码 | 淘汰 | 外推能力差,被 RoPE 取代 | 第 6 章 |
| encoder-decoder | 在 LLM 里淘汰 | 但在多模态里以"视觉编码器 + 语言解码器"的形式复活 | 附录 G |
| ReLU FFN | 淘汰 | 见上 | 第 5.3 节 |
| Dropout / label smoothing | 预训练阶段基本关掉 | 原因见附录 A.7 | — |
d_ff = 4 × d_model |
松动 | SwiGLU 为保持参数量改成约 8/3 × d_model |
第 5.3 节 |
这张表是本书的一条暗线:活下来的都是"决定信息怎么流动"的结构,被换掉的都是"数值细节"。判断一篇新论文重不重要,可以先问它动的是哪一类。
B.2 2018–2019:三条路线分叉,为什么 decoder-only 赢了¶
同一时期出现了三种用 Transformer 做预训练的方式:
- GPT-1(2018,decoder-only,117M):自回归语言建模 + 下游微调。
- BERT(2018,encoder-only,110M/340M):掩码语言建模(MLM)+ 下一句预测,双向上下文,在理解类任务上碾压。
- T5(2019,encoder-decoder):把所有任务统一成 text-to-text,span corruption 预训练,用相对位置偏置。
2018 到 2020 年,BERT 才是学术界和工业界的主流。decoder-only 后来赢了,原因有四条,值得记住,因为它们解释了本书为什么从第 2 章起就只讲解码器:
- 它天然会生成。MLM 模型要生成得额外设计解码过程,而生成是后来所有能力(对话、推理链、工具调用)的载体。
- 训练信号密度高。自回归在每个位置上都产生一个预测目标;BERT 只在被掩码的 15% 位置上有 loss。同样的算力,前者从数据里榨出的监督多得多。
- 结构最简单,最好扩展。没有 encoder-decoder 的 cross-attention,没有两套参数,张量并行和流水并行的切分都更规整(第二册第 4–7 章)。
- 推理形态与 KV Cache 完美契合。因果掩码意味着历史表示永不改变,于是可以缓存。双向注意力每来一个新 token 就要重算全部(第 4 章)。
第 4 条尤其值得体会:一个看起来纯属"建模选择"的因果掩码,实际上决定了整个推理系统能不能做出来。 第二册几乎所有的推理优化都建立在这一个性质上。
B.3 GPT-2(2019):把归一化挪了个位置¶
它的主要贡献常被记成"1.5B 参数 + zero-shot",但对架构而言更重要的是两个细节:
- Pre-LN:把 LayerNorm 移到每个子层的输入端,并在最后一层之后补一个 LayerNorm。残差主干上不再有归一化操作,梯度能一路直通。这和 pre-activation ResNet 是同一个发现(附录 A.3)。
- 残差投影的初始化缩放:把每个残差分支最后那个投影层的初始权重乘以
1/√N(N为残差层数)。因为L层的输出会累加到同一条残差流上,不缩放的话主干的方差随深度线性增长。
配置:48 层,d_model=1600,上下文 1024,BPE 词表 50257。
为什么值得单列一节:这两条今天仍然写在几乎每一份开源模型的代码里,而且是第 5 章"训练稳定性"整章的起点。很多人以为稳定性问题是模型做到百亿以上才出现的,其实 2019 年就已经在解了。
B.4 GPT-3(2020):规模本身成了方法¶
论文:Language Models are Few-Shot Learners(arXiv:2005.14165)
配置:175B 参数,96 层,d_model=12288,96 个头(d_head=128),上下文 2048,训练约 300B token。
架构上它几乎没有新东西——照抄 GPT-2,唯一的结构改动是"交替使用稠密注意力与局部带状稀疏注意力"(借自 Sparse Transformer,arXiv:1904.10509)。
但它确立了两件影响至今的事:
- 上下文学习(in-context learning):不改一个参数,只在 prompt 里给几个示例,模型就能完成新任务。这直接催生了后来的 prompt 工程、few-shot 评测协议,以及第三册整册的"不改权重也能改行为"这条线。
- 稀疏/稠密交替是可行的。这个结论被搁置了几年,2024 年之后随着长上下文需求回归,成了主流(第 12、14 章,以及附录 C.4、D.3)。
顺便记一个数:175B 参数、300B token,比例约 1.7 token/参数。两年后 Chinchilla 会告诉你这个配比错得离谱。
B.5 Scaling law 的两次修正:一条决定了所有模型尺寸的线¶
这条线不改计算图,却决定了每一个模型该做多大、训多少数据,因此必须放进架构书里。
第一次(Kaplan et al., 2020,arXiv:2001.08361):损失随参数量、数据量、算力呈幂律下降,并且结论是给定算力时应优先把参数做大。GPT-3 那一代的"大模型、相对少数据"路线就是这么来的。
第二次(Chinchilla, 2022,arXiv:2203.15556):DeepMind 重做了实验,发现参数与数据应该按同等比例一起扩,经验值约 20 token/参数。他们用 70B 模型训 1.4T token,全面打败了 280B 的 Gopher。这直接导致下一年的模型集体变小、数据集体变多——LLaMA 就是这条结论的产物。
第三次修正(2023 年之后,没有单一论文,是工业界的共识):Chinchilla 最优是训练算力最优,不是总成本最优。一个模型训一次、推理无数次,把小模型训到远超 Chinchilla 点(Llama 3 的 8B 训了 15T token,约 1800 token/参数)在总账上更划算。
给你的判断工具:看到一个模型的"参数量 / 训练 token 数"比例,就能大致推断它的定位——接近 20 是研究型或算力受限,几百到上千是为部署优化的产品型。
B.6 2020–2022:零件的铺货期¶
现代模型用的大部分零件都在这两三年里被发明出来,但当时没有任何一个模型把它们凑齐。
| 年份 | 工作 | 它给了什么 | 本书章节 |
|---|---|---|---|
| 2019 | MQA(arXiv:1911.02150) | 所有头共享一份 K/V,KV Cache 直接除以头数 | 第 7.2 节 |
| 2019 | Sparse Transformer | 跨步/固定稀疏模式,长序列注意力的第一批可用方案 | 第 11 章 |
| 2019 | RMSNorm | 去掉均值中心化的 LayerNorm | 第 5.2 节 |
| 2020 | GShard(arXiv:2006.16668) | MoE 的 top-2 路由、容量因子、跨设备专家并行 | 第 9 章 |
| 2020 | GLU 变体(arXiv:2002.05202) | SwiGLU,以及"把 d_ff 乘 2/3 保持参数量"这个惯例 |
第 5.3 节 |
| 2021 | Switch Transformer(arXiv:2101.03961) | top-1 路由把 MoE 做到 1.6T 参数,也暴露了负载均衡和容量丢弃 | 第 8.3–8.4 节 |
| 2021 | RoPE(arXiv:2104.09864) | 旋转位置编码:相对位置、可外推、无需额外参数 | 第 6.2 节 |
| 2021 | ALiBi(arXiv:2108.12409) | 线性距离惩罚,当时外推最好的方案 | 第 6 章 |
| 2022 | FlashAttention(arXiv:2205.14135) | IO 感知的精确注意力,分块计算不落 n×n 矩阵 |
第 4.4 节 |
| 2022 | muP(arXiv:2203.03466) | 让小模型上调好的超参能迁移到大模型 | 附录 F |
两点值得说:
- ALiBi 输给了 RoPE,但不是因为效果差。它当时确实外推更好。输的原因是 RoPE 对后续技术更友好——后来的窗口扩展多半在 RoPE 的频率上做手脚(第 6 章),生态一旦形成就很难逆转。"哪个技术胜出"经常不取决于单点指标,这在本书后面会反复出现。
- FlashAttention 不是近似注意力,它计算同一个数学结果,只是重排顺序以避开显存带宽瓶颈。由于浮点运算次序不同,数值不保证逐 bit 相同。把它和第 11 章的稀疏注意力分清楚:前者不改变目标算子,后者改变参与计算的连接。
B.7 PaLM(2022):第一份"现代配方"的完整清单¶
论文:arXiv:2204.02311,540B 稠密模型。
规模已经不是它今天的价值所在,它的价值在于第一次把一批选择打包在一起并公开说明理由:
- SwiGLU 替代 ReLU FFN
- RoPE 替代可学习位置嵌入
- 去掉所有 bias(包括 LayerNorm 的)——报告称这提升了大模型的训练稳定性
- 输入输出嵌入共享
- MQA(在当时是为了推理速度)
- 并行化的 attention 与 FFN(两者读同一个归一化后的输入,输出相加,可以省一次通信)
- 预训练不用 Dropout
除了最后一条"并行 attention+FFN"没有成为主流(收益主要在特定并行配置下,后来被更好的通信重叠方案取代),其余每一条都进了 2023 年的标准配方。下一篇的 LLaMA 基本就是这张清单去掉 MQA 和并行层。
B.8 这六年留下的三条经验¶
- 结构上的胜者都在解决"信息怎么流",数值上的细节会被反复替换。 残差、注意力、因果掩码活了九年;归一化种类、激活函数、位置编码换了好几轮。
- 一个建模选择的真正代价往往出现在系统侧。 因果掩码带来了 KV Cache,MQA 是为了推理而不是为了精度,稀疏注意力的成败取决于能不能写出高效核。
- 好想法经常要等几年才等到它的场景。 稀疏注意力 2019 年就有,2024 年才成主流;MoE 2020 年就能做到 1.6T,2024 年才在开源模型里普及。技术不是在发明的那一年成熟的,是在约束变化的那一年成熟的。
核心问答¶
Q1:现在还有必要读 2017 年那篇原论文吗? 有,但读法要变。读它的第 3 节(模型结构)和附录里的超参表,对照 B.1 那张表看哪些还在。不要照着它建立对现代模型的认识——它有一半内容(encoder-decoder、Post-LN、正弦编码、label smoothing)在今天的 LLM 里已经不存在了。
Q2:BERT 这条路线彻底死了吗? 在生成式大模型这条线上是的。但 encoder 结构在检索(embedding 模型、reranker)、分类、以及多模态的视觉侧仍然是主力。它不是被证伪,是被换了赛道。
Q3:Chinchilla 的 20 token/参数现在还能用吗? 只能当参考下界。它回答的是"训练算力固定时怎么分配",而真实项目要考虑推理成本、部署显存、上下文长度。现在的实际取值普遍远高于 20,见 C.1。
Q4:为什么 MoE 在 2021 年就能做到 1.6T 参数,开源社区却到 2023 年底才用上? 三个原因:稀疏模型当时训练不稳定且质量不如同算力稠密模型;专家并行需要的通信基础设施(AllToAll)不成熟;以及最关键的——显存价格还没贵到让人愿意接受"总参数很大但激活很小"这种交易。第 9.6 节算过这笔账。
Q5:这一段里哪一件事对读现代模型代码最有用?
B.1 的那张生死表。打开任何一份 modeling_*.py,你看到的结构就是"2017 年的骨架 + 表里那几处替换"。认出这一点之后,读新模型的速度会快一个量级。