现代续写机器的构造蓝图——每一次手术的下刀点
这一章讲三件事: 模型内部有哪几类零件、每个零件干什么活;经典设计在哪里撞了墙、现代模型用什么改动翻过去的;以及「深度」和「宽度」这两个词为什么值得各占一个坐标轴。 它是全书的枢纽章: 剪枝剪的是「块」和「神经元」,蒸馏对齐的是「中间层输出」,注意力手术动的是「注意力模块」——每一个名词都在本章定义。
1. 这一章讲什么
第 02 章你已经动过刀,但动的是黑箱:知道切 model.layers 能让模型变小,不知道里面到底有什么。这一章打开箱子。读完后你拿到一张零件-手术对照表:哪把刀对付哪个零件1。
它在全书链条里的位置: 它不产生新结论,它给全书供词汇。后面任何一章卡住,回到这里。
2. 顶层全景:三段式,和一摞重复块
这类机器的学名叫 Transformer(你出门会到处撞见这个词)。任何一台现代机器的解剖结构都是三段:输入端(把文字变成数字)→ 一摞完全相同的块(干活的地方)→ 输出端(把数字变回「下一个词的可能性清单」)。
经典款里最出名的一支叫 GPT——一代续写机器的家族名;解剖标本用它的缩小版 DistilGPT2,8200 万参数,零件最少,又保留了经典结构的全部要素2。
块里面的两个主角,职责铁打不动:
| 零件 | 一句话职责 | 在本章 |
|---|---|---|
| 注意力模块 | 语境化:让每个词看别人,消歧义 | 第 4-6 节 |
| MLP 模块 | 知识处理:用训练中学到的知识加工语境 | 第 7-8 节 |
书里反复强调这组分工,原话值得记:注意力做语境化,MLP 把语境化变成知识3。一个例子先放在这里:「泉水」(spring)这个词,注意力负责发现它旁边站着「水」「山」;MLP 负责调用知识——哦,那是 nature 那边的意思,不是季节。
3. 输入端:把词变成带地址的向量
模型不认识字,只认识数。第一站叫嵌入(embedding):一张大字典,给词表里每个编号配一串数——DistilGPT2 的词表有 50257 个条目,每个条目是一串 768 个数4。你输入的每个词,查表领到自己的那一串。
但光有「是什么词」不够。「工人打电话给律师」和「律师打电话给工人」是两件事5。所以还有第二张表:位置嵌入——给句中的每个座位(第 0 到第 1023 个)各配一串数,1024 就是这台机器的上限,也就是它的上下文窗口。两串数直接相加,得到「这个词 + 在第几位」的合成向量6。
之后的 Dropout 层只在训练期起作用:随机暂时关闭一些神经元,防止模型把训练材料背得太死(这毛病叫过拟合);推理时它下班7。
4. 注意力:让每个词看别人
4.1 主走查(上):「spring」为什么不能只靠自己
拿这句贯穿全书的话当走查输入:
"Fresh water flows from the mountain spring daily"
(新鲜的水每日从山泉流出)
走查对象:第 6 个词 spring。
经过第 3 节后,spring 已经有了「词义 + 位置」的向量。但它有个根本缺陷:这句话里的 spring 和「花园在春天复活」那句话里的 spring,查表领到的向量一模一样——模型还没看邻居,不知道这是泉水还是季节8。
注意力干的活:用句子里其他词的信息,修正每个词的向量。看完成风流动后,spring 的向量就被「水」和「山」拉向泉水一侧,被「花」和「季节」拉向季节一侧——同一词、不同句,从此不同9。
4.2 注意力头:十二个各管一摊的小侦探
注意力不是一整个机构,而是多头并行(同时跑好几份小机构)。DistilGPT2 有 12 个注意力头(attention head),每个头是一个完整独立的小型注意力机制。
每个头各专攻一类关系——有的盯句法(主语配动词),有的盯长距离依赖。
有的则盯语义(词义近似);这种分工不是谁指定的,是训练过程中自己长出来的10。
768 维向量怎么分给 12 个头?12 等分,每头拿到 64 维的小空间独自分析,最后把 12 份结果拼回 768 维11。
5. QKV 与 KV cache:注意力的记账本
5.1 每个词的三张牌:Query、Key、Value
每个头的注意力内部,给每个词发三张牌:
| 牌 | 角色 | spring 这句话里的例子 |
|---|---|---|
| Query(查询) | 当前词的提问:「我在找什么?」 | spring 问:「谁跟我是同类?」 |
| Key(键) | 词的标签:「我能提供什么」 | mountain 挂牌:「自然、地理」 |
| Value(值) | 词的真实内容 | mountain 携带的语义本身12 |
配对方式:拿 spring 的 Query 和每个词的 Key 做点积(两个向量对应位相乘再求和,得到一个数,数越大=两向量越对齐)13。
再用 softmax(把一排分数压成一组加起来等于 1 的配比)把分数变成权重;最后按权重把每个词的 Value 掺一份进 spring 的向量。到这里,走查对象的向量完成了它的第一次「看别人」。
5.2 记账问题:1152 个槽
生成文本时模型一次只产一个词,但每个新词都要看全部旧词。总不能每产一词就把旧词全部重算一遍——所以旧的 Key、Value 存起来复用,这本账就叫 KV cache。它随每个新词线性(等量匀速)增长,是最主要的动态内存开销14。
算一笔小账(书里的原题):
那句 spring 例句:8 个词 × 12 个头 × 2 份(K、V 各一)× 6 层
= 1152 个「槽」要一直占着显存[^15]
图说:词数、头数、层数任何一个变大,账本同比例变厚。
这就是长上下文贵的直接原因。
关掉这本账行不行?行,但等于把内存问题换成计算问题——每个词都要从头重算全部旧词的 K 和 V,推理慢到没法用;唯一合理的关账时机是训练,那时整段并行处理,本来就没有「逐词生成」15。
6. GQA:让多个头共用一本账
既然账本是瓶颈,现代模型的答案是少记几份账。三种方案:
| 方案 | 谁跟谁共用账本 | 效果 |
|---|---|---|
| MHA(经典多头) | 不共用,每头全套 K/V | 8 词的账 = 1152 槽 |
| MQA(多查询) | 全部头共用唯一一套 | 省到极致,质量有损 |
| GQA(分组查询:头分小组、组内共用一套) | 省下大头 | 质量几乎不损,已成事实标准16 |
同一笔预算下的容量差(书里的算例,同样 1152 个槽):MHA 存 8 个词;GQA 按四比一分组能存 32 个(+300%);MQA 能存 96 个(+1100%)17。
怎么从结构上一眼认出 GQA?看投影层的尺寸。Llama-3.2-1B 里,Query 的投影是 2048→2048,而 Key、Value 的投影只有 2048→512——K/V 通道只有四分之一宽,就是因为四个头共用一份18。另外注意 o_proj 这一层:各头算完后由它把结果重新拼成一个向量,等价于第 4.2 节说的「拼回 768 维」在现代模型里的样子19。
顺带交代一个后果: 在 MHA 时代,「删掉某个注意力头」是干净的手术——每头权重独立,删了就完了。GQA 让组内头共用 K/V,删单头会碰到别人共用的张量(多维数字表格),容易把机器弄坏。所以本书后面处理注意力冗余时不再剪头,而是整体旁通整层的注意力(第九章)20。
7. MLP:扩张、激活、收缩
走查继续。注意力掺完信息,向量进入同块的 MLP。DistilGPT2 的 MLP 是三步:
768 维 ──扩张──> 3072 维 ──激活函数──> 3072 维 ──收缩──> 768 维
图说:执行顺序以 forward 函数为准,别信结构打印里的定义顺序[^22]。
为什么中间非要停一下? 扩张和收缩各自都是一次线性变换(即矩阵——数字表格——的整批相乘),而线性变换叠线性变换还是线性变换——不停一下,整个 MLP 数学上塌缩成一次矩阵乘,白扩21。
中间那一步叫激活函数(决定每个信号放行还是压小的关卡),经典的叫 GELU:对 3072 个位置的每一个问同一句话——这个信号够不够重要?够就放行,不够就压小。像每个神经元装了一个带调节器的开关——正是这一步「有的放行有的压小」打破了线性22。
扩张的那 3072 个位置就是所谓「神经元」。训练中它们各自长成了模式探测器:有的见地理概念就亮,有的见时间关系就亮23。这个事实是第五章宽度剪枝的立足点——书里那句挖苦值得原样记住:要做金融专家模型,留着检测菜谱的神经元干什么24?
8. GLU:给每个神经元配一个会看上下文的门
经典 MLP 有个概念层面的短板:GELU 的放行标准是固定的,不管现在处理的是泉水还是财报,同一套数学标准从头用到尾25。
现代模型的答案叫 GLU——一种自带闸门的过滤结构;门控(决定放行还是压小的那个闸)是它名字的由来:把「过滤」也变成学出来的、按内容变化的。Llama-3.2-1B 的 MLP 因此从两层变三层:
up_proj(内容路)────「这个词都有哪些含义」──┐
├─逐元素相乘─> down_proj(收缩)
gate_proj(门路)─SiLU─「此刻哪些含义该放行」──┘
图说:门路学的是「该放大谁、该静音谁」;
这套家族的变体按激活函数命名(SwiGLU/GeGLU/ReGLU),本书统称 GLU[^28]。
走查收尾,看 GLU 处理 spring(此时注意力已把「水」「山」掺进向量):内容路 up_proj 把它可能的多种含义都点亮——泉水、季节、甚至机械弹簧;门路 gate_proj 看着同样的上下文,给地理含义的神经元发高值、给金融含义的发近零值;两路逐位相乘,季节和弹簧被静音,泉水被放大,最后收缩输出26。
一条硬约束,全书第五章的地基: 内容路和门路是成对工作的——第 i 个门只管第 i 份内容。删神经元必须两边一起删,只删一边,门就对着空气过滤了;所以重要性必须成对评估27。
9. 形状:深度与宽度
零件认完,该有坐标系了。模型的两个结构维度:
- 深度 = 堆了多少个块。DistilGPT2 是 6,Llama-3.2-1B 是 16。更深意味着更多轮次序贯精化,代价是延迟(等结果的时间)逐层累加28;
- 宽度 = MLP 中间维多大。它决定每一步能调动多少知识,也是参数和内存的大头29。
同为现代模型,选型哲学却分两派:宽模型(如 Llama-3.2-1B,扩张四倍)每层处理能力大;深窄模型(如 Qwen3-0.6B、Gemma-3-270M,扩张三倍)靠更多层换精化次数。深度剪枝(第四章)动的是深度轴,宽度剪枝(第五章)动的是宽度轴30。
现代层里还有两个新面孔,一句话各交代:RoPE 用「词与词的相对距离」取代固定座位号的位置嵌入,所以现代模型能开十万级上下文;RMSNorm 是 LayerNorm 的省钱版,稳定训练的效果相近、计算更便宜31。
10. 激活:模型此刻在想什么
最后一个词,也是全书方法论的支点。权重是训练固化的参数,静态;激活是某个具体输入流过时神经元实际输出的数值,每次都不同32。以 Llama-3.2-1B 为例:每个 MLP 层有 8192 个神经元,每个神经元揣着 2048 个权重——权重是它的「性格」,激活是它「此刻的反应」。
看激活能看出什么?书里给的两个示例(明说是虚构的示意,真实测量在后面 章节):处理「doctor」时 1247 号、2891 号神经元强烈点亮;「he」和「she」引发的激活差在中间几层高出三倍——顺着这种线索能定位机器把哪些人群和哪些角色绑在了一起33。
测量激活 = 诊断机器怎么想;第四章给它装上标尺(标尺是余弦——量两个向量方向有多一致的相似度),第五章用它给神经元打分,第八章用它找出多余的注意力层34。
11. 作者的判断与证据
给了证据的: MHA/GQA/MQA 的容量算术(1152 槽的三种分法)是书内的确定性计算;Llama 的 GQA 从结构尺寸(2048 vs 512)直接可验;DistilGPT2 与 Llama 的结构差异来自打印模型结构,谁跑谁都一样。
书的立场(未证明但影响后面的取舍): 「块内两个模块分工不变」是作者反复声明的架构不变量——注意力再怎么优化,管的都是语境化。若未来架构打破这个分工(比如块内不再有独立 MLP),本书的手术地图需要重画。
外部补一笔(不在书里,来自通用知识): 注意力机制出自 2017 年论文《Attention is all you need》——书里提到它时是当常识用的,这里给出处35。
12. 边界与局限
-
本章只拆单向续写这一类文本机器。 多模态(图文混合的)结构、双向理解加单向生成的其他架构不在蓝图内;书末练习让读者自己去翻图文机器的配置文件找不同36。
-
「头有分工」是涌现(没人设计、训练中自己长出来)现象的简化讲法。 书里明说:头的分工是训练的副产品,不可直接解读,图上的标签只是示意37。
-
实现细节不在本章。 想亲手实现注意力,作者推荐的是 Raschka 的《Build a Large Language Model (From Scratch)》38——顺带一提,这本书也在我们书架上。
-
扩张率没有理论最优。 Llama 上发现更低扩张率某些任务反而更好,Gemma 上结果完全不同——答案要等第五章的实验39。