第 6 章 位置表示¶
6.1 回顾:第 2 章的绝对位置¶
不带位置、也不带因果掩码的自注意力是置换等变的:若用置换矩阵 \(P\) 重排输入,则
输出只会跟着重排。第 2 章的对策是查表后加绝对位置:
\(\mathrm{PE}\) 可以是正弦公式,也可以是可学习表。小模型因此能分清语序,第一部分的解码器才算齐。因果掩码还会泄露「左边有几个词」,但稳定表达「相隔 3」和「相隔 3000」仍要靠显式位置。
绝对位置的两处限制,在放大后变得扎眼:
- 相对距离是间接学的:模型看见的是「我在 17、对方在 20」,要自己悟出「差 3」;\(q^\top k\) 里没有直接出现 \(n-m\)。
- 长度绑在训练分布上:可学习表对没见过的下标没有行;正弦能外推,质量也常掉。
要的是:注意力分数里直接出现相对距离,而不是只靠嵌入上的绝对下标让模型自己悟。
6.2 RoPE:把相对位置写进点积¶
这个例子里 Q、K、V 各是什么¶
四个位置,每个位置投影之后都有自己的三个向量 \(q_j,k_j,v_j\)(这里假装头维 \(d_h=2\),数字是示意):
| 下标 \(j\) | token | \(q_j\)(去提问) | \(k_j\)(被提问时的标签) | \(v_j\)(被选中时交出的内容) |
|---|---|---|---|---|
| 0 | 预算 | \((1.0,\ 0.2)\) | \((0.9,\ 0.1)\) | \((0.5,\ 0.5)\) |
| 1 | 五千 | \((0.3,\ 0.8)\) | \((1.0,\ 0.0)\) | \((2.0,\ 0.0)\) |
| 2 | , | \((0.1,\ 0.1)\) | \((0.2,\ 0.2)\) | \((0.0,\ 0.1)\) |
| 3 | 别太赶 | \((1.0,\ 0.0)\) | \((0.4,\ 0.6)\) | \((0.7,\ 0.3)\) |
- \(q_j\):位置 \(j\) 作为当前格时,用来和序列里各位置做匹配的向量。
- \(k_j\):位置 \(j\) 被匹配时参与点积的向量。
- \(v_j\):匹配权重算完后,从位置 \(j\) 取走的内容向量。
当前要算的是位置 3 的输出:用到 \(q_3\),以及 \(k_0,k_1,k_2,k_3\) 和 \(v_0,v_1,v_2,v_3\)。\(q_0,q_1,q_2\) 在这一步不用;它们只在「当前格是 0/1/2」时才会被拿来打分。
转谁¶
RoPE 只旋转上表里的 \(q\) 和 \(k\),而且按该行自己的下标转:
| 向量 | 转不转 | 转完变成 |
|---|---|---|
| \(q_3\) | 转,用 \(R_3\) | \(R_3 q_3\) |
| \(k_0\) | 转,用 \(R_0\) | \(R_0 k_0\) |
| \(k_1\) | 转,用 \(R_1\) | \(R_1 k_1\) |
| \(k_2\) | 转,用 \(R_2\) | \(R_2 k_2\) |
| \(k_3\) | 转,用 \(R_3\) | \(R_3 k_3\) |
| \(v_0,v_1,v_2,v_3\) | 不转 | 仍是表里原来的数 |
| 词嵌入 | 不转 | 与 RoPE 无关 |
\(R_j\) 是由下标 \(j\) 决定的 \(2\times 2\) 旋转矩阵(角度 \(j\cdot\omega\))。同一行的 \(q_j\) 与 \(k_j\) 用同一个 \(R_j\);不同行用不同的 \(R_j\)。
转完干什么¶
位置 3 用转完的 Query 去和每个转完的 Key 打分(再除 \(\sqrt{d_h}\)):
四个分数 softmax 得到权重 \(\alpha_{3,0},\ldots,\alpha_{3,3}\),再对没转过的 Value 加权:
整段里 RoPE 只插手「\(s_{3,j}\) 算多大」;取内容时仍用表里原来的 \(v_j\)。
还用上面的数:相对距离怎样进 \(s_{3,1}\)¶
只看位置 3 对位置 1 这一格分数。表里 \(q_3=(1,0)\),\(k_1=(1,0)\)。为把角度算清楚,这一小节假设每步转 \(\omega=30^\circ\)(真模型里由 rope_theta 算出来的 \(\omega\) 小得多,道理相同)。
不转时。
\(q_3^\top k_1=1\cdot 1+0\cdot 0=1\)。分数只说「这两个内容向量完全同向」。
按例子转完再乘。
\(R_3\) 把向量转 \(3\times 30^\circ=90^\circ\),故 \(R_3 q_3=(0,1)\)。
\(R_1\) 把向量转 \(1\times 30^\circ=30^\circ\),故 \(R_1 k_1=(\cos 30^\circ,\sin 30^\circ)=(\sqrt{3}/2,\ 1/2)\)。
点积变成
同一对内容,分数从 \(1\) 变成 \(1/2\)。差在哪里?两步转角相差 \(90^\circ-30^\circ=60^\circ\),也就是下标差 \(3-1=2\) 步 \(\times 30^\circ\)。写成矩阵就是前面那条恒等式在本例上的样子:
同一对内容,换一个间隔。 若「五千」的 \(k\) 仍是 \((1,0)\),但挪到下标 2(与 3 只隔 1),则用 \(R_2\)(转 \(60^\circ\)):
\(k\) 的内容没变,只是相对位置 3 的间隔从 2 变成 1,分数从 \(1/2\) 变成 \(\sqrt{3}/2\)。相对距离进的是这一格点积的数值;\(v_1\) 始终还是表里的 \((2,0)\),没有参与旋转。
一般写成 \((R_m q)^\top(R_n k)=q^\top R_{n-m}k\)。二维里 \(R(m\omega)\) 就是
真模型把 \(d_h\) 切成多对,每对各自一个 \(\omega_i=\theta_{\text{base}}^{-2i/d_{\text{rope}}}\)。不增加参数,输出形状不变。
各维频率由 rope_theta 决定(经典值 10000,长文常更大)。靠前的维对转得快,分辨局部;靠后的转得慢,覆盖长距离。Qwen、Llama 一类 decoder-only 几乎都用 RoPE。ALiBi、相对位置偏置仍有个别模型在用。
与第 2 章对照:绝对位置加在 \(h^{(0)}\) 上;RoPE 在每一层注意力点积前作用在 Q/K 上,嵌入不再加 \(\mathrm{PE}(t)\)。若同时有第 5 章的 QK-Norm,顺序是:投影 → 拆头 → QK-Norm → RoPE → 点积。先旋转再归一化,与先归一化再旋转,形状相同、数值不同。
6.3 超过训练长度时会发生什么¶
RoPE 的角度 \(m\cdot\omega\) 只在训练见过的 \(m\) 上可靠。推理时若 \(m\) 远大于训练长度,模型面对的是没见过的旋转角,注意力分布会乱,生成质量明显下降。换了 RoPE 也不会自动变成任意长上下文。
2023 年前后,有一批方法在不改结构的前提下改旋转角,好把已训好的模型窗口拉长一点:位置插值(PI)把位置线性压回训练范围;NTK-aware / 调大 rope_theta 让低频维承担扩窗、高频维尽量保住局部;YaRN 再按频率分段并加温度修正。它们常出现在 config 的 rope_scaling 一类字段里。算法名相同不代表各家公式完全一样;权重若没按同一方案训过,格式能跑不代表质量可靠。再配少量长文本继续训练,通常比只改推理侧角度更稳。
今天多数开源模型会直接按目标长度训练,rope_scaling 经常是空的。读 config 时认出这些名字即可。超长之后真正难的是 KV 涨、注意力变贵、中间内容被忽略——第 7 章与第四部分。
6.4 部分层不加 RoPE¶
因果模型里,每个位置能看见左边多少个 token,本身带一点位置线索。于是有的层干脆不旋转(NoPE),只靠内容做匹配,长度泛化有时更好。常见做法是带 RoPE 的层与 NoPE 层交替;它还没有像 RMSNorm、GQA 那样成为统一标配。
另有一种是部分维度 RoPE:每个头只有一部分维旋转,其余维不转。第 16 章的 QSA(头维 256、RoPE 维 64)属于后者,不是整层 NoPE。
6.5 现代位置表示¶
开源 config,Qwen、Llama 一类稠密模型默认仍是 RoPE + 目标长度直接训
在新的 Kimi K3 的全局注意力(MLA)层对 Q/K 不加 RoPE,报告里直接写成 NoPE;顺序与近因,改由穿插的线性/递归层(KDA:门控、衰减、短卷积)隐式带着。扩到百万级上下文时,也就不必再调 rope_theta 或套 YaRN。这能成立,靠的是混合注意力骨架;在「纯 decoder + 全注意力」骨架上直接去掉 RoPE,通常撑不住同样的长度。K2 那种全 MLA 路径上,RoPE 仍关键。混合架构在第四、五部分展开;读权重时 RoPE 仍是最常见的选择,但旗舰里已经有人把显式位置编码从注意力里拿掉。
动手:改一处¶
在第 2 章绝对位置骨架上,去掉嵌入上的 \(\mathrm{PE}\),改接 RoPE。用短序列训练后,直接推到更长的长度,观察困惑度;再与「保留绝对位置、不加 RoPE」对照,看相对距离相关的错误差在哪。
核心问答¶
Q1:第 2 章已经有位置编码,为什么还要第 6 章? 第 2 章的绝对位置解决「跑起来时能分清先后」。这一章解决「放大、拉长之后,相对距离怎样更干净地进注意力」。RoPE 不是位置的第一次出现,而是绝对位置的主流替换。
Q2:RoPE 是在量 \(q\) 与 \(k\) 之间的距离吗? 分数仍是点积 \(q^\top k\)(再缩放),反映投影后内容是否对齐;欧氏距离不进公式。RoPE 让这个点积额外依赖相对位置差 \(n-m\),于是同一对内容在不同间隔上得分不同。
Q3:RoPE 明明按绝对位置旋转,为什么说它是相对位置编码? 因为 \(R_m^\top R_n=R_{n-m}\),旋转后的点积只通过 \(n-m\) 依赖位置,不依赖绝对下标本身。
Q4:为什么只旋转 Q 和 K,不旋转 V? \(q^\top k\) 决定看谁、看多少;V 是取回来的内容。位置差写进匹配分数即可,不必改写被取用的向量。
Q5:想支持更长上下文,把 rope_theta 直接调大不就行了? 可以,但不是免费的。基频调大等于所有维转得更慢,长距离好分辨了,相邻位置的差别变小。今天更常见的是训练时就开到目标长度;只靠推理侧改角度,质量要另验。
Q6:既然 NoPE 也能工作,为什么不全部去掉位置编码? 纯因果注意力里,隐式线索偏弱,局部语序仍要相对位置撑着,所以常见是多数层 RoPE、少数层 NoPE。整网去掉显式位置编码可以,但通常要有别的模块承担顺序——Kimi K3 靠 KDA 一类递归层(§6.5),不是在第 2 章那套全注意力骨架上直接拔掉 RoPE。