没训练过的位置,能不能用公式算出来?
本课一问:可学习的位置表背不下没见过的位置。能不能不「背」,而是给一条公式,任何位置代进去都能算出一个位置向量?
这一课先不碰:RoPE(第 4 课,它和本课的公式是亲戚,但用法完全不同)、超长上下文的扩展方法(第 5 课)。
从已有出发
第 2 课留下两条教训:位置信号的尺度不能无限增长(直接加编号会淹没内容);位置表只认表里有的行(GPT-2 只有 1,024 行)。所以新方案要同时满足三件事:任意位置都能给出一个向量;数值有界,和词向量量级相当;不同位置的向量互不相同。
先自己设计:从「查表」换成「现算」
- ① 朴素方案
- ② 它在哪失败
- ③ 改进方案
| 位置 p | 0 | 1 | … | 1,023 | 1,024 | 100,000 |
|---|---|---|---|---|---|---|
| GPT-2 的位置表 P[p] | ✓ 有 | ✓ 有 | … | ✓ 有 | ✗ 查无此行 | ✗ 查无此行 |
规定一条函数 PE(p),对任意整数 p 都给出一个 d 维向量。原始 Transformer 用的就是这个思路:每两维一组,一组放一对 sin、cos,各组转速不同。位置 1,024、100,000 都能直接代进去算——下面的组件里点这两个预设就能看到结果。
改进:多组不同转速的 sin / cos
公式本身不长,每一项都有用意。逐项点开:
试三件事:① 点「▶ 播放」,看 8 根指针的速度差多少:最快的一根每 6.28 个 token 转一圈,最慢的一根要 19,869 个 token;② 点预设 1,024 和 100,000,位置表查不到的位置,公式照样给出 16 个数,而且都在 [−1, 1] 之内;③ 在热力图下点「整句往后平移 +10」,绝对位置全变了,颜色一格不变——两个位置编码的点积只取决于它们相隔多远。
对话样本用了一个类比:「像钟表的秒针、分针、时针,几根针的组合表示时间。」它可以当入口,但要说清对应关系和不成立的地方:
- 映射:一根指针 = 一组 (sin, cos);指针的角度 = p·ωi;所有指针的读数合起来 = 位置向量 PE(p);转得快的指针(i 小)区分相邻位置,转得慢的(i 大)区分相隔很远的位置。
- 失效点 ①:钟表指针的转速比是整数(60 : 1),而且会「进位」;这里相邻两组的转速比是 √10 这样的无理数,没有进位,所有指针的组合在实际长度内不会重复出现。
- 失效点 ②:人会读钟表,是因为早就知道读法;模型拿到这 16 个数,得自己学会怎么用——这就是本课后半段要看的失败。
两条可以证明的性质
有界、可算:任何 p 都能代进公式,每个分量都在 [−1, 1] 之间。
点积只依赖距离:用 sin a·sin b + cos a·cos b = cos(a − b),
PE(p)·PE(p+k) = Σi [sin(pωi)sin((p+k)ωi) + cos(pωi)cos((p+k)ωi)] = Σi cos(kωi)
右边没有 p,只有 k 证据等级 · 数学可证明 在写明的前提下可以严格推导出来,不依赖实验。只要前提成立,换数据、换规模仍然成立。 本条一步三角恒等式。组件里的热力图沿斜线颜色相同、平移后逐格不变,就是这个式子的样子;曲线画的是右边的 Σ cos(kωi)。 出处待补 。换句话说,两个位置编码之间的关系只由「相隔多远」决定。
原论文还多说了一句:对固定的 k,PE(p+k) 可以写成 PE(p) 的线性函数——每一组都是转一个固定角度 k·ωi。作者据此希望模型能容易地学会「按相对位置去关注」,也希望它能外推到比训练更长的序列 证据等级 · 有理论动机 有数学或机制上的理由说明它可能有效,但没有证明它一定更好。最后是否采用,仍然要看实验。 本条原文措辞是 hypothesized 与 may allow:两个都是动机,论文没有验证外推。 出处Vaswani 2017 §3.5 ↗ 。注意这两个「希望」:它们是理论动机,不是结论。
另一个观察:语言更在乎「相隔多远」
「小明打了小王」前面如果多出一个 token,三个词的绝对位置都 +1,可「小明」和「小王」之间仍然隔着 2 个位置,语义关系一点没变。同样的主谓宾结构,出现在文章第 10 个 token 还是第 1,000 个 token,规律是一样的。
这引出了相对位置的思路:不告诉模型「我是第几个」,而是在注意力打分时直接加一项「我们相隔多远」。Shaw 等人 2018 年的做法是为每个相对距离学一个向量,距离超出范围就截断;T5 用的是按距离分桶的偏置(RoFormer 论文 §2.3 对这些方案有综述)。它们的共同代价是要改注意力的计算,为距离单独加项。第 4 课的 RoPE 做的是同一件事,却不加任何参数。
它在哪失败:算得出 ≠ 会用
公式能算出位置 100,000 的向量,不代表模型见到它时知道怎么办。两份证据:
原论文自己的对照。把公式版换成可学习的位置向量,开发集 PPL 4.92 对 4.92、BLEU 25.8 对 25.7,几乎没有差别 证据等级 · 实验验证 由对比实验得出的经验结论,只在出处写明的模型、数据和规模下成立。换了条件可能不再成立,引用时要带上实验设置。 本条英德翻译 base 模型,只比较了训练长度之内;论文没有做超长序列的外推实验。 出处Vaswani 2017 表 3 第 (E) 行 ↗ 。在训练长度之内,两者一样好;选公式版的理由是「可能外推」,但论文没有去测。
我们自己模型上的实测。同一数据、同一步数,训练长度 128:
我们踩的坑:sinusoidal 这一组在训练长度之内就明显更差。原因在实现:我们的 embedding 按 std = 0.02 初始化,而 sin/cos 的每个分量在 ±1 之间(均方根 1/√2 ≈ 0.71),两者直接相加,开局时内容只有位置信号的约 0.02 ÷ 0.71 ≈ 2.8%——正是第 2 课「位置淹没内容」的真实版本。原论文在相加之前先把 embedding 乘以 √dmodel(§3.4),我们的 dmodel = 256,就是乘 16。上图的虚线就是只改这一处的对照组(单个种子):差距的大头来自这一步。补上之后,它在我们的小模型上仍然落后于另外三组,越过训练长度也照样变坏——原论文是 6 层翻译模型训 10 万步,我们是 3.7M 参数训 400 步,实验条件不同,结论不能直接搬。
再按位置拆开看:512 长的序列里,训练长度之后的位置 loss 怎么变。
位置 128 之后,公式照样给出位置向量,loss 却明显变差:这些位置向量模型一次也没见过。「能算出来」只解决了「有没有向量」,没解决「模型会不会用」。
常见误解:「sinusoidal 就是 RoPE。」
两者的频率公式确实同源(都是 base−2i/d),用法却完全不同。sinusoidal 在第一层之前加到输入向量上,只加一次;之后内容和位置混在同一组数里,连 V 也带着位置。RoPE 在每一层注意力内部,乘(旋转)在 Q 和 K 上,V 不动。下一课会看到,正是「加」还是「转」这一步,决定了注意力分数里的相对位置干不干净。
位置编码的演进,你在这里
- 解决了注意力对所有 token 一视同仁,一次矩阵乘并行算完。卡在交换「小明打了小王」为「小王打了小明」,每个 token 的输出向量逐位相同,差值 = 0(第 1 课在浏览器里实算)。
- 解决了每个位置一个不同的数,简单直接。卡在编号没有上限:在位置 37,内容只剩位置信号的 2.7%(内容 RMS = 1 时;按项目初始化尺度只剩 0.054%)。
- 解决了位置也查表,和词向量一样训练出来。卡在表有多少行就只能处理多少个位置:GPT-2 的位置表 1,024 行 × 768 维 = 786,432 个参数,位置 1,024 没有对应的行。
- 解决了不背位置,用多组 sin/cos 现算,任意位置都算得出来;两个位置编码的点积只依赖距离。卡在「算得出」不等于「会用」:原文表 3 里它和可学习位置几乎一样(dev PPL 4.92 vs 4.92,BLEU 25.8 vs 25.7);而且加在输入上,整句平移后注意力分数会变。
- 解决了直接告诉注意力「相隔多远」,语言规律在文章各处一样。卡在要改注意力的计算,为每个距离单独加一项,距离还被截断在 [rmin, rmax] 之内(RoFormer §2.3 的综述)。
- 解决了按位置旋转 Q、K,转完再点积,绝对位置被约掉,只剩 n − m;不加参数。卡在能算到任意长,却只在训练见过的角度内可靠:Qwen3 原生 32,768,64 个频率对里有 24 对一圈都没转满;Qwen3.8 原生 262,144,32 对里有 10 对。
- 解决了把新位置折算回见过的范围:Qwen3 32,768 → YaRN ×4 = 131,072;Qwen3.8 262,144 → ×4 ≈ 1M。卡在窗口 ≠ 有效长度:Qwen3.8-Flash-Next 技术报告自报,8 针 MRCR 在 128K 为 97.14,到 1M 只剩 20.71(全注意力版本)。
- 解决了Qwen3.8 只转 25% 的维度;Kimi K3、GLM-5.3-Flash 的全局注意力层不用任何位置编码,顺序交给线性注意力层。卡在Qwen 报告:全注意力层去掉 RoPE,预训练看不出差别,后训练后「停不下来」的比例明显升高——所以它保留了 RoPE。两条路线都做到了百万级上下文,没有唯一正解。
证据三问
| 问 | 本课的回答 |
|---|---|
| ① 它解决什么问题? | 任意位置都能给出一个有界的位置向量,不用背表 |
| ② 数学上为什么可能有效? | 位置编码之间的点积只依赖距离 证据等级 · 数学可证明 在写明的前提下可以严格推导出来,不依赖实验。只要前提成立,换数据、换规模仍然成立。 本条Σ cos(kωi),与 p 无关。 出处待补 ;平移是每组转一个固定角度,所以作者希望模型容易学会相对位置、并且能外推 证据等级 · 有理论动机 有数学或机制上的理由说明它可能有效,但没有证明它一定更好。最后是否采用,仍然要看实验。 本条「希望」是原文的立场,不是证明。 出处Vaswani 2017 §3.5 ↗ |
| ③ 实验上为什么选了它? | 原论文里它和可学习位置一样好(表 3),选它是为了「可能外推」;可外推这一点没被验证,我们的小模型上也没有外推好 证据等级 · 实验验证 由对比实验得出的经验结论,只在出处写明的模型、数据和规模下成立。换了条件可能不再成立,引用时要带上实验设置。 本条我们自己的实测见上面两张图(3.7M 参数、训练长度 128,只在这个规模上成立)。 出处Vaswani 2017 表 3 ↗ |
一句话
位置可以用多组不同转速的 sin/cos 现算,任意长度都算得出,两个位置的点积只看距离;但「算得出」不等于「模型会用」。
先停在这里:记住「现算解决了有没有向量,没解决会不会用」,进下一课。
再深一层:读 SideRef 里苏剑林的第 1 篇,看注意力分数展开后,绝对位置项和相对位置项各在哪里。
下一个缺口
能不能让注意力直接感受到「相隔多远」? → 第 4 课:RoPE 到底旋转了什么?
线索已经在本课里了:「平移 k 个位置 = 每组转一个固定角度」。第 4 课把这个旋转从输入上挪进注意力里,直接作用在 Q 和 K 上。
你可能会问
- 「base 为什么是 10000?」 原论文没有推导,只说波长从 2π 到 10000·2π 呈几何级数。它决定了最慢那组有多慢,也就决定了能区分多远的距离;现代模型把它调大(第 5 课)。
- 「sin 和 cos 为什么都要,只用 sin 不行吗?」 只用 sin,「往后挪 k 位」就不再是一个固定的线性变换(sin(a+b) 里要用到 cos a)。成对出现,每组才是单位圆上的一个点,平移才等于旋转——这正是 RoPE 的出发点。
- 「为什么原论文说它和可学习位置差不多,我们的实测却差很多?」 大头见上面「我们踩的坑」:原论文先把 embedding 乘了 √dmodel,我们的第一版实现没有乘。补上之后差距缩小了大半,剩下的部分和规模、训练步数有关:原论文训 10 万步,我们只训 400 步。