从0训练LLM · 现代大模型体系 实验 实验 ≈ 30 分钟 页内实验 ×6
C2 位置:模型怎么知道顺序 实验课

实验课:三种位置编码在我们自己的模型上比一比

实验课:位置编码在我们的模型上比一比
同一份数据、同样的步数,只改位置编码这一项:可学习位置、sinusoidal、RoPE,外加一个不加位置的对照组。前五课的每一条结论,都拿我们自己训练的小模型来核对一遍。
🧪

这一课不讲新概念。前五课的每一条结论,都放到我们自己从 0 训练的小模型上核对:三种位置编码(可学习位置、sinusoidal、RoPE),再加一个什么都不加的对照组。所有图都直接读取实验导出的真实结果;每张图下面的「数字口径」一行写明了模型规模、语料、步数、种子和噪声。

这一课先不碰:续训版的 PI / YaRN(本轮只做了零样本)、更大的模型与更长的训练长度(C6 讲规模)。

实验是怎么设计的

对照实验的原则只有一条:一次只改一项。

从已有出发 · 累计数据流 点已学环节看形状与参数
解码层

一、先猜,再看外推

项目实测 · 四组位置编码在 128 / 256 / 512 长度上的 val loss
先猜:在最长的测试长度上,哪一组的 val loss 相对训练长度涨得最多?

读这张表要回答三个问题:① 训练长度 128 之内,谁最低?② 谁在 256、512 上根本跑不起来,为什么?(第 2 课)③ 虚线那组和 sinusoidal 实线差在哪?(第 3 课「我们踩的坑」)

二、训练过程

项目实测 · 四组训练曲线(train 虚线 / val 实线)

把指针移到曲线上,找两个时刻:哪一组最先拉开差距?训练结束时,val 与 train 的差(最右一列)哪组最大?注意这里的 train loss 是在固定的训练集窗口上评估出来的,不是小批次的均值,所以能和 val 直接比。

三、越过训练长度,坏在哪一段

项目实测 · 512 长的序列里,每一段位置的 val loss

竖线左边是训练见过的位置,右边是没见过的。每一组越过竖线之后怎么变,就是第 2–5 课在各自方案上讲的那件事。

四、RoPE 的三种折算方法

先把理论算一遍:我们的模型每头 32 维、base 10,000、训练长度 128,切到「我们的小模型」,四种做法各有几组越界、几组被压扁:

模型
做法

点上图任意一根柱子,看这一对的全部数字。

再看实测:

项目实测 · RoPE 零样本缩放:128 / 256 / 512

项目实测 · 四种做法:每一段位置的 loss

理论和实测对得上吗?三个核对点:PI 让所有组都不越界,却把训练长度之内的 loss 也抬高了(相邻角度被压扁,零样本用不好);NTK-aware 只压低频,训练长度之内几乎不受影响;YaRN 在这个小模型上几乎把每一组都插值了——因为训练长度只有 128,最快的一组也转不满 32 圈。

五、把结论对回前五课

课那一课的结论在我们的模型上看什么
第 1 课注意力本身对顺序无感「不加位置」这一组照样能学,loss 只是更高:我们的模型带因果掩码,掩码本身透露了位置(第 5 课误解二)
第 2 课位置表有多少行,就只认多少个位置learned 在 256、512 上是「✗」;强行延长(复用第 127 行)在竖线之后立刻跳升
第 3 课算得出 ≠ 会用sinusoidal 越过竖线后变坏;不先乘 √d 时连训练长度之内都被位置淹没
第 4 课RoPE 让打分只看相对位置训练长度之内,RoPE 这一组最低,和第二名的差距远大于种子间波动
第 5 课越界的是低频组,折算能缓解RoPE 直接外推在竖线之后变坏;零样本折算里,只压低频的 NTK-aware 最稳
⚖️

这些结论只在这个规模上成立:3.7M 参数、约 50 万 token 的语料、训练长度 128、400 步 。第 4 课 RoFormer 的作者、第 5 课 Qwen 的 NoPE 反证都说明:有些差别到了更大的规模、甚至后训练之后才会显现。实验课的价值不在「证明谁最好」,而在练习先写下预测、再只改一项、最后连同条件一起报告结论。

六、为项目拍板

🧭

你要拍板的三件事(对应章首页的项目里程碑):

  1. 选哪种位置编码?依据上面的表:训练长度之内谁最好、谁 0 参数、谁有成熟的延长方案。
  2. 训练长度定多少?它决定了哪些频率对能转满一圈(第四部分的组件),也决定了注意力的计算量(C3)。
  3. 要不要为更长的输入预留缩放方案,用哪一种?看第四部分:零样本还是准备续训?

验收标准写成「不比实测基线更差」,而不是拍一个数:以本页 RoPE 直接外推在 2 倍训练长度处的涨幅为基线(表中「2× 处涨幅」一列),之后任何改动都不能让它变大;差距小于种子标准差的改动,不算改进也不算退步。

🔍 自己复现这个实验

脚本在 04-实践项目/experiments/exp_c2_position.py,训练配置沿用 04-实践项目/configs/baseline.json,只把 model.pos 换成四选一、训练长度设成 128;数据导出到 知识平台/src/data/project/c2-position.json,本页所有图自动读它。项目的 tests/test_core.py 里,TestRoPE 有 5 项测试:旋转后点积只依赖位置差、相对位置确实影响分数(反例对照)、加法式 sinusoidal 不满足平移不变(反例对照)、线性插值后依赖 (n−m)/s 且保持向量长度、放进完整注意力后整体平移分数不变;另有一项检查 learned 位置超出表长时报错。改一项、跑三个种子、写下预测再看结果——这是这门课所有实验课的固定流程。

一句话

📌

同一数据、同一步数、只改位置编码:RoPE 在训练长度之内最好,但每一种方案越过训练长度都会变坏;零样本折算里只压低频的 NTK-aware 最稳,PI 必须续训。

下一个缺口

位置已经进了 Q/K,那 Q、K、V 到底是什么? → C3 第 1 课:已经有 Embedding 了,为什么还要变成 Q、K、V 三份?