回扣:RoPE 为什么偏偏旋转 Q 和 K,不旋转 V?
本课一问:回扣——RoPE 为什么偏偏旋转 Q 和 K,不旋转 V?
这一课先不碰:RoPE 的频率怎么选、长上下文怎么外推(C2 已讲);好几套 Q/K/V(第 7 课)。
从已有出发
C2 第 4 课留下过一句话:RoPE 不往 embedding 上加任何东西,而是在注意力内部,按位置把 q 和 k 转一个角度;转过之后,qm·kn 只依赖位置差 n − m。当时 Q、K、V 还只是三个名字。现在五课走下来,它们各自的职责已经清楚:
- q·k 决定权重——谁看谁、看多少(第 2–4 课);
- V 决定内容——按权重取回什么(第 5 课)。
锚点 Qwen3.8 的做法是:q_proj、k_proj 投影 → 每个头各做一次 RMSNorm → 对 q、k 旋转 → 打分;v_proj 投影之后不转。而且每个头 256 维里只转 64 维(partial_rotary_factor = 0.25),基数 rope_theta = 10,000,000。
先自己设计:V 也一起转?
Q、K、V 都是同一个 x 投影出来的向量,既然要给 q、k 加位置,顺手把 v 也转了,不是更「一致」吗?
- ① 朴素方案
- ② 它在哪失败
- ③ 改进方案
转 V 之后,「给了」(位置 i)取回的是 Σj wj·R(jθ)·vj。整句平移 Δ,权重 w 不变(打分只看相对位置),但每个 vj 都多转了 Δθ,于是整个输出变成原来的 R(Δθ) 倍——转了一个只和绝对位置有关的角度。下面组件的第 ② 种做法就是它。
只转 q、k:打分里 (R(iθ)q)·(R(jθ)k) = q·R((j−i)θ)k,只剩相对距离;V 原样加权求和。整句平移 Δ,权重不变、V 不变,输出一个数都不变——下面组件的第 ① 种做法。
试三件事:① 在「① 只转 Q、K」下拖动平移 Δ,看虚线和实线两根箭头始终重合;② 切到「② V 也转」,拖动 Δ,看输出箭头绕原点转,转过的角度恰好是 Δ·θ;③ 把频率对 i 拖到 31(锚点最慢的一对,θ 只有约 1.7×10−7 弧度/位置),再看第 ② 种——转得太慢,几乎看不出差别。慢的维度在短距离上几乎不携带位置,这是 C2 第 5 课讲过的事。
改进:只转 Q 和 K
答案落在一条恒等式上:旋转矩阵是正交的,R(a)TR(b) = R(b − a)。所以
所以 RoPE 只转 q、k:位置应该影响「看谁」(比如更常看近处的 token),打分正是决定「看谁」的地方 证据等级 · 数学可证明 在写明的前提下可以严格推导出来,不依赖实验。只要前提成立,换数据、换规模仍然成立。 本条R 正交,(R_i q)ᵀ(R_j k) = qᵀ R_(j−i) k 出处RoFormer(Su et al. 2021)§3.2 ↗ 。V 不参与打分,转它没有任何好处,只会让输出随绝对位置旋转——上面的平移实验就是证据 证据等级 · 数学可证明 在写明的前提下可以严格推导出来,不依赖实验。只要前提成立,换数据、换规模仍然成立。 本条w 不随平移变化;Σ w_j R((j+Δ)θ) v_j = R(Δθ) Σ w_j R(jθ) v_j 出处待补 。
前沿里真的有人不得不转 V。DeepSeek-V4 的压缩注意力让同一个向量既当 K 又当 V(省一半缓存);K 必须转,于是 V 也跟着转了。报告写得很直白:这样做,输出会带上绝对位置;对策是对输出再施加位置 −i 的 RoPE,让每个条目对输出的贡献只和「提问者与它的距离」有关 证据等级 · 实验验证 由对比实验得出的经验结论,只在出处写明的模型、数据和规模下成立。换了条件可能不再成立,引用时要带上实验设置。 本条原文:the naive core attention outputs will carry absolute position embeddings … we also apply RoPE with position −i。这是设计选择,由它自己的训练结果支持 出处DeepSeek-V4 技术报告 §2.3.3 ↗ 。上面组件的第 ③ 种做法就是它:R(−iθ)·Σ wjR(jθ)vj = Σ wjR((j−i)θ)vj,又只剩相对距离。
⚠ 常见误解
「RoPE 给 embedding 加了一个位置向量。」没有加任何东西。RoPE 发生在注意力内部、q_proj/k_proj 之后,只作用在 q、k 上;embedding 本身和 V 都不带位置。
「V 不转,所以注意力的输出里没有位置信息。」有,只是来路不同:权重 w 由转过的 q、k 算出,依赖相对位置;输出 = Σ w·v,哪些 token 的 V 被多拿、被少拿,就是位置在起作用。RoPE 让位置只通过「看谁」进入输出,而不是把内容本身拧一个角度。
注意力的演进,你在这里
① 训练时:一个 token 怎么从别的 token 那里取信息
- 解决了能读任意长的序列,参数与长度无关;手里只带一个固定大小的状态 h。卡在ht 要等 ht−1 算完:T = 4,096 时每层 4,096 步不能并行,第 1 个 token 的信息要经过 4,095 次更新才到最后;翻译时整句还得挤进一个定长向量——Bahdanau 2014 说的瓶颈。展开岔路 B1
- 解决了解码器每一步回头给源句的每个位置打分、加权取回,不再只靠那一个定长向量:score = vT·tanh(W1q + W2k)。卡在每一对都要单独过 tanh,交不给矩阵乘单元;朴素实现要先落一个 T×T×da 的中间张量:T = 4,096、da = 256 时单头单层 8.0 GiB(BF16),点积只留 T×T 个分数,32 MiB。它还长在 RNN 翻译模型里,串行没解决。展开第 2 课
- 解决了直接比 embedding 时「给了」最像的是它自己(余弦 1.000),小明、苹果、小王排在最后;投影成 Q、K 再点积,它自己排到最后、前三名是苹果、小王、小明,全部配对一次矩阵乘 QKT;取回用单独的 V——两个人名的 K 余弦 0.995,取回 K 分不清是谁。卡在不缩放:锚点每头 256 维,点积标准差 √256 = 16,同一行分差十几二十是常态(e20 ≈ 4.9 亿),softmax 几乎独占,梯度传不回 WQ、WK。
- 解决了softmax 把分数变成正的、和为 1 的权重,只看分差(按占比分,对话样本的 10、3、−4 会给「汽车」−44.4%);除以 √dk = 16,点积方差回到 1。卡在训练时整句一次喂进去:不加掩码,「给了」一行有 32.5% 的注意力直接落在它要预测的答案「小王」上,loss 低得虚假。展开第 3 课
- 解决了旋转后 q·k 只依赖距离 j − i;V 不参与打分,不转(转了会把绝对位置混进取回的内容)。锚点每头 256 维里只转 64 维。卡在旋转矩阵随位置变,夹在展开矩阵和缓存之间就没法事先并进 Q:MLA 因此把 RoPE 单独拆出 64 维另存(DeepSeek-V2 config,第 10 课)。
- 解决了标准 softmax 逼每行分完 100%:「苹果」一行 3 个分数只差零点几(0.04、0.36、0.00),照样分成 30% / 41% / 29%;分母加可学习的 sink logit,或在输出上乘门,这个头就能「这次不取」——锚点开着输出门(attn_output_gate = true)。卡在出口的效果只有实验证据:Gated Attention 原文说门控「缓解」sink,不是消除;DeepSeek-V4 没给 sink logit 的单独消融。展开岔路 B4
② 生成时:K、V 怎么越存越少
- 解决了缓存直接除以头数:锚点形状下每 token 16 KiB,262,144 上下文 4 GiB。卡在质量会掉、训练可能不稳:GQA 论文表 1(T5-XXL,七个任务平均)MHA 47.2 → MQA 46.6。展开第 9 课
- 解决了24 个 Q 头分 4 组、每组 6 个共用 1 个 KV 头(组数 = KV 头数):每 token 64 KiB、262,144 上下文 16 GiB;T5-XXL 上 GQA-8 平均 47.1、推理 0.28 s,质量接近 MHA(47.2、1.51 s),速度接近 MQA(0.24 s)。卡在再减 KV 头就回到 MQA:DeepSeek LLM 67B 已是 GQA-8,每 token 仍要 389,120 B(每头一份的 MHA 是 3,112,960 B),1M token 单条请求 380 GiB。展开第 9 课
- 解决了不存 K、V,每层每 token 只存 512 维潜向量 + 64 维 RoPE = 576 个数,用时再展开:DeepSeek-V2(60 层)每 token 69,120 B、V3(61 层)70,272 B;相对 67B 按 BF16 降 82.2%,官方「−93.3%」还含约 6 bit 的 KV 量化。卡在仍随长度线性增长,打分仍是 T²:GLM-5.3 同是 576 个数、78 层,每 token 89,856 B,原生 1,048,576 上下文时单条请求只算潜向量就要 87.75 GiB。展开第 10 课
- 解决了换掉「按长度存」本身:锚点 64 层里 48 层不存 KV,只存固定大小的状态(FP32 共 144 MiB),与上下文长度无关(这些层是什么、怎么更新,C11 第 4 课揭晓);DeepSeek-V4.1 叠加压缩、稀疏与低精度,官方报告全局 KV 890 B/token。卡在固定状态装不下任意多对键值,锚点仍留 16 层全注意力;稀疏注意力每步只读挑出来的一部分,挑本身也有代价——各自省了什么、没省什么,C11 讲。
证据三问
- 它解决什么问题?让位置信息以「相对距离」的形式进入打分,并且不污染取回的内容。
- 数学上为什么有效?旋转矩阵正交,内积里只剩 j − i;V 不做内积,转它只会引入绝对位置 证据等级 · 数学可证明 在写明的前提下可以严格推导出来,不依赖实验。只要前提成立,换数据、换规模仍然成立。 本条两条恒等式都可在组件里数值核对 出处待补 。
- 实验上呢?RoPE 本身「比其他位置编码好」是实验结论(C2 岔路讲过三层证据);DeepSeek-V4 在 K=V 的场景下主动把输出转回相对位置,从反面说明设计者认为绝对位置混进输出不可取 证据等级 · 实验验证 由对比实验得出的经验结论,只在出处写明的模型、数据和规模下成立。换了条件可能不再成立,引用时要带上实验设置。 本条设计选择 出处DeepSeek-V4 §2.3.3 ↗ 。
一句话
RoPE 转 Q、K,是为了让「看谁」只取决于相对距离;V 不参与打分,转它只会把绝对位置混进内容。
下一个缺口
到这里,一套 Q/K/V 已经完整:有位置、有掩码、有打分、有取回。可「给了」要同时找三样东西:谁给的、给了什么、给了谁。一次 softmax 只有一份 100% 的注意力可分——一套 Q/K/V 够用吗?→ 第 7 课:一套 Q/K/V 只能看一种关系,够吗?
你可能会问
这一课还没有收到真实提问;你的提问会记到 05-问答记录/C3-L5.md。
🔍 为什么 Qwen3.8 每个头只转 64 维,不全转?
转的维度负责携带位置,不转的维度只比内容。锚点 256 维里有 192 维完全不转,q、k 在这些维上的点积与位置无关,模型可以用它们做「不管多远都一样」的纯内容匹配。转多少是实验选出来的(GPT-J、GPT-NeoX 就只转 25%),细节在 C2 第 4 课。