附录 A 从 ResNet 到 CLIP:你已经会的组件在 LLM 里的位置¶
这一篇的任务:把你在视觉领域已经掌握的模块,一个一个对应到本书正文的章节上。读完你会发现,第 2 到第 8 章里没有一个组件是凭空出现的——它们中的大多数你训练 ResNet 和 ViT 的时候就用过,只是换了名字和位置。
这一篇也负责一件同样重要的事:指出你的视觉训练直觉会在哪里失效(A.7)。那些地方比相似之处更值得花时间。
A.1 先说结论:架构的差异比你想的小,配方的差异比你想的大¶
把 ResNet-50 和一个 8B 语言模型并排放,你会以为它们毫无关系。但如果逐个拆零件:
| 零件 | 视觉里的形态 | LLM 里的形态 | 本书章节 |
|---|---|---|---|
| 残差连接 | ResNet 的 skip connection | 残差流(residual stream) | 第 2 章 |
| 归一化 | BatchNorm | RMSNorm | 第 5 章 |
| 归一化位置 | ResNet v2 的 pre-activation | Pre-LN | 第 5 章 |
| 升维再降维的非线性块 | bottleneck 的 1×1 → 3×3 → 1×1 | FFN 的 d → 4d → d |
第 2 章 |
| 把图/文切成单元 | ViT 的 patch embedding | tokenizer + token embedding | 第 1、2 章 |
| 位置信息 | ViT 的可学习绝对位置嵌入 | RoPE | 第 6 章 |
| 局部感受野 | Swin 的窗口注意力 | 滑动窗口注意力 | 第 11 章 |
| 全局交互 | ViT 的全局自注意力 | 因果自注意力 | 第 2 章 |
| 跨模态交互 | DETR / CLIP 的 cross-attention 与双塔 | 多模态连接器 | 附录 G |
真正把两边区分开的不是这张表,而是训练配方:数据量与参数量的比例、epoch 数、正则化策略、精度、以及"只有一次机会"这个约束。A.7 专门讲这件事。
A.2 ResNet:残差流这个概念是它给的¶
ResNet(He et al., 2015, arXiv:1512.03385)解决的问题是:网络加深到一定程度后,训练误差反而上升——不是过拟合,是优化不动了。它的答案是让每个块学残差 y = x + F(x),而不是直接学 y = H(x)。
这个结构被 Transformer 原封不动地拿走了。现代 LLM 里的说法叫残差流:贯穿所有层的那条主干 x,每一层(注意力、FFN)把自己的输出加回主干。两点值得注意:
- 主干的维度从头到尾不变(就是
d_model)。所有层都在往同一条流上读写,这是后来很多可解释性工作的出发点。 - 加法而非替换,意味着任何一层都可以学成近似恒等。这是深层网络能训起来的物理原因,在 ResNet 和 Transformer 里是同一个原因。
bottleneck 结构也搬过来了。ResNet 的 1×1 降维 → 3×3 卷积 → 1×1 升维,和 Transformer FFN 的 d → 4d → d 是同一类设计:在一个与主干不同的维度里做非线性变换,再投影回来。区别只是 FFN 是先升后降、卷积是先降后升,以及 FFN 用 SwiGLU 把中间层拆成了门控与值两支(第 5 章)。
2026 年的一个转折:残差连接沿用了十年没变,但这一年两个前沿模型同时动了它——Kimi K3 的 Attention Residuals 和 DeepSeek-V4 的 Manifold-Constrained Hyper-Connections。详见附录 D.5。你在这里建立的"残差流"直觉,正好是理解那些改动的前提。
A.3 ResNet v2 与 Pre-LN:同一个发现,隔了两年在两个领域各发生一次¶
原始 ResNet 的块是 conv → BN → ReLU,残差加完之后再过激活。何恺明团队第二年做了一个看似很小的改动(arXiv:1603.05027):把 BN 和 ReLU 提到卷积前面(pre-activation),让残差路径变成一条纯粹的恒等通路。结果是 1000 层的网络可以训练了。
Transformer 那边发生了一模一样的事。原始 Transformer(2017)是 Post-LN:x + Sublayer(x) 然后再 LayerNorm。这个结构在深层时需要精心设计的学习率 warmup 才能不发散。GPT-2(2019)改成 Pre-LN:x + Sublayer(LN(x)),残差主干上不再有归一化,梯度可以一路直通。
这是同一个原理的两次独立发现:残差主干上不要放任何会缩放信号的操作。 如果你当年理解了 pre-activation ResNet 为什么更好训,第 5 章的 Pre-LN 你已经懂了。
现代模型在此之上还有一层变化:部分模型(Gemma 2、Qwen 系列的一些配置)在子层输出上再加一个归一化,形成 x + Norm(Sublayer(Norm(x))) 的"三明治"结构。目的是控制残差流的数值随深度累积增长。这同样在视觉里有对应物(各种 LayerScale / ReZero 的变体)。
A.4 BatchNorm 为什么进不了 LLM¶
这是视觉工程师最常问的问题之一,答案有四条,每一条单独都足以判死刑:
- 依赖 batch 统计量。推理时 batch 常常等于 1(decode 阶段逐 token 生成),BN 必须切换到滑动平均统计量,训练与推理行为不一致。语言模型对这种不一致更敏感。
- 序列长度可变。BN 要在 batch 和空间维度上求统计量;序列是变长的,加上因果掩码后每个位置可见的历史还不一样,"在哪个维度上归一化"这个问题没有好答案。
- 因果性会被破坏。在序列维度上求统计量意味着当前 token 能看到未来 token 的信息,直接违反自回归约束。
- 分布式训练要同步。BN 的统计量跨数据并行需要通信(SyncBN),在几千卡规模上这是不能接受的额外开销。
于是 LLM 走了 LayerNorm(Ba et al., 2016):只在特征维度上归一化,与 batch 和序列长度完全无关,每个 token 独立计算。再往后是 RMSNorm(Zhang & Sennrich, 2019):连均值中心化都去掉,只除以均方根,x / RMS(x) * g。省掉一次求均值和一次减法,效果基本不变,现在是事实标准(第 5.2 节)。
顺带回答另一个常见疑问:LLM 里为什么没有 BN 那种"自带正则化效果"的东西?因为预训练阶段基本不需要正则化——见 A.7。
A.5 ViT:你其实已经训过 Transformer 了¶
ViT(arXiv:2010.11929)的贡献是证明了一件事:把图像切成 16×16 的 patch,每个 patch 线性投影成一个向量,然后原封不动地喂进 NLP 那套 Transformer encoder,在足够数据下能打败 CNN。
这意味着你训 ViT 的时候,已经在训 Transformer 了。对照如下:
| ViT | LLM | 差别在哪 |
|---|---|---|
| patch embedding(线性投影) | token embedding(查表) | 图像是连续的所以用投影,文本是离散的所以用查表 |
| 固定 196 个 patch | 变长 token 序列 | LLM 必须处理变长,这带来 padding、packing、掩码一系列问题(第二册) |
| 可学习绝对位置嵌入 | RoPE | 见下 |
| 双向自注意力 | 因果自注意力 | ViT 每个 patch 看全图,LLM 每个 token 只能看左边(第 2.3 节) |
| CLS token 做分类 | 最后一个位置的 logits 做预测 | 任务头不同,主干相同 |
| Post-LN → Pre-LN 的迁移 | 同样的迁移 | 见 A.3 |
最值得你花时间的差别是位置编码。 ViT 的可学习绝对位置嵌入有个硬伤:训练时是 196 个位置,推理时换分辨率就得插值。LLM 面对的是同一个问题的极端版本——训练时几千,部署时常要长得多。第 6 章讲的是 RoPE 怎样把相对距离写进注意力;超长时的显存和质量,在第 7、11 章。这也是为什么位置这套东西在视觉里没有同等分量。
另一个值得注意的对应是 Swin。 Swin Transformer(arXiv:2103.14030)为了把注意力的平方复杂度降下来,用了窗口内注意力 + 移位窗口。LLM 这边的滑动窗口注意力(Mistral、Gemma、gpt-oss)是同一个想法在一维上的版本,连"局部窗口必须配上某种全局通路"这个结论都一样——Swin 靠移位窗口跨窗传信息,LLM 靠在若干层里插入全注意力层(第 12、14 章)。
A.6 CLIP 与 SigLIP:它们今天的身份是"多模态大模型的眼睛"¶
CLIP(arXiv:2103.00020)本身是双塔对比学习:图像塔(ViT)和文本塔(一个小 Transformer)各自编码,在共享空间里拉近正样本、推远负样本,温度参数可学习。
对本书读者,CLIP 有三层意义:
- 它的文本塔就是一个标准的 Transformer 解码器结构(带因果掩码,取最后一个 token 的表示)。你读它的代码时看到的东西,第 2 章会逐行讲。
- 它的图像塔是今天几乎所有多模态大模型的视觉编码器的祖先。LLaVA 用 CLIP ViT,后来主流换成 SigLIP(arXiv:2303.15343,把 softmax 对比损失换成逐对 sigmoid,去掉了对全局负样本 all-gather 的依赖,因此更好扩展)。接法见附录 G。
- 它演示了"用海量弱标注数据做对比预训练"这个范式,和语言模型"用海量文本做 next-token 预训练"是同一个时代精神的两个分支。
A.7 你的视觉训练直觉会在这些地方失效¶
这一节比前面所有内容都重要。相似之处会自己浮现,不同之处不会,它们会以"我的实验结果很奇怪"的形式出现。
| 你的习惯 | LLM 预训练的实际做法 | 为什么 |
|---|---|---|
| 训练 100–300 epoch | 约 1 epoch,甚至不到 | 数据量远大于模型容量,重复看数据收益很低且会加剧记忆化 |
| 数据增强是标配 | 基本没有等价物 | 文本没有"不改变语义的扰动"这种廉价操作;对应的工作变成了数据配比、去重、质量过滤(第二、三册) |
| Dropout 0.1–0.5 | 预训练阶段通常关掉 | 单次遍历数据、模型远未过拟合,Dropout 只会拖慢收敛。后训练在小数据上微调时它才回来 |
| BatchNorm | RMSNorm | 见 A.4 |
| weight decay 给所有参数 | 只给矩阵参数,norm 的权重、bias、embedding 通常排除 | 对一维参数做衰减会直接改变归一化的尺度行为 |
| 看验证集早停 | 没有早停,按预算训完 | 验证 loss 单调下降,几乎不会转折;真正要看的是下游评测和训练稳定性 |
| 不行就重训 | 只有一次机会 | 一次预训练是千卡月级别的开销,所以超参必须靠小模型外推(附录 F 的 muP) |
| 混合精度 = amp + fp32 权重 | bf16 计算 + fp32 主权重,前沿模型已经在用 FP8 甚至 FP4 存专家 | 规模逼出来的,细节在第二册 |
| 过拟合是主要敌人 | 训练不稳定(loss 尖峰、发散)是主要敌人 | 第 5 章大半章在讲这个 |
| 模型大小由显存决定 | 模型大小由"训练预算 + 部署成本"共同决定 | Chinchilla 与它后来的修正,见附录 B.5 和 C.1 |
如果只能记住一条:视觉里你在和过拟合搏斗,LLM 预训练里你在和不稳定与成本搏斗。 这条差异解释了本书为什么把整整一章(第 5 章)给了归一化和激活函数这些看起来很基础的东西。
A.8 ConvNeXt 给的一个方法论¶
ConvNeXt(arXiv:2201.03545)做的事是:拿一个标准 ResNet,按 Swin Transformer 的配方逐项改造——换宏观阶段比例、换大卷积核、换 GELU、换 LN、减少归一化层数量、用 AdamW 和更长的训练——最后纯卷积网络追平了 Transformer。
对读这本书的人,这个实验的价值在于它划清了一条界线:很多时候被归因于"新架构"的收益,其实来自随新架构一起引进的训练配方。所以后面三篇附录在拆解每个模型时,都会尽量分开写两件事:
- 它改了计算图(新的注意力形式、新的路由、新的残差结构)——这是第一册的内容;
- 它改了训练配方(数据量、优化器、精度、调度)——这是第二册的内容。
厂商的技术报告通常把两者混在一起报告收益。读报告时主动拆开,是判断一个新方法值不值得跟的基本功。
核心问答¶
Q1:我完全没做过 NLP,直接从第 2 章开始读会不会缺东西? 不会缺架构上的东西。真正需要补的只有 tokenizer(第 1 章讲)和"自回归生成"这个推理形态(第 1、4 章讲)。注意力、残差、归一化、FFN 你都熟。
Q2:既然 ViT 就是 Transformer,我能不能把视觉里的调参经验直接搬过来? 架构级的经验可以(比如 Pre-LN 更好训、加深比加宽更省参数)。训练配方级的经验基本不能搬,A.7 那张表就是清单。最容易出事的是 epoch 数、Dropout 和 weight decay 的作用范围。
Q3:为什么 LLM 不用 BatchNorm,而扩散模型里还能看到 GroupNorm? 因为扩散模型的输入是定长的特征图,没有因果约束,batch 内也不需要跨位置对齐。约束不同,选择就不同。判断标准始终是 A.4 那四条。
Q4:CLIP 这种双塔结构在语言模型里还有对应物吗? 有,在检索侧。RAG 的向量检索器就是双塔对比学习训出来的(第三册)。但生成主干是单塔解码器,这点没变。
Q5:我该按什么顺序读这四篇附录? A 读完就可以直接进正文。B、C、D 三篇建议在读完对应正文章节之后再读——比如读完第 9 章 MoE 再去看 C.2 的 Mixtral 和 C.6 的 DeepSeek-V3,那时候配置表上的每个数字才有意义。