位置编码
Transformer 的自注意力不含任何位置信息——对它来说 agent learns 和 learns agent 完全等价。位置编码(Positional Encoding)解决这个问题,而不同的注入方式决定了模型能不能处理超出训练长度的输入。
这一篇讲这条演进线:绝对 → 相对 → RoPE → 长上下文外推。
绝对位置编码
正弦余弦式(原始 Transformer)
把固定的位置矩阵加到词嵌入上:
每个维度是一个不同频率的正弦波(低维高频、高维低频),模型要学会从这种相位模式里读出位置。公式不需要学习,索引时零成本。
致命问题:超过 max_len 就失效。模型只见过 0–2047 的位置,没人告诉它位置 2048 该怎么办——预计算的矩阵里根本没有那一行。
学习式绝对位置嵌入
干脆把位置向量也当成可训练参数(GPT-2、GPT-3 这么做)。成本极小(每层一个 max_len × d 的嵌入表),但外推能力等于没有:模型只能在训练时固定的输入长度上工作,超长直接不可用。
相对位置编码
思路转向:不该告诉模型「你在第 5 位」,而该告诉它「你和对方隔了多远」——因为语义关系取决于相对距离,而不是绝对序号。
Shaw 等人最早的可学习相对位置方案是在注意力里加一项:
其中
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 向量施加一个与位置相关的旋转。对每一对维度
同样的旋转也施加到 K 上,用的位置是
最关键的性质
旋转是按绝对位置做的,但内积的结果只依赖
也就是说:注意力分数只由相对距离决定,尽管每一步的旋转用的是绝对位置。这被称为「beautiful trick」——用绝对位置的操作实现了相对位置的效果。
频率的分配
| 维度位置 | 频率 | 旋转速度 | 编码什么 |
|---|---|---|---|
| 低维 | 高 | 快 | 相邻顺序(近程) |
| 高维 | 低 | 慢 | 长距离关系(远程) |
这形成了一个多尺度的位置表示。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(位置插值)
把位置索引按训练长度与目标长度的比例压回去,让长序列落进模型见过的范围:
NTK-aware 插值
不整体压缩,而是调 base 频率、同时保住高频分量:
更实用的做法是分段:低频维度做完整插值,高频维度保持原样——因为高频维度负责近程顺序,压掉它们会直接损害局部语序感知。
YaRN
YaRN 结合了频率内插(NTK-aware)+ 温度缩放:长距离 logit 除以
效果量级: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) 走的是另一条路:不碰嵌入,直接给注意力分数加一个与距离成比例的负偏置:
其中
三个特点:
- 不引入任何额外参数,训练成本为零
- 长度外推开箱即用——推理时只要把下三角位置矩阵的值放大到匹配实际输入长度就行
- 该文报告它在原训练长度上就能追平正弦余弦式,且外推表现更好
和 RoPE 的对比很直观:两者都在降低远距离 token 对之间的注意力,只是手段不同——RoPE 靠增大 Q、K 之间的夹角来压低内积,ALiBi 靠直接加一个大的负数。
一个实践差别:ALiBi 的外推开箱即用比 RoPE 好(RoPE 需要配套的缩放技巧),但 RoPE 生态更成熟、下游任务表现通常更好。
RoPE 为什么赢了
三条合起来:
- 不改架构就能插进注意力——不像 ALiBi 要改注意力分数的计算路径,RoPE 只是对 Q、K 做一次变换
- 天然编码相对位置——通过内积的
依赖,白拿了相对编码的好处 - 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 外推。
相关
- 02-Transformer 架构 —— 位置编码在整体架构里的位置
- 05-文本分词与子词算法:BPE、WordPiece 与 Unigram —— 位置编码的上一步:文本怎么变成 token 序列
- 11-RAG 检索增强 —— 嵌入模型能处理多长输入,由位置编码决定
参考
- https://aiengineeringfromscratch.com/lesson?path=phases/07-transformers-deep-dive/04-positional-encoding
- https://www.alphaxiv.org/overview/2312.17044v5
- https://huggingface.co/buckets/hf-doc-build/doc-dev/tree/transformers/pr_33174/en/llm_tutorial_optimization.html
- https://ima.qq.com/wiki/ 分享的《词嵌入与位置编码》整理
YJ