Skip to content

位置编码 ​

标签
AI/llm
字数
3967 字
阅读时间
16 分钟

Transformer 的自注意力不含任何位置信息——对它来说 agent learns 和 learns agent 完全等价。位置编码(Positional Encoding)解决这个问题,而不同的注入方式决定了模型能不能处理超出训练长度的输入。

这一篇讲这条演进线:绝对 → 相对 → RoPE → 长上下文外推。

绝对位置编码 ​

正弦余弦式(原始 Transformer) ​

把固定的位置矩阵加到词嵌入上:

PE(pos,2i)=sin⁡(pos100002i/dmodel),PE(pos,2i+1)=cos⁡(pos100002i/dmodel)

每个维度是一个不同频率的正弦波(低维高频、高维低频),模型要学会从这种相位模式里读出位置。公式不需要学习,索引时零成本。

致命问题:超过 max_len 就失效。模型只见过 0–2047 的位置,没人告诉它位置 2048 该怎么办——预计算的矩阵里根本没有那一行。

学习式绝对位置嵌入 ​

干脆把位置向量也当成可训练参数(GPT-2、GPT-3 这么做)。成本极小(每层一个 max_len × d 的嵌入表),但外推能力等于没有:模型只能在训练时固定的输入长度上工作,超长直接不可用。

相对位置编码 ​

思路转向:不该告诉模型「你在第 5 位」,而该告诉它「你和对方隔了多远」——因为语义关系取决于相对距离,而不是绝对序号。

Shaw 等人最早的可学习相对位置方案是在注意力里加一项:

Attentionij=xiWQ(xjWK+aijK)Tdk

其中 aijK 是位置 i 与 j 之间距离对应的相对位置嵌入。配套用 clipping(截断) 限制不同相对距离的取值数量——外推时出现的超范围距离不会变成分布外的输入。

RoPE:把位置信息转进 Q 和 K ​

RoPE(Rotary Position Embedding,旋转位置编码) 是现在的事实标准,用在 Llama 2/3/4、Qwen 2/3、Mistral、DeepSeek-V3、Kimi 等大多数主流模型上。

三种方案的差别,落在「位置信息在哪一步进入计算」这个位置上。

① 加到词嵌入上(绝对位置编码)
   词嵌入 x ──▶ x + PE(pos) ──▶ 注意力
   PE 是预计算的固定矩阵(正弦余弦),或可训练的位置嵌入
   └─ 位置 2048 在预计算矩阵里根本没有那一行 ──▶ 超过 max_len 直接失效

② 加到注意力分数上(相对位置编码 / ALiBi)
   词嵌入 x ──▶ 注意力,只在分数里加一项
   score[i, j] = q_i·k_j / √d − m_h · |i − j|
   └─ 位置只以「距离」的形式出现 ──▶ 外推时不会变成分布外的输入

③ 旋转 Q 和 K(RoPE)
   词嵌入 x ──▶ Q、K ──▶ 按各自的位置做一次旋转 ──▶ 注意力
   └─ 不改嵌入、不改分数公式,只是对 Q、K 做变换

位置进入计算的位置越靠前,外推越困难:
① 的位置是输入的一部分,训练没见过的位置就是没学过;
③ 的位置在每层内部按需施加,缩放方式可以事后调。

它不是加法,是旋转 ​

RoPE 不改词嵌入,而是对每一层的 Q 和 K 向量施加一个与位置相关的旋转。对每一对维度 (2i,2i+1):

[q2i′q2i+1′]=[cos⁡(pos⋅θi)−sin⁡(pos⋅θi)sin⁡(pos⋅θi)cos⁡(pos⋅θi)][q2iq2i+1]θi=base−2i/dhead,base=10000(默认)

同样的旋转也施加到 K 上,用的位置是 posk。

最关键的性质 ​

q^mTk^n=qTRθ,m−nk

旋转是按绝对位置做的,但内积的结果只依赖 m−n。

也就是说:注意力分数只由相对距离决定,尽管每一步的旋转用的是绝对位置。这被称为「beautiful trick」——用绝对位置的操作实现了相对位置的效果。

频率的分配 ​

θi 的取值让不同维度对以不同速度旋转:

维度位置频率旋转速度编码什么
低维高快相邻顺序(近程)
高维低慢长距离关系(远程)

这形成了一个多尺度的位置表示。RoPE 还有一个附带的好性质:长距离衰减——距离越远的 token 对,注意力分数自然越低。这和 ALiBi 显式加的偏置达成的是同一件事。

RoPE 的操作对象是 Q、K 里成对的维度。

对每一对维度 (2i, 2i+1) 施加一次旋转

  ┌ q_{2i}   ┐       ┌ cos(pos·θ_i)  −sin(pos·θ_i) ┐ ┌ q_{2i}   ┐
  └ q_{2i+1} ┘   ×   └ sin(pos·θ_i)   cos(pos·θ_i) ┘ └ q_{2i+1} ┘

  θ_i = base^(−2i/d_head),base 默认 10000
  同一份旋转也施加到 K 上,用的是它自己的位置 pos_k

为什么「按绝对位置旋转」能得到相对位置的效果
  q̂_m^T k̂_n = q^T R_{θ, m−n} k
  旋转用的是绝对位置,但内积的结果只依赖 m − n

多尺度频率(d_head 内的维度按 θ_i 分档,越往高维转得越慢)
  低维 ── θ_i 大 ── 转得快 ── 短距离内就转完一圈 ── 编码相邻顺序(近程)
  高维 ── θ_i 小 ── 转得慢 ── 要走很远才转完 ──── 编码长距离关系(远程)

附带的一条好性质:距离越远的 token 对,Q 与 K 的夹角越大
   ──▶ 内积自然更低,长距离注意力被压低
   ──▶ ALiBi 靠直接加一个负的偏置达到的是同一件事

base 是长上下文的旋钮 ​

base 默认 10000,但它是个可以调的旋钮:调大 base 会拉伸每一个波长,从而扩大可用的上下文长度。

这就是后面所有 RoPE 外推方法的入口——不改架构、不动训练流程,只调一个频率参数。

base 是唯一一个不改架构就能扩上下文的旋钮。

base 默认 10000
   │
   └─ 调大 base ──▶ 每个 θ_i 变小 ──▶ 每个波长被拉长
                ──▶ 同一个位置区间里转过的角度更小
                ──▶ 可用的上下文长度变大

这一步是所有外推方法的入口:不改架构、不动训练流程,只调一个频率参数。

但它只解决「能不能编到那么远」:沿用训练时的 base,
输入远超训练长度时效果仍会明显下降 ──▶ 所以有了后面三类缩放方案。

长上下文的外推方法 ​

RoPE 本身也不是天生就能外推:沿用训练时的 base,输入远超训练长度时效果会明显下降。三类解法:

Position Interpolation(位置插值) ​

把位置索引按训练长度与目标长度的比例压回去,让长序列落进模型见过的范围:

θi′=θi⋅LtrainLtarget

NTK-aware 插值 ​

不整体压缩,而是调 base 频率、同时保住高频分量:

θi′=θi⋅α−2i/d

更实用的做法是分段:低频维度做完整插值,高频维度保持原样——因为高频维度负责近程顺序,压掉它们会直接损害局部语序感知。

YaRN ​

YaRN 结合了频率内插(NTK-aware)+ 温度缩放:长距离 logit 除以 1+t,抑制远距离注意力被过度放大。

效果量级:YaRN 让 LLaMA-2 7B 的上下文从 4k 扩到 128k;Llama 3 也走这条路从 8K 扩到 128K。代价是需要在微调阶段应用,不是纯推理期的技巧。

完整对应关系:

变体外推能力训练成本用在
绝对正弦余弦差零原始 Transformer、早期 BERT
学习式绝对无极小GPT-2、GPT-3
RoPE配缩放可外推零Llama 2/3/4、Qwen 2/3、Mistral、DeepSeek-V3、Kimi
RoPE + YaRN极好微调阶段Qwen2-1M、Llama 3.1 128K
ALiBi极好(开箱)零BLOOM、MPT、Baichuan

Dynamic NTK:把缩放因子推迟到推理期决定 ​

上面三种都是训练期定好的方案。Dynamic NTK 换了个时机:推理时按实际输入长度动态算缩放因子 —— 输入不超过训练长度就不缩放,超了才按超出的比例缩放。

这样做的收益是短输入不会被不必要的缩放干扰。PI 和静态 NTK 是「为了能处理 32K,把 4K 也一起压了」,而实际上大部分请求根本用不到长上下文,压缩只会平白损害短输入的精度。Dynamic NTK 把这件事变成了按需生效。

代价是推理期的位置编码不再可缓存 —— 缩放因子随时可能变。

外推能力的量级对照 ​

方法外推能力是否需要微调质量损失
无处理(直接外推)差否严重
PI中(约 8×)少量微调轻微
NTK-aware好(约 16×)可选轻微
YaRN好(约 32× 以上)少量微调极小
Dynamic NTK好否轻微
长上下文继续预训练取决于数据全量继续训练最小

这张表里的倍数是训练长度的倍数(4K 训练 → YaRN 档位对应 128K 上下),不是绝对长度。它给的是量级而不是保证 —— 同一个方法在不同的数据与模型上都可能有出入。

最后一档:直接在长文本上继续训练 ​

更彻底的路是不做技巧,直接喂长数据:LLaMA 2 是 4K,LLaMA 3 通过在长文本上继续训练扩到 128K。

这一档的瓶颈不在算法而在数据。 互联网上的文本绝大多数不到 4K token,真正长的材料(完整书籍、长代码文件、长对话记录)相对稀缺 —— 要凑出足够的长上下文训练语料,得主动构造(拼接相关文档、生成跨文档的问答对)。

「支持 128K」与「在 128K 上有效」是两件事

模型配置文件里写 max_position_embeddings: 131072 只说明位置编码能编到那里。真实有效长度要靠长上下文基准测出来 —— 大量模型在 4K–8K 内表现稳定,往中间放信息就开始掉(Lost in the Middle)。测法见 14-长上下文技术。

外推方法的谱系,倍数按「训练长度的倍数」读。

无处理      ── 差 ─────────────────────── 直接外推就退化
   │
PI          ── 中 ── 约 8× ───────────── 位置索引按 L_train / L_target 压回训练范围
   │                                      代价:短输入的精度被一起压了
NTK-aware   ── 好 ── 约 16× ──────────── 调 base 频率,同时保住高频分量
   │                                      更实用的做法是分段:低频插值、高频原样
   │                                      高频维度负责近程语序,压掉会直接损害局部顺序感知
YaRN        ── 好 ── 约 32× 以上 ─────── NTK 内插 + 温度缩放:长距离 logit 除以 √(1+t)
   │                                      LLaMA-2 7B 靠它从 4k 扩到 128k
   │                                      代价:要在微调阶段应用,不是纯推理期技巧
Dynamic NTK ── 好 ── 按实际输入长度决定 ── 推理期才定缩放因子
   │                                      好处:短输入不被无谓压缩
   │                                      代价:位置编码不再可缓存
长上下文继续预训练 ── 取决于数据 ──────── 不做技巧,直接喂长数据
                                          瓶颈从算法转到数据:互联网上真正长的材料稀缺

ALiBi:不做嵌入,直接改注意力分数 ​

ALiBi(Attention with Linear Biases) 走的是另一条路:不碰嵌入,直接给注意力分数加一个与距离成比例的负偏置:

attn_score[i,j]=qi⋅kjd−mh⋅|i−j|

其中 mh 是每个注意力头各自的斜率(例如 1/28h/H)——不同头用不同的衰减速度,形成多尺度的距离敏感性。

三个特点:

  • 不引入任何额外参数,训练成本为零
  • 长度外推开箱即用——推理时只要把下三角位置矩阵的值放大到匹配实际输入长度就行
  • 该文报告它在原训练长度上就能追平正弦余弦式,且外推表现更好

和 RoPE 的对比很直观:两者都在降低远距离 token 对之间的注意力,只是手段不同——RoPE 靠增大 Q、K 之间的夹角来压低内积,ALiBi 靠直接加一个大的负数。

一个实践差别:ALiBi 的外推开箱即用比 RoPE 好(RoPE 需要配套的缩放技巧),但 RoPE 生态更成熟、下游任务表现通常更好。

RoPE 为什么赢了 ​

三条合起来:

  1. 不改架构就能插进注意力——不像 ALiBi 要改注意力分数的计算路径,RoPE 只是对 Q、K 做一次变换
  2. 天然编码相对位置——通过内积的 (m−n) 依赖,白拿了相对编码的好处
  3. base 超参是一个干净的旋钮——长上下文微调时只调它,不用改网络结构

而 ALiBi 虽然开箱外推更强,但没长成主流——说明「工程上可调、生态可复用」这件事的权重不低于「纯技术指标」。

两条研究层面的结论(影响你怎么读「哪个更好」) ​

一、相对位置编码在长度外推上一致优于绝对编码,原因在于它的平移不变性(shift invariance)——相对距离不随序列整体移动而改变,这是理论上就成立的优势。

二、评测指标会显著改变结论。 T5-Bias 家族(ALiBi、KERPLE、FIRE)在语言建模的困惑度上表现更强,而 RoPE 类方法在复杂下游任务上往往更好。

同一批方法的排名会因为评测指标不同而翻转。**只看困惑度类的指标不足以判断一个位置编码方案的实际能力**——这类指标可能反映不了复杂下游任务的表现。这是当前这一块评测标准化不足的问题。

与分词、嵌入链路的关系 ​

调用链上是这个顺序:

文本
   │  tokenizer 切分
   ▼
token 序列
   │  词嵌入矩阵
   ▼
词嵌入 (N, d_model)
   │
   ├─ 绝对位置编码在这一步相加(固定的正弦余弦矩阵,或可训练的位置嵌入)
   │
   ▼
┌─ 编码器层 × N ──────────────────────────────────────────┐
│  注意力层                                               │
│     ├─ ALiBi:在 attention score 上减 m_h · |i − j|      │
│     └─ RoPE:在每层内部对 Q、K 按各自的位置做旋转         │
│  Add & Norm → FFN → Add & Norm                          │
└─────────────────────────────────────────────────────────┘

嵌入模型同样需要位置编码——它是 Transformer,就有这个问题。所以在 11-RAG 检索增强 的嵌入链路里,位置编码决定了这个嵌入模型能处理多长的输入:绝对位置编码的模型超过训练长度直接失效,用 RoPE 的模型靠调 base 外推。

相关 ​

参考 ​

贡献者 ​

文件历史 ​