Chapter 06

自检:动手回想 + 跨章辨析

前五章铺完——本章不教新东西,靠动手回想把零散知识逼成可调用的判断力。先合上前面的章节再答,答案全在 <details> 里。

流畅性错觉

三个最危险的自我感觉:「我读得很顺」「我做题很快」「我没卡壳」。这三种感觉都不代表知识可以被提取和迁移——只有合上教程、从空白纸上写出答案,才算检验了真正的掌握程度。每道题先停一下再点开答案。

三层梯度 · 怎么用这一章

  • 概念层(§6.1):回忆定义和直觉,卡住就回对应章节补读。
  • 原理层(§6.2):解释机制背后的数学逻辑,要求说出"为什么"而不只是"是什么"。
  • 应用判别层(§6.3):给定场景,横跨多章作出有取舍的判断——这才是知识真正落地的形式。
难 易 §6.1 概念层(Remember / Understand) token · embedding · logits · QKV 角色 · 因果掩码 · 位置编码 · FFN 职责 · 三形态 §6.2 原理层(Apply / Analyze) √d_k 缩放 · pre-norm · 多头 · KV-cache · 训练/推理 · O(n²) §6.3 应用判别层(Evaluate) 5 跨章场景 · 任务选型 · 部署权衡 ch01–03 ch02–04 ch01–05
图 6.1题库三层梯度。越往上越接近真实工作中的判断。注意:底层概念题最多也最像背诵,但顶层应用判别层才是面试和落地真正考的——能背出 pre-norm 的定义,不代表知道什么时候选它、它换了什么代价。

6.1概念层(Remember / Understand)

先合上全部章节,逐题默写答案,再展开对照——这是动手回想,不是再读一遍。

Q 6.1.1

token、embedding、logits 三者各是什么?说出它们在前向传播里的先后顺序和各自的数据类型/形状。

展开答案(先停一下再点)

token:文本的最小离散单位,是整数 id(词表 id),模型看到的原始输入。embedding:把 token id 查表映射成 d_model 维连续向量,进入神经网络的第一步——形状 (n, d_model)。logits:最后一层 unembedding 后的原始分数向量,softmax 之前,形状 (n, vocab_size);softmax(logits) 得到下一个 token 的概率分布。顺序:token id → embedding 查表 → N 层 block 变换 → unembedding → logits → softmax → 概率。

参考:→ ch01 §1.1 序列建模

Q 6.1.2

在 scaled dot-product attention 里,Q、K、V 各扮演什么角色?用"字典查找"这个比喻翻译一遍。

展开答案(先停一下再点)

Q(query):当前位置想要什么信息——相当于查询词。K(key):每个位置"声称自己是什么"——相当于字典的键。V(value):每个位置真正携带的信息内容——相当于字典的值。计算 QKᵀ 算出 query 与所有 key 的相似度,softmax 归一化成权重,再对所有 V 加权平均,得到本位置聚合后的表示。这是一个可微的"软字典查找":不像硬字典只取一个 value,而是按相似度把所有 value 混合。

参考:→ ch01 §1.3 attention 直觉 → ch02 §2.1 scaled dot-product

Q 6.1.3

因果掩码为什么要在 softmax 之前把未来位置置为 −∞,而不是在 softmax 之后置为 0?

展开答案(先停一下再点)

softmax 之后置 0 会改变整行的分布形状:先 softmax 再强制归零,各位置权重之和不再等于 1,剩余权重的比例也发生了变化,等于悄悄重新分配了注意力。在 softmax 之前置 −∞,经过 softmax 时 exp(−∞)→0,未来位置自然归零,同时其余位置在各自 exp 之后重新归一——分布形状正确,且数学上等价于"这些位置不存在"。

参考:→ ch02 §2.3 因果掩码

Q 6.1.4

为什么 Transformer 必须注入位置编码?不加会怎样?(提示:说出"置换等变性"这个性质)

展开答案(先停一下再点)

点积 attention 是置换等变的:把输入序列的 token 打乱顺序,输出也同样打乱,模型看到的本质上是一个无序的 embedding 集合(set),而不是序列。"dog bites man"和"man bites dog"在不注入位置前,注意力分数完全相同——模型无法区分语序。位置编码(正弦或 RoPE)把位置信息叠加到 embedding 或 Q/K 旋转上,让模型能感知词的顺序。

参考:→ ch03 §3.1 位置编码

Q 6.1.5

在一块 Transformer block 里,FFN 负责什么?它和 attention 的分工边界在哪里?

展开答案(先停一下再点)

Attention 是 token 之间交换信息的唯一算子(通信);FFN 在 attention 之后对每个位置独立加工(计算),各位置之间无横向连线。FFN 的作用:把 attention 汇集来的跨位置信息通过非线性变换进一步提炼,同时作为"键值记忆"存储事实(Geva 2021:W₁ 的行像 key,W₂ 的列像 value)。FFN 占 transformer 约 2/3 的参数量——知识主要住在这里,而不是 attention 权重里。

参考:→ ch01 §1.4 通信/计算框架 → ch03 §3.4 FFN

Q 6.1.6

encoder-only、decoder-only、encoder-decoder 三种形态各适配什么类型的任务?各举一个代表模型。

展开答案(先停一下再点)

Encoder-only(双向):适合理解类任务——分类、序列标注、embedding。代表:BERT。不适合生成(双向 attention 看到整个序列,生成时会泄露答案)。Decoder-only(因果):适合生成类任务——文本续写、问答、代码生成。代表:GPT 系列、Llama。注意:它没有 cross-attention,不是 encoder-decoder 的"一半"。Encoder-decoder:适合 seq2seq——机器翻译、摘要。代表:T5、原版 Transformer。encoder 双向理解源序列,decoder 因果生成目标序列,两者通过 cross-attention 连接。

参考:→ ch01 §1.5 三种形态 → ch03 §3.7 enc-dec

6.2原理层(Apply / Analyze)

每道题要求说出机制背后的逻辑链,不只是复述结论。

Q 6.2.1

为什么 scaled dot-product attention 要除以 √d_k?把方差论证说完整。

展开答案(先停一下再点)

假设 q、k 的各分量是零均值、单位方差的随机变量,则 q·k = Σᵢ qᵢkᵢ 是 d_k 项之和,每项方差为 1,总方差为 d_k,标准差为 √d_k。当 d_k 大(如 64 或 512)时,点积数值量级达 √d_k(d_k=64 时约 8,d_k=512 时约 22),把 softmax 推进近 one-hot 区(某一位接近 1,其余接近 0),该区域的导数 σ(1−σ)≈0——梯度消失。除以 √d_k 把方差重新拉回 1,softmax 的输入保持温和,梯度稳定。

参考:→ ch02 §2.2 为什么除以 √d_k

Q 6.2.2

现代 LLM 普遍使用 pre-norm 而不是原版 post-norm。说出两者的区别,以及切换到 pre-norm 的真实原因(提示:不是因为质量更好)。

展开答案(先停一下再点)

Post-norm(原版):LayerNorm(x + Sublayer(x))——归一化在残差相加之后,破坏了 identity 捷径(归一化把 x 改变了);超过 12 层时训练脆弱,需要精心 warmup 和初始化。Pre-norm(现代):x + Sublayer(RMSNorm(x))——归一化在 sublayer 内部,残差捷径直接通过不被归一化;任意深度下梯度 ∂L/∂x 至少有原始梯度这一项,训练无需 warmup。切换的真实原因是可扩展性和深度稳定性,不是质量提升——浅层模型上 pre-norm 甚至略逊 post-norm,这个权衡是反直觉的。

参考:→ ch03 §3.3 归一化 → ch05 §5.2 现代 norm

Q 6.2.3

多头 attention 相比单头多了什么?多头机制是否真的会让不同头专门化?

展开答案(先停一下再点)

单头只产生一个加权平均,承诺一种混合方式;多头把 d_model 切成 h 份,每头在 d_model/h 维子空间里独立学习一种关系,最后 concat 再用 Wᴼ 投回原维度——总 FLOPs 与单头几乎相同(免费获得多样性)。真实专门化:已有实验证据(Olsson/Elhage)发现 induction heads,专门做"找到当前 token 上次出现的位置,然后 attend 到那个位置的下一个 token"这个模式,与 in-context learning 能力相关,且在训练中相变式突现。不是所有头都专门化,但确实有头会专门做句法依存、共指等任务。

参考:→ ch02 §2.4 多头

Q 6.2.4

KV-cache 缓存的具体是什么?显存成本随哪些因素增长?(给出公式轮廓)

展开答案(先停一下再点)

KV-cache 缓存的是过去每个 token、每一层、每个注意力头的 K 和 V 投影矩阵(不是权重,是激活值)。没有缓存时,每生成一个新 token 就要对所有历史 token 重算一遍 K 和 V;有缓存则只算当前新 token 的 Q,再与缓存的 K/V 做一次注意力。显存成本公式轮廓:

seq_len × layers × heads × head_dim × 2 × dtype_bytes

以 7B 典型配置为例(32 层,32 头,head_dim=128,fp16=2 bytes,seq=8192)约 8 GB——仅 KV-cache 就和模型权重相当。成本随序列长度、层数、头数×head_dim(即 d_model)线性增长,这正是催生 GQA、MLA 等技术的根本动力。

参考:→ ch04 §4.4 KV-cache

Q 6.2.5

训练时为什么所有位置能并行计算,推理时却必须串行逐 token 生成?说出两者数据流的根本差异。

展开答案(先停一下再点)

训练(teacher forcing):ground truth 序列在训练时全部已知,因果掩码保证位置 t 只能看到 1…t,但所有位置的掩码矩阵可以一次算完——GPU 对所有位置并行做矩阵乘法,梯度全部在同一次前向/反向中传播。推理(自回归):没有 ground truth,第 t 步的输出必须追加到输入里,才能生成第 t+1 步——每一步的输出依赖上一步,无法跳过,天然串行。陷阱:很多人先实现训练式前向,纳闷"为什么推理出乱码"——少了把当步输出喂回输入再跑下一步的循环。

参考:→ ch04 §4.1 训练 → ch04 §4.2 推理 → ch04 §4.3 不对称性

Q 6.2.6

Attention 的 O(n²) 瓶颈,到底贵在算力还是显存?两者的来源有什么区别?

展开答案(先停一下再点)

两者都贵,但显存瓶颈在长上下文下更为致命。QKᵀ 产生 n×n 的注意力分数矩阵,标准实现必须把这个矩阵落地(存到显存),才能做 softmax 再乘 V——显存消耗随 n² 增长;n=8192 时每头约 268M 个浮点数。算力层面,矩阵乘法本身也是 O(n²·d),但现代 GPU 对矩阵乘法极度优化,算力相对不是最紧张的资源。FlashAttention 的核心贡献正是通过 SRAM 分块避免落地 n×n 矩阵,把显存开销降到 O(n),同时输出结果与标准 attention 完全一致(非近似)。

参考:→ ch04 §4.5 O(n²) → ch05 §5.5 FlashAttention

6.3应用判别层(Evaluate — 跨章辨析)

每道题都横跨两章以上,要求作出有取舍的判断,而不只是复述概念。先说清楚选什么,再说为什么,以及放弃了什么。

场景 A · 任务选型

给三个任务:① 情感分类(正面/负面),② 写作续写(给前半段故事,续写后半段),③ 中英翻译。各应选 encoder-only / decoder-only / encoder-decoder,说出理由。

涉及:ch01 #three-forms + ch03 #enc-dec

展开答案(先停一下再点)

① 情感分类 → encoder-only:分类需要对整句话有双向理解("虽然开头不好,但结尾很好"这类转折靠双向上下文判断);不需要生成,用 encoder 输出的 [CLS] token 表示接分类头即可。代表:BERT fine-tune。

② 续写 → decoder-only:给定前缀、生成后续文本,正是 decoder-only 的主场——因果自回归生成。不需要独立的 encoder 理解前缀,decoder 本身读入前缀再续写。代表:GPT、Llama。

③ 中英翻译 → encoder-decoder:源语言和目标语言是两个不同序列,encoder 双向理解整个中文源句,decoder 因果生成英文目标句,两者通过 cross-attention 对齐——这正是 encoder-decoder 的设计目标(原版 Transformer 就是为翻译而生)。代表:T5、MarianMT。注意:现代大 decoder-only 模型也能做翻译,但在架构设计层面 enc-dec 更自然。

场景 B · 显存被吃爆

部署 LLM 推理时显存被 KV-cache 占满。列出 GQA、MLA、sliding-window attention、FlashAttention 四个手段,说明各自压的是哪个成本(KV-cache 显存 vs O(n²) 中间矩阵),以及哪些可以叠加使用。

涉及:ch04 #kv-cache ch04 #on2 + ch05 #kv-heads ch05 #flash ch05 #longctx

展开答案(先停一下再点)

GQA(Grouped Query Attention):压 KV-cache 显存。把 Q 头分组,每组共享一个 K/V 头,KV-cache 大小 = 总 Q 头数 / 组数。Llama 3 全系使用,现代 LLM 主流。不影响 O(n²) 中间矩阵问题本身。

MLA(Multi-head Latent Attention,DeepSeek-V2):压 KV-cache 显存(更激进)。把 K/V 压缩成低秩潜向量,按需 up-project,DeepSeek-V2 省 93.3% cache。截至 2025 中仍属个别实现,GQA 是更广泛主流。

Sliding-window Attention:压 KV-cache 显存 + O(n²) 算力(同时缓解)。每个 token 只 attend 到固定窗口 W 内的 token,KV-cache 上限锁死为 W 而不随序列增长,注意力复杂度降为 O(n·W)。代价:丢失远距离依赖(需要与全局注意力交替才能覆盖全程)。

FlashAttention:仅压 O(n²) 中间矩阵显存,不减少 KV-cache。通过 SRAM 分块避免落地 n×n 矩阵,输出与标准 attention 完全一致(非近似);算力和显存效率都更高,但 KV-cache 本身大小不变。

叠加方案:GQA + FlashAttention 完全可以叠加(分别针对不同成本);GQA + sliding-window 也可叠加(Mistral 同时用两者);MLA 与 FlashAttention 理论可叠加但实现更复杂。FlashAttention 与 sliding-window 可以结合(FlashAttention 3 支持分块的 sliding-window kernel)。

场景 C · 推理乱码

"模型训练 loss 正常下降,但一推理就输出乱码"——给出根因,并说出它所在的机制。

涉及:ch04 #asymmetry

展开答案(先停一下再点)

最可能的根因:推理代码少了自回归喂回循环——把训练式前向直接拿来当推理用,一次性把整个 prompt 喂进去拿输出,没有"把当步输出 token append 到输入、再跑下一步"的循环。训练时有 ground truth(teacher forcing),每步输入都是正确上文;推理时没有 ground truth,必须把自己上步的输出当成下步的输入,缺少这个循环就等于每步都在随机噪声上做预测,输出自然是乱码。这是训练/推理不对称最典型的陷阱:loss 正常下降说明训练逻辑没问题,问题出在推理逻辑上。

参考:→ ch04 §4.3 训练与推理不对称

场景 D · RoPE 与长文本

团队把正弦位置编码换成 RoPE,号称"解决了长文本问题"。这个说法对在哪、不严谨在哪?

涉及:ch03 #pos-enc + ch05 #rope ch05 #longctx

展开答案(先停一下再点)

对的部分:RoPE 把位置信息编码为 Q/K 向量在 2D 子空间的旋转,点积只依赖相对位置距离而非绝对位置,比正弦位置编码(绝对位置,难外推)更适合处理训练中未见过的位置——这是向长文本迈出的一步。现代几乎所有大模型(Llama、Qwen、DeepSeek、Gemma 等)都用 RoPE 取代了正弦编码。

不严谨的部分:RoPE 本身并不能"解决"超出训练长度的外推问题,只是缓解了绝对位置编码的硬墙。128K 上下文需要额外的外推技术:YaRN(ICLR 2024,Llama 3.1 用它扩到 128K,同时把 RoPE base 提到 500,000)、LongRoPE2、iRoPE(Llama 4,部分层不用位置编码)等。换 RoPE 只是必要条件,不是充分条件——"解决了"这个说法过于绝对。

场景 E · 注意力热力图

有人指着一张注意力热力图说"模型在重点看'巴黎'这个词"。这个解读的漏洞是什么?

涉及:ch02 #weights-not-importance

展开答案(先停一下再点)

漏洞:注意力权重只是加权平均的权重,最终输出是 Σ αᵢ Vᵢ。高注意力权重(α 大)并不等于高贡献——V 向量(value)的范数是缺失的另一半。如果"巴黎"对应的 V 向量范数很小(接近零向量),即使 α=0.9,对输出的实际贡献也可能微乎其微;反之,α=0.05 但 V 范数很大的 token 可能影响更强。热力图给人强烈的"模型在看哪里"错觉,但没有同时展示 V 的范数时,这种可解释性结论是误导性的(arxiv 2004.10102 专门研究过这个问题)。

参考:→ ch02 §2.6 权重≠重要度

6.4自己动手画

手画挑战 · 合上教程

不看任何资料,在白纸上画两张图

图一:decoder-only block 完整数据流。画出以下全部元素:输入 x → 第一条残差(x 旁路)→ RMSNorm(pre-norm,在 sublayer 内)→ 因果自注意力(标注 Q/K/V 投影)→ 残差合并 → 第二条残差(x₂ 旁路)→ RMSNorm → FFN(两层,标注 d_model → d_ff → d_model)→ 残差合并 → 输出。注明 norm 在 sublayer 内部(pre-norm),两条残差捷径分别跨过 attention 和 FFN。

图二:训练(并行)与推理(自回归)的数据流对比。左侧画训练:整个序列(含 causal mask 矩阵)一次前向,所有位置输出并行算梯度。右侧画推理:step 1 → token 追加 → step 2 → token 追加 → … 的循环,标出 KV-cache 在哪里被写入和读取。两侧各画一个时间轴,直观显示并行 vs 串行的差异。

画完后,回到 ch03 §3.5 完整 block 和 ch04 §4.3 不对称性 对照:残差连接的位置对了吗?推理循环里有没有画出把输出 token 追加到输入的那一步?