第 15 章 Transformer 架构
第 15 章 Transformer 架构
本章把「注意力」从一个辅助对齐技巧,推导成唯一的序列建模算子:先解释 RNN seq2seq 的瓶颈,再逐步建立 Q/K/V、缩放、多头、位置编码、残差与归一化、掩码,最后给出复杂度分析与稀疏注意力家族。
学习目标
读完本章,你应当能够:
- 说明固定长度上下文向量为什么构成 RNN seq2seq 的瓶颈,注意力如何解除该瓶颈;
- 用「软寻址」解释 Q/K/V,并完整推导缩放点积注意力中
√d_k的来源(内积方差随维度的增长)与不缩放的后果; - 写出多头注意力的维度账本与参数量,说明每头维度
d_k = d_model/H的约束; - 说明自注意力为什么是置换等变的,比较正弦位置编码、可学习位置编码、RoPE、ALiBi 的性质与长度外推能力;
- 辨析 Post-LN 与 Pre-LN 的梯度差异,说明大模型为何普遍采用 Pre-LN + RMSNorm;
- 构造因果掩码,解释掩码与 softmax 中
−∞的配合为什么等价于「只在可见位置归一化」; - 推导
O(N²d)时间与O(N²)显存的来源,比较滑窗、Longformer、BigBird、Linformer、Performer 的近似思路与代价,并实现滑动窗口注意力。
前置知识检查
| 你需要知道 | 在哪一节补齐 |
|---|---|
| 矩阵乘法与批量矩阵乘的维度规则 | 本章 15.3.1 节的维度账本与 15.3.2 节的 Q@Kᵀ 形状 |
| Softmax 的数值稳定性(减最大值) | 本章 15.6 节结合 −∞ 掩码复述(完整版见第 5 章) |
方差的可加性 Var(Σxᵢ) = ΣVar(xᵢ)(独立时) | 本章 15.2.2 节推导 √d_k 时显式列出 |
| 残差连接与梯度流 | 本章 15.5 节从 ∂y/∂x = ∂F/∂x + I 讲起(见第 13、14 章) |
| 层归一化(LayerNorm)的统计维度 | 本章 15.5.3 节说明它对最后一维归一化 |
| 序列建模、隐藏状态、RNN 展开 | 本章 15.1 节重新叙述,不需要事先掌握 |
15.1 注意力的起源:从 RNN 瓶颈到对齐
15.1.1 固定长度上下文向量的瓶颈
机器翻译的经典结构是 seq2seq:编码器(encoder)逐词读入源句,把全部信息压进最后一个隐藏状态 h_N;解码器(decoder)从 h_N 出发逐词生成目标句。
| |
问题在于 c 是固定长度的:不管源句是 5 个词还是 50 个词,编码器都必须把它塞进同一个 d 维向量。这带来两个后果:
- 信息瓶颈:长句的信息量远大于
d个实数所能承载,解码器必然丢失细节; - 无差别压缩:生成第
j个目标词时真正需要的往往只是源句的一两个位置(例如翻译 “the cat” 时对应「猫」),但c里所有位置的信息被等权混合,解码器无法「按需取用」。
15.1.2 对齐与注意力权重
注意力的想法是:不压缩。保留编码器每一个时间步的输出 h₁ … h_N,让解码器在每一步动态挑选当前最需要的部分:
| |
α_{j,i} 读作「生成第 j 个目标词时,源句第 i 个位置该占多大分量」。它有两个好处:长度不再受限(c_j 随源句长度自适应地加权),可解释(把 α 画成矩阵就是一张对齐热图)。
重要
注意力的本质是可微的软检索:它不做出「选第 3 个词」这样的硬决策,而是输出一个权重分布,再对全部候选做加权平均。权重来自 softmax,所以整条链可导、可端到端训练。这个「软」字是理解后续全部推导的钥匙。
15.2 缩放点积注意力:Q/K/V 与 √d_k
15.2.1 Q/K/V 的直觉:软寻址
把注意力想象成一次数据库检索(或哈希查表),但有两点不同:查询不是精确匹配而是相似度匹配,返回的不是单条记录而是全部记录的加权和。
| 数据库概念 | 注意力记号 | 含义 |
|---|---|---|
| 查询条件 query | Q(N × d_k) | 当前 token 想「问」什么 |
| 索引键 key | K(N × d_k) | 每个 token 能「答」什么特征 |
| 存储值 value | V(N × d_v) | 每个 token 实际提供的内容 |
| 匹配分数 | QKᵀ | 查询与键的相似度(内积) |
| 软寻址权重 | softmax(QKᵀ/√d_k) | 每行是一个概率分布,和为 1 |
| 检索结果 | softmax(...)V | 值的加权汇总 |
三个矩阵都由同一个输入 X(N × d_model)经线性投影得到:
| |
为什么要三套不同的投影,而不是直接拿 X 三两配对? 因为「我想找什么」「我是什么」和「我提供什么」是三种不同的角色。同一个词在作 query 时关心的是主谓关系,在作 key 时提供的是词性特征,在作 value 时贡献的是语义内容。让 W_Q、W_K、W_V 各自学习,模型才获得这种角色分离的表达力。
15.2.2 完整公式与 √d_k 的方差推导
标准写法(对应 【09-02 编程题 1】 的题面公式):
| |
为什么必须除以 √d_k? 设 q、k 是 d_k 维向量,各分量独立、均值 0、方差 1(初始化与 LayerNorm 之后这是合理近似)。内积是 d_k 项之和:
| |
结论:内积的方差随 d_k 线性增长,量级是 √(d_k)。 于是 d_k = 64 时分数典型波动范围约 ±8,d_k = 512 时约 ±22。
不缩放会怎样? 分数的一大一小的差距被放大后送进 softmax:
| |
设两个分数差 Δ。softmax 的雅可比是 ∂softmax_i/∂z_j = softmax_i(δ_ij − softmax_j),当某个分量接近 1 时,其余分量的导数趋于 0 —— 这就是饱和区。
| |
后果是梯度消失:softmax 输出的梯度趋近于零,W_Q、W_K 几乎收不到更新,训练在早期就停滞。除以 √d_k 把分数方差重新拉回 1 量级,使 softmax 工作在梯度最灵敏的区域。
警告
√d_k 里是每个头的维度 d_k,不是模型维度 d_model。多头注意力中 d_k = d_model/H,例如 d_model = 512、H = 8 时 d_k = 64,缩放因子是 √64 = 8 而不是 √512 ≈ 22.6。把两者搞混是高频错误。
15.3 多头注意力与维度账本
15.3.1 为什么要多头
单头注意力只能输出一个加权平均。如果句子中同时存在「指代关系」「时态一致」「局部搭配」等多种依赖,一个平均分布无法同时表达它们——softmax 每行只有一个分布,注意力只能「聚焦在一处」。
多头注意力把 d_model 切成 H 份并行计算,每份在自己的子空间里学一种关系:
| |
「子空间假设」:不同头会自发分化——有的头盯着相邻词(局部语法),有的头盯着句首(全局主题),有的头负责指代消解。这是一种可观测的经验事实(把每个头的注意力矩阵画出来即可看到分工),而不是理论保证:训练不保证每个头都学到互不相同的模式,实际中常有冗余头可以被剪掉而不明显掉点。
15.3.2 维度账本与参数量
这是编程题(【08-26 编程题 2】)最常考的部分,务必能默写:
| |
对应 【09-09 选择 Q7】:Q ∈ R^(B×L×d) 与 Kᵀ ∈ R^(B×d×M) 相乘,批量矩阵乘只在后两维做矩阵乘,第一维 B 作为批维度对齐保留;后两维 (L×d)(d×M) 内维相消得 L×M,所以结果是 B×L×M。这个 L×M 矩阵就是注意力分数矩阵,第 (i,j) 项表示第 i 个 query 对第 j 个 key 的相关度,行数必须等于 query 个数。
参数量统计(单个注意力模块,含偏置省略):
| |
注意参数量与头数 H 无关:8 个头各用 512 × 64,总和与单头 512 × 512 完全相同。多头不增加参数,只改变计算的组织方式(把它看成「分块 + 并行 + 拼接」,等价于给每个子空间独立归一化与独立 softmax 温度)。
提示
记忆账本的口诀:d_k 是所有形状计算的分母,N 是所有注意力矩阵的边长。任何维度对不上时,先问「这一维是 d_model、d_k 还是 N」。
15.4 位置编码:把顺序注入无先验的结构
15.4.1 自注意力是置换等变的
自注意力对输入序列做的是 softmax(QKᵀ/√d_k)V。若把输入的行按置换矩阵 P 重排(X → PX),则 Q → PQ、K → PK、V → PV:
| |
也就是说:打乱输入顺序,输出只是被同样打乱,模型本身完全察觉不到顺序变化。「猫追狗」与「狗追猫」在它眼里是同一个多重集合。这与 RNN 的时序递推、CNN 的局部窗口形成鲜明对比——那两者天然含顺序先验。
所以顺序必须显式注入。通用做法是给每个位置 i 构造一个向量 p_i,与词嵌入相加(或拼接):
| |
15.4.2 正弦位置编码与相对位置性质
原始 Transformer 用固定公式(不学习):
| |
其中 i 是位置,k 是维度索引(偶数维用 sin,奇数维用 cos)。波长从 2π 到 10000·2π 几何级数分布,于是低维捕捉细粒度位置、高维捕捉粗粒度位置。
为什么它能表达相对位置? 用和角公式看位置 i+Δ 与位置 i:
| |
PE(i+Δ) 是 PE(i) 的线性变换,而这个变换矩阵只依赖 Δ、不依赖 i。既然它是线性变换,Q/K 的线性投影就有机会把它「吸收」成只与相对距离有关的项——这就是正弦编码能支持相对位置推理的原因。
15.4.3 可学习位置编码、RoPE 与 ALiBi
| 方案 | 形式 | 是否可学习 | 相对位置 | 长度外推 | 代表 |
|---|---|---|---|---|---|
| 正弦编码 | z_i = x_i + PE(i) | 否 | 通过线性关系间接获得 | 公式对任意 i 有定义,但训练分布外的位置效果差 | 原始 Transformer |
| 可学习编码 | z_i = x_i + E[i],E 为 L_max × d 参数量 | 是 | 无显式结构,靠数据学 | 差:超出 L_max 无参数可用 | BERT、GPT-2 |
| RoPE | 对 q、k 按二维子空间旋转角度 θ = i·ω | 否(角度固定) | 内积只依赖 i − j | 较好,可配合插值/NTK 缩放外推 | LLaMA、Qwen、GPT-NeoX |
| ALiBi | 不编码位置,直接在分数上加线性偏置 −m·(i−j) | 斜率 m 固定 | 显式只依赖距离 | 好,训练短序列即可外推 | BLOOM、MosaicML |
RoPE(rotary position embedding)的核心思想:不用加法,而是把 q、k 按位置相关的角度做旋转。对每一对维度 (2t, 2t+1) 施加旋转矩阵 R(i, θ_t):
| |
最后一步用了旋转矩阵的正交性 R(a)ᵀ = R(−a) 与 R(−i)R(j) = R(j−i)。于是内积只依赖相对距离 j − i,且不改变向量模长。这是 RoPE 被广泛采用的原因:相对位置性质是结构性保证的,不是学出来的。
ALiBi(attention with linear biases)的思路更直接:完全不动 q、k,只在分数矩阵上加一个与距离成正比的惩罚:
| |
m_h 是每个头固定的斜率(几何级数,如 1/2, 1/2², …)。距离越远惩罚越大,等价于给模型一个「近处优先」的强先验。它的外推优势来自形式简单:加性偏置对任意长度都成立,不依赖训练时见过的最大长度。
长度外推问题:模型在 L = 4096 上训练,推理时喂 8192 个 token,性能通常明显下降。原因有二:位置编码从未见过 i > 4096(可学习编码直接失效,正弦与 RoPE 虽可计算但分布外);注意力分布本身也没在更长序列上校准过。常见补救是位置插值(把推理位置 i 按 i·L_train/L_infer 压缩回训练范围)与 NTK 缩放(改变 RoPE 各维频率的基)。
15.5 残差、归一化与前馈网络
15.5.1 残差:每个子层都包一层
Transformer 的每个子层都是 y = Sublayer(x) + x。理由与第 14.5.3 节完全相同:
| |
恒等项 I 保证梯度有一条无损旁路,即使子层内部的雅可比很小,梯度也能回流到浅层。由于 x 与 Sublayer(x) 要相加,两者的最后一维都必须等于 d_model——这也是 W_O 输出 d_model 维的原因。
15.5.2 Post-LN 与 Pre-LN
归一化放在残差里的位置有两种排布:
| |
差异在梯度路径上:
| |
后果是 Post-LN 的深层梯度容易被 LayerNorm 缩放系数压制,需要学习率 warmup 才能稳定训练(原始论文明确要求 warmup);而 Pre-LN 的恒等主路径使梯度尺度与层数基本无关,训练更稳、对学习率与 warmup 更宽容。代价是 Pre-LN 的最终输出范数会随层数增长,因此通常在最后一层后再补一次 LayerNorm(即 final_norm)。
重要
这是「为什么大模型普遍用 Pre-LN」的标准答案:Pre-LN 把恒等路径放在了残差主干上,使梯度不经过归一化的雅可比。它的代价(输出范数漂移)只需一个末端 LayerNorm 就补偿掉,而 Post-LN 的代价(必须精细调 warmup)无法用结构消除。
15.5.3 RMSNorm 的位置
RMSNorm(root mean square norm)是 LayerNorm 的简化:不减均值,只除以均方根,且去掉仿射偏置。
| |
减去均值的那一步在 Transformer 里贡献有限,而它带来的均值计算与同步开销不小,因此 RMSNorm 用更少的运算换到几乎相同的效果,在 LLaMA 系模型里成为标配。它出现的位置仍然是 Pre-LN 的那个位置(子层输入之前),即 y = x + Sublayer(RMSNorm(x))。
15.5.4 前馈网络与激活函数
每个 Transformer 层里,注意力后面还有一个位置独立的前馈网络(FFN, feed-forward network):
| |
它的作用:注意力负责跨位置混合信息(token 之间交换内容),FFN 负责逐位置的非线性变换(对每个 token 的表示做加工)。两者分工明确——注意力是唯一的跨位置算子,FFN 是唯一的非线性算子(若去掉 FFN,整个模型退化为若干线性投影与 softmax 的叠加,表达力大幅下降)。
现代变体把两层线性改成门控形式(GLU 家族):
| |
SwiGLU 多引入一个投影 W₃,为了保持参数量不变,实践上把 d_ff 从 4 d_model 下调到约 (8/3) d_model。
参数量占比是一个常考的估算题:
| |
所以「Transformer 的多数参数在 FFN 里」这句话是对的——这也是 MoE(专家混合)把 FFN 换成多个专家的原因:改一个模块就能把参数量放大若干倍,而注意力保持共享。
15.6 编码器、解码器与掩码
15.6.1 三种用法
| 结构 | 每个位置能看到 | 训练目标 | 典型用途 | 代表 |
|---|---|---|---|---|
| encoder-only | 全序列(双向) | 掩码语言模型(完形填空) | 理解类:分类、抽取、句向量 | BERT、RoBERTa |
| decoder-only | 只有自己及左侧 | 下一 token 预测 | 生成类:对话、续写、代码 | GPT 系列、LLaMA |
| encoder-decoder | 编码器双向,解码器带因果掩码并交叉注意编码器输出 | 序列到序列 | 翻译、摘要、语音识别 | T5、BART、原始 Transformer |
三者的差别只在可见性与训练目标,模块本身完全一样。所以「Q@Kᵀ 的维度」这类问题与结构无关,永远是 B×L×M。
15.6.2 因果掩码的构造
自回归生成要求第 i 个位置不能「看到」未来的 j > i,否则训练时就能直接抄答案。做法是构造一个下三角掩码矩阵:
| |
实现上只需 torch.tril(torch.ones(N, N))。它对应 【09-02 编程题 1】 里滑动窗口掩码的「同一族」思路:窗口掩码 |i − j| ≤ ω 是把上下三角都截断,因果掩码是只保留一侧。
15.6.3 掩码与 −∞ 的配合
掩码不是「算完再删」,而是在 softmax 之前把被屏蔽的分数改成 −∞:
| |
为什么这样等价于「只在可见位置归一化」? 因为 exp(−∞) = 0:
| |
被屏蔽位置的 exp(−∞) = 0,于是它们既不进分子也不进分母——分母 Σ_t 虽然形式上写的是对所有 t 求和,实际有效项只有可见位置。把分子分母同时限制在可见集合上,正是「只在窗口内归一化」的定义。这就是滑动窗口注意力不需要为每行单独切片的根本原因。
数值稳定的前提:每行至少要有一个有限分数,否则减最大值会得到 −∞ − (−∞) = NaN。因果掩码下 j = i 自己一定可见;滑动窗口下 |i − i| = 0 ≤ ω 同样保证自己可见。这个细节在编程题里是必须说明的正确性依据。
警告
掩码必须在 softmax 之前生效。若先算 softmax 再乘 0/1 掩码,被屏蔽位置的概率质量已经被分走,结果是「不可见位置的权重被抹掉但可见位置的权重没有重新归一化」,总和不等于 1,输出尺度整体偏小。
15.7 复杂度分析与稀疏注意力家族
15.7.1 O(N²d) 与 O(N²) 的来源
逐个算子数一遍(单层、单头、忽略常数):
| |
于是(把 d_k、d_v 统一记作 d):
| |
关键认识:O(N²) 的显存不是「模型的固有需求」,而是 softmax(QKᵀ) 这个物化中间矩阵的开销。这为两条优化路线留了口子:
- 不物化整个
N×N矩阵 → FlashAttention(分块 + online softmax,把中间结果留在片上内存); - 不计算全部
N²个分数 → 稀疏注意力家族(只算被选中的位置对)。
注意
FlashAttention 只是常数因子与访存层面的优化,它不改变 O(N²) 的渐进复杂度,因为它算的仍然是精确的稠密注意力。第 19 章会给出 online softmax 的完整推导与 IO 复杂度分析,本章只建立「为什么要分块」的动机。
15.7.2 稀疏注意力家族
| 方法 | 近似思路 | 复杂度 | 代价与限制 |
|---|---|---|---|
| 滑动窗口(sliding window) | 每个 query 只看 |i − j| ≤ ω 的邻居 | 时间 O(Nωd),显存 O(Nω) | 感受野只有 ω,需多层堆叠才能传播全局信息;ω 需与任务匹配 |
| Longformer | 滑窗 + 少量全局 token(如 [CLS])对所有位置双向注意 | O(Nω),ω ≪ N | 全局 token 数量是超参,过多则退回 O(N²) |
| BigBird | 滑窗 + 全局 + 随机稀疏连接(三者混合) | O(N)(ω、全局数、随机数均为常数) | 有理论上的图灵完备/通用近似保证,实现较复杂 |
| Linformer | 假设注意力矩阵低秩,把 K、V 从 N 投影到固定长度 k | 时间与显存均 O(N) | 低秩假设在长序列上不总成立;k 太小会掉点 |
| Performer | 用核方法近似 softmax:exp(qᵀk) ≈ φ(q)ᵀφ(k),从而交换乘法顺序 | 线性 O(N) | 近似有误差,核函数选择影响大,长序列精度通常弱于精确注意力 |
共同的取舍是:稀疏或低秩近似把 N² 降到 N·ω 或 N,代价是放弃了「任意两个位置都能直接交互」的完备性。它们都依赖同一条实证规律——大多数任务的依赖具有局部性,远距离 token 通过多层堆叠间接交互即可(这正是 【09-02 编程题 1】 题面给出的动机)。是否掉点取决于任务对长程依赖的真实需求。
15.7.3 滑动窗口注意力的实现
对应 【09-02 编程题 1】:窗口掩码(|i − j| ≤ ω,两端自动截断)→ 缩放打分 → 窗口内 softmax(减窗口内最大值)→ 对 V 加权求和 → 非法参数返回 0。
| |
三个易错点:① 归一化权重只是展示精度,不能先量化成 2 位小数再乘 V(否则末位会差 0.01);② 输出要处理负零,-0.00 应归成 0.00;③ 非法输入的分支要在读矩阵之前判断,否则会先读到脏数据再报错。
15.7.4 与 RNN/CNN 的对比
| 维度 | RNN | CNN | Transformer |
|---|---|---|---|
| 每层计算复杂度 | O(N d²) | O(k N d²)(k 为核宽) | O(N² d + N d²) |
| 最长路径(依赖距离) | O(N),随距离线性增长 | O(N/k),需堆叠 | O(1),任意两位置一步直达 |
| 并行性 | 差(时间步串行,无法在 N 上并行) | 好 | 好(整个序列一次性矩阵乘) |
| 归纳偏置 | 强:顺序、递推 | 中:局部性、平移等变(见第 14.5 节) | 无顺序先验,必须靠位置编码注入 |
| 长序列瓶颈 | 梯度消失 + 串行 | 感受野增长慢 | N² 时间与显存 |
| 显存峰值位置 | 激活随层数 | 特征图 | 注意力矩阵 N×N |
为什么 Transformer 取代了 RNN? 关键不是「更准」,而是可并行:RNN 的第 t 步依赖第 t−1 步,无法把序列长度摊到 GPU 的并行度上;Transformer 把 N 个位置一次性变成矩阵乘,同时最长依赖路径从 O(N) 降到 O(1),长程依赖更容易学。代价是 N²,而这正是 15.7.2 节全部方法要解决的问题。
本章小结
| 关键结论 | 一句话表述 | 常见错误 |
|---|---|---|
| 注意力的起源 | 固定长度上下文向量是瓶颈,注意力用变长加权替代压缩 | 以为注意力只是为了可解释性 |
| Q/K/V 直觉 | 软寻址:query 找 key,按相似度对 value 加权求和 | 把三者当成同一个投影 |
| 缩放因子 | Var(qᵀk) = d_k,故除以 √d_k;不缩放则 softmax 饱和、梯度消失 | 用 √d_model 而不是 √d_k |
| 多头 | 参数量与头数无关,只把 d_model 切成 H 个子空间并行 | 以为多头增加参数量 |
Q@Kᵀ 维度 | 批量矩阵乘只动后两维,(B,L,d)(B,d,M) → B×L×M,行数 = query 数 | 写成 B×M×L 或 B×d×d |
| 位置编码 | 自注意力置换等变,顺序必须显式注入 | 以为 ViT 或 Transformer 自带顺序感 |
| RoPE | 旋转 q、k,使内积只依赖 i − j,且保模长 | 以为 RoPE 是加法位置编码 |
| Pre-LN vs Post-LN | Pre-LN 把恒等路径放在残差主干,梯度不穿过归一化 | 以为 Post-LN 更稳 |
| RMSNorm | 不减均值、无偏置,位置仍在子层输入前 | 以为它替换了残差 |
| 因果掩码 | 下三角,j ≤ i 可见;掩码须在 softmax 之前生效 | 先 softmax 再乘掩码 |
exp(−∞) = 0 | 窗口外概率恒为零,与「只在窗口内归一化」等价 | 以为要逐行切片重算 |
| FFN | 逐位置非线性,占单层约 2/3 参数;SwiGLU 需按 8/3 调 d_ff | 以为注意力是参数大头 |
| 复杂度 | 时间 O(N²d)、显存 O(N²),N² 来自被物化的分数矩阵 | 以为 FlashAttention 降低渐进复杂度 |
| 稀疏注意力 | 滑窗/Longformer/BigBird/Linformer/Performer 用局部性或低秩换线性复杂度 | 以为近似永不掉点 |
| RNN/CNN/Transformer | 差异在并行性、最长依赖路径、归纳偏置与复杂度 | 只说「Transformer 更准」 |
自测题
Q1(推导)设 q、k 是 d_k 维独立同分布向量,各分量均值 0、方差 1。推导 qᵀk 的方差,并说明不除以 √d_k 会发生什么。
答案与解析
qᵀk = Σ_{i=1}^{d_k} q_i k_i。每项期望 E[q_i k_i] = E[q_i]E[k_i] = 0,方差
| |
即内积的波动量级随 d_k 线性增长。不缩放时分数差被放大 √d_k 倍再送进 softmax;softmax 的雅可比是 ∂A_i/∂z_j = A_i(δ_ij − A_j),当某项 A ≈ 1 时其余分量的导数趋于 0,即进入饱和区。d_k = 512 时典型分数差可达 22 量级,exp(22) ≈ 3.6 × 10⁹,分布塌缩成近似 one-hot,梯度几乎为零,W_Q、W_K 得不到有效更新。除以 √d_k 把方差拉回 1,使 softmax 工作在梯度灵敏区。
常见错误:答「防止数值溢出」。溢出只是表象,核心是分布饱和导致梯度消失;√d_k 也远不到浮点溢出的量级。
Q2(计算)d_model = 512、H = 8、d_ff = 2048。写出单层注意力模块与 FFN 的参数量,并说明多头是否增加了参数。
答案与解析
| |
多头不增加参数:每头的 W_Q^(h) 是 512 × 64,8 头拼起来等价于一个 512 × 512(8 × 512 × 64 = 512 × 512)。多头改变的是计算组织方式——在 H 个子空间里各做一次独立 softmax,而不是在 d_model 维上做一次。
常见错误:把每头投影按 d_model × d_model 算,把参数量放大 H 倍;或漏掉 W_O。另注意 SwiGLU 要把 d_ff 从 4 d_model 下调到约 8/3 d_model 才能保持参数量可比。
Q3(辨析)为什么 Transformer 必须加位置编码?正弦编码为什么具备相对位置性质?
答案与解析
必须加的原因:设输入被置换矩阵 P 重排,则 Q → PQ、K → PK、V → PV,而 (PQ)(PK)ᵀ = P(QKᵀ)Pᵀ,因此输出只是被同样重排——自注意力是置换等变的,模型根本无法区分「猫追狗」与「狗追猫」。RNN 的递推与 CNN 的局部窗口天然带顺序先验,Transformer 没有,顺序只能由位置编码显式注入。
正弦编码的相对位置性质:由和角公式,位置 i+Δ 的编码是位置 i 编码的线性变换,且该变换只依赖 Δ:
| |
因 Q、K 是线性投影,这个只依赖 Δ 的变换有机会被吸收进内积,使分数表达相对距离。注意这是**「可表达」而非「保证学会」**:能力由结构给出,是否用起来取决于训练。
常见错误:把「置换等变」说成「置换不变」。置换等变是「输出随输入一起置换」,恰恰说明模型没有任何位置概念。
Q4(辨析/推导)滑动窗口注意力把窗口外分数置为 −∞ 后直接对整行做 softmax。为什么这与「只在窗口内归一化」等价?这个操作安全的前提是什么?
答案与解析
等价性:设第 i 行可见集合 W_i = {j : |i − j| ≤ ω}。因为 exp(−∞) = 0,对 j ∉ W_i 分子为 0,而分母 Σ_t exp(S̃[i][t]) 中 t ∉ W_i 的项也全为 0,于是分母等于 Σ_{t∈W_i} exp(S̃[i][t])。分子分母同时被限制在 W_i 上,正是「只在窗口内归一化」的定义——这就是编程题无需逐行切片、可以保持向量化的原因。
安全前提:每行至少存在一个有限分数,否则减最大值时会得到 −∞ − (−∞) = NaN。因果掩码下 j = i 必可见;滑动窗口下 |i − i| = 0 ≤ ω(要求 ω ≥ 1)同样保证自己可见。
顺序前提:−∞ 必须在 softmax 之前写入。若先 softmax 再乘 0/1 掩码,被屏蔽位置原本占有的概率质量被直接丢弃,可见位置没有重新归一化,该行权重之和小于 1,输出被整体缩小。
常见错误:只答「exp(−∞) = 0」而漏掉「每行至少一个有限值」——当某行全被屏蔽时(如 ω = 0 或掩码构造错误),实现会产生 NaN。
Q5(辨析)比较 Post-LN 与 Pre-LN 的梯度路径,说明为什么大模型普遍选择 Pre-LN,以及 RMSNorm 在其中处于什么位置。
答案与解析
两种排布是 y = LN(x + Sublayer(x)) 与 y = x + Sublayer(LN(x))。梯度路径的差别是:
| |
所以 Post-LN 需要学习率 warmup 才能稳定训练(原始论文明确要求),Pre-LN 对学习率与 warmup 宽容得多;代价是 Pre-LN 的输出范数随层数累积增长,通常在最后一层后补一次 LayerNorm(final_norm)收口。
RMSNorm 的位置:它是 LayerNorm 的简化——不减均值、不带偏置,RMSNorm(x) = γ · x / √((1/d)Σ x_i² + ε)。它替换的是归一化函数本身,位置仍是 Pre-LN 的位置:y = x + Sublayer(RMSNorm(x))。所以「Pre-LN + RMSNorm」是两个独立选择叠加,不是一回事。
常见错误:把 RMSNorm 说成「另一种残差排布」;或认为 Pre-LN 一定精度更高——取舍主要在训练稳定性与调参成本。
Q6(计算)某模型 d_model = 4096、N = 8192、FP16 存储。估算单个头物化分数矩阵 QKᵀ 所需的显存,并说明 FlashAttention 与稀疏注意力各自从哪一侧解决这个问题。
答案与解析
分数矩阵有 N × N = 8192² = 6.71 × 10⁷ 个元素,FP16 每元素 2 字节:
| |
关键是 N² 与 d_model 无关,只由序列长度决定——这就是长上下文的显存瓶颈。
FlashAttention 从「访存」一侧解决:它不改变「算哪些位置对」(仍是精确稠密注意力),而是不把 N×N 矩阵写回 HBM,用分块与 online softmax 把中间结果留在片上 SRAM 逐块累积。它优化的是显存峰值与 IO,渐进复杂度仍是 O(N²)。
稀疏注意力从「算多少」一侧解决:只计算被选中的位置对(滑窗 |i − j| ≤ ω、Longformer 的全局 token、BigBird 的随机连接、Linformer 的低秩投影、Performer 的核近似),把时间与显存降到 N·ω 或 N;代价是放弃「任意两位置一步直达」的完备性,可能掉点。
常见错误:声称 FlashAttention 把复杂度降到 O(N)。它降低的是常数因子与显存峰值,不是渐进复杂度。
与真题的关联
| 真题 | 考查角度 | 对应本章小节 |
|---|---|---|
【09-09 选择 Q7】 Q@Kᵀ 的维度与分数矩阵含义 | 批量矩阵乘只动后两维,(B,L,d)(B,d,M) → B×L×M;行数 = query 数 | 15.3.2 节(维度账本) |
【09-02 编程题 1】 滑动窗口注意力 | 窗口掩码 |i − j| ≤ ω、窗口内 softmax(减最大值)、非法参数返回 0 | 15.6.2、15.6.3、15.7.3 节(含可运行实现) |
【08-26 编程题 2】 未归一化多头点积注意力的维度账本 | 每头 d_k = d_model/H,β = q kᵀ,c = β V,拼接后经 W_p 回 2R 维并加残差 | 15.3.1、15.3.2、15.5.1 节 |
【09-02 选择 Q11】(延伸)prefill/decode 瓶颈 | 注意力与 KV Cache 的显存来源 | 15.7.1 节(第 19 章展开) |
【09-02 选择 Q4】(延伸)算子融合 | 把 RMSNorm 与残差融进同一 kernel | 15.5.3 节(第 19 章展开) |
延伸阅读
- Vaswani 等,Attention Is All You Need(2017):缩放点积注意力、多头、正弦位置编码、Post-LN 的原始定义。
- Bahdanau 等,Neural Machine Translation by Jointly Learning to Align and Translate(2015):注意力机制的起源与对齐可视化。
- Su 等,RoFormer: Enhanced Transformer with Rotary Position Embedding(2021):RoPE 的旋转推导与相对位置性质。
- Press 等,Train Short, Test Long: Attention with Linear Biases Enables Input Length Extrapolation(2022):ALiBi 与外推性实验。
- Xiong 等,On Layer Normalization in the Transformer Architecture(2020):Pre-LN 的梯度分析与 warmup 必要性论证。
- Beltagy 等,Longformer(2020);Zaheer 等,BigBird(2020);Wang 等,Linformer(2020);Choromanski 等,Performer(2021):稀疏与低秩近似四条路线。
- Dao 等,FlashAttention: Fast and Memory-Efficient Exact Attention with IO-Awareness(2022):分块与 online softmax(第 19 章详细推导)。
- 本套书相关章节:第 5 章(Softmax 数值稳定性)、第 12 章(反向传播)、第 13 章(归一化与残差)、第 14 章(ViT 与「无先验 + 位置编码」范式)、第 19 章(FlashAttention、KV Cache、prefill/decode)。