位置编码的外推问题:为什么模型训了 4K 长度,直接用 8K 就会崩溃

如果你把一个训练长度只有 4K 的模型直接拿去读 8K 的文本,结果不是“后面那 4K 内容它记不住”,而是从第 4097 个 token 开始,困惑度像断崖一样往上跳——模型开始复读、乱跳主题,甚至生成不存在的词。我第一次看到这个实验曲线时,还以为是评测代码写错了。后来把每一层都翻了一遍才发现,问题几乎不在“记忆”上,而在一个更安静、更底层的部件:位置编码

AI technology illustration

Transformer 没有顺序,位置是后加的

Transformer 本身没有顺序概念。你把一句话的词随机打乱再喂进去,它的注意力计算路径和原句没有任何区别——注意力是对一个集合做加权求和,集合是无序的。所以每个 token 都必须带一个“座位号”。早期模型用两种办法:

  • 绝对位置:每个位置学一个固定向量。BERT、GPT-2 就是这么干的。位置表训练到 512,推理时你想要第 1000 个位置?对不起,表里不存在。
  • 相对位置:让注意力只依赖两个位置之间的距离。RoPE(旋转位置编码)是这种思路的代表。

读到这儿你可能会想:相对位置总该能外推了吧?如果距离是 9000,模型只需要知道“很远”不就行了?——这是我最早的误解,也是很多人卡住的地方。

RoPE 已经“相对”了,为什么还是崩?

我过去一直以为,模型只要学会了“相对距离”这个抽象概念,就能泛化到任意距离。后来读了 RoPE 原文 才意识到:RoPE 确实让 attention logits 变成了相对位置的函数,但它没有告诉模型“距离 9000 应该怎么分配注意力”。模型在训练时见过的距离差只有 -4095 到 4095。距离差为 8000 的注意力模式,是它从未学过的函数输入。

位置编码方案 外推性 失败原因
可学习绝对位置 几乎为零 超过位置表就没有向量
正弦绝对位置 理论上可行,实际很差 模型仍依赖训练范围内的位置模式
RoPE 相对旋转 超范围陡降 相对距离差超出训练区间,高频旋转角开始混淆
ALiBi 偏置法 相对较好 固定斜率无法覆盖所有尺度

旋转角度超过 π 的那一刻,位置认不出来了

RoPE 的细节值得展开。它把每个位置 m 的 q 向量和 k 向量按分量旋转。对第 i 对维度,旋转角度是:

theta_i = 1 / base ** (2 i / d)
base = 10000
angle = m * theta_i

两个位置 m 和 n 的距离差 d = m-n 进入 attention logits 时,也要乘同样的 theta_i。训练长度是 4096,那么训练中距离差最大就是 4095。当测试时距离差变成 8000,某几个高频维度的旋转角会比训练时大近一倍。问题就出在这些维度上:如果 8000 * theta_i 已经转了好几圈,cos 和 sin 的周期性会让“距离 8000”和“距离 8000 减掉一个周期”产生几乎相同的旋转向量。

这会带来什么?模型在训练中学到的“距离越大,注意力越弱”的单调先验,超出了某个阈值后开始周期性反弹。高频维度说“我和他很近”,低频维度却说“我们很远”。互相矛盾的证据把 attention 的 softmax 分布搅乱,模型只能复读和胡说。这是我很长时间里没有想通的机制——外推崩溃不是“预测能力不够”,而是位置特征本身出现了混叠

正弦绝对位置也没好到哪儿去

你可能会问:原始 Transformer 用的是连续的正弦位置编码,理论上可以生成任意长度的位置向量,为什么还是不能外推?答案是:能生成新位置,不等于能理解新位置。这篇 长度泛化研究 专门测过:在短训练、长测试的设置下,正弦位置编码的 Transformer 在超出训练长度后预测质量接近随机;反而是某些相对位置编码和 ALiBi 能做到不崩溃。

原因在于:位置向量的生成函数是连续的,但模型内部的线性变换和注意力权重是在固定长度上学会的。超出训练区间后,这些参数面对的是分布外的输入,再完美的位置函数也救不回来。

与其外推,不如把 8K 的内容压回 4K 的镜头里

现在大模型把上下文从 4K 扩到 128K,很少直接硬推。主流思路是插值:测试时不使用真实距离,而是把距离映射回训练区间。比如 8K 长度用 4K 的训练区间表示,相当于把每个旋转角除以 2。但这会引入新的副作用——所有维度转得都变慢,相邻位置间的编码差异变小,短距离的顺序感变钝。

NTK-aware 缩放 的聪明之处在于不统一压缩所有频率:高频维度尽量保持原始转速,把压缩压力主要放在低频维度上。这就像把一整段电影时间轴压缩,远景镜头整体被拉慢,但近景关键动作还保持原来的节拍。之后出现的 YaRN 又在 NTK 基础上加入了注意力温度校正,进一步修复了高频维度混叠的问题。

# 直接外推:用真实位置
angle = m / base ** (2 i / d)

# 线性插值:把距离统一缩放
angle = (m / scale) / base ** (2 i / d)

# NTK-aware 缩放:改 base,间接改变不同频率的缩放量
base2 = base * scale ** (d / (d - 2))
angle = m / base2 ** (2 i / d)
方法 思路 局限
直接外推 用模型没见过的真实距离 高频旋转混淆,模型直接崩溃
线性插值 把新距离压回训练区间 高频信息损失,短距离感知变模糊
NTK-aware 高频不变,低频压缩 只在特定扩展比有效
YaRN NTK + 注意力温度校正 仍有上限,大扩展比时也需训练数据配合

外推本质上是一个统计问题

所以答案很清楚:训练 4K 的模型直接在 8K 上跑,崩溃不是运气问题,而是训练分布里根本没有距离差大于 4095 的样本。位置编码只是把这个统计缺口暴露了出来。任何数学变换,无论叫 NTK 还是 YaRN,都是在给旧模型打补丁。补丁可以撑几个扩展倍率,但到了某个阈值,高频混淆、长程衰减失真这些物理规律会一起找上门。

说句我的判断:别再指望后处理把 4K 模型魔改成 128K 还能无损。往前看,真正稳的做法是在预训练阶段就让模型见过多个时间尺度的文本,或者用 RAG 把长输入切短再喂。位置编码要学的是一种距离感知能力,而距离感知需要足够的距离样本练出来。任何回避训练的手段,都只是在借旧模型的能力补课。

原创文章,作者:guanweilu,如若转载,请注明出处:https://guanweilu.cn/article/716.html

(0)
上一篇 2小时前
下一篇 1小时前

相关推荐