四:位置编码与 RoPE¶
来源:http://mp.weixin.qq.com/s?__biz=MzYyNTk3Njg1NA==&mid=2247483773&idx=1&sn=1731b7351575c7e53b2a19449cebf22f&chksm=f01eb204c7693b12ff4021c807e97df71cee685b663127d4726276b44f2b4ecc3fe3709da0c9#rd
1. 学习定位¶
位置编码解决的是 Transformer 中的顺序信息问题。self-attention 本身根据 token 内容做两两匹配,但如果不加入位置机制,它并不知道 token 的先后顺序,也不知道两个 token 相距多远。 第四天重点是 RoPE,也就是 Rotary Position Embedding。它是现代 decoder-only LLM 中非常常见的位置编码方案。学习 RoPE 不能只记住“旋转”这个词,而要理解它在 attention 中的作用位置、数学形式、为什么能让 attention score 感知相对距离,以及它和绝对位置编码、相对位置编码的关系。 今天的知识链路是:
self-attention 本身无顺序信息
-> 需要位置编码
-> 绝对位置编码:把位置向量加到 token embedding
-> 相对位置编码:在 attention 中显式建模相对距离
-> RoPE:对 Q/K 按位置做旋转,使 QK 内积天然包含相对位置信息
-
绝对位置编码和相对位置编码有什么区别。
-
sinusoidal position encoding 的公式和直觉。
-
RoPE 作用在 Q/K/V 的哪个部分。
-
RoPE 为什么能体现相对位置。
-
RoPE 的二维旋转矩阵怎么写。
-
rotate_half、cos/sin cache、position_ids的工程实现。 -
RoPE 对长上下文外推有什么优点和局限。
2. Self-Attention 的位置缺失问题¶
self-attention 的核心计算是:
如果不加入任何位置信息,Q、K、V 都只来自 token 内容表示。此时 attention 只能知道“哪些 token 内容相关”,不能天然知道“谁在前、谁在后、距离多远”。 从结构上看,纯 self-attention 对输入顺序是 permutation equivariant 的。也就是说,如果把输入 token 顺序打乱,输出也会对应地打乱,但模型内部没有额外机制区分原始顺序。 自然语言中顺序非常关键: 两个句子 token 集合相同,但语义不同。位置编码就是为 Transformer 提供顺序信息的机制。3. 位置编码的基本分类¶
常见位置机制可以粗略分成几类:
绝对位置编码:
为每个绝对位置 m 提供位置向量 p_m。
常见形式是 x_m + p_m。
相对位置编码:
在 attention 中显式使用相对距离 i-j。
常见形式是给 attention score 加相对 bias 或相对 key。
旋转位置编码 RoPE:
按位置旋转 Q/K。
Q/K 的点积结果天然依赖相对距离。
线性 bias 类方法 ALiBi:
不加位置 embedding,而是在 attention score 中加入与距离成比例的 bias。
4. 绝对位置编码¶
绝对位置编码给每个位置一个位置向量 p_m,然后和 token embedding 相加:
m 个 token 的表示中同时包含内容信息和绝对位置信息。
常见绝对位置编码包括:
- learned absolute position embedding:每个位置一个可学习向量。
- sinusoidal positional encoding:用固定 sin/cos 函数生成位置向量。
绝对位置编码的优点是实现简单,直接加到 embedding 上即可。缺点是它主要告诉模型“当前位置是第几位”,但相对距离信息需要模型自己从绝对位置中学习出来。learned absolute embedding 还受最大训练长度限制,对未见过的位置外推能力较弱。
5. Sinusoidal 位置编码¶
原始 Transformer 使用固定 sinusoidal 位置编码:
PE(pos, 2i) = sin(pos / 10000^(2i / d_model))
PE(pos, 2i + 1) = cos(pos / 10000^(2i / d_model))
pos 是位置。
-
i是维度对的索引。 -
d_model是模型隐藏维度。
sin/cos 的不同频率对应不同尺度的位置变化。低维或高频部分对短距离变化敏感,高维或低频部分能表达更长尺度的位置。 sinusoidal encoding 是固定函数,不需要训练参数,并且可以为训练长度之外的位置继续计算位置向量。这使它比 learned absolute embedding 更具外推潜力。 但 sinusoidal 仍然以加性绝对位置的方式注入输入表示。相对距离信息不是直接加到 attention score 中,而是希望模型通过后续层学出来。
6. 相对位置编码¶
相对位置编码关注两个 token 之间的相对距离,而不是每个 token 的绝对编号。对于 attention 来说,位置 i attend 位置 j 时,更直接有用的信息往往是:
bias_{i-j} 或 r_{i-j} 都依赖相对距离。
相对位置编码更贴近语言中的距离关系。例如“当前词更关注前一个词”“主谓之间相隔 3 个 token”等模式,本质上与相对距离有关。
缺点是某些相对位置实现会引入额外 attention bias 矩阵或相对位置表,实现和缓存相对复杂。
7. RoPE 的核心思想¶
RoPE 的目标是用一种优雅方式同时获得绝对位置和相对位置的好处。 它不把位置向量加到 token embedding 上,而是在 attention 内部对 Q 和 K 做位置相关的旋转:
其中m 和 n 是位置,R_m 和 R_n 是由位置决定的旋转矩阵。
attention score 变成:
由于旋转矩阵有良好的正交性质,这个内积可以变形为:
这说明 attention score 最终依赖相对位置 n-m。这就是 RoPE 的关键:它看起来对 Q/K 注入绝对位置旋转,但 Q/K 点积后自然产生相对位置信息。
8. 二维旋转矩阵¶
RoPE 的基本单元是二维旋转。对一个二维向量:
位置m 对应的旋转角度是 m * theta。旋转矩阵为:
旋转后:
旋转矩阵是正交矩阵,不改变向量模长:
这也是 RoPE 相对稳定的重要原因之一:它改变向量方向以注入位置信息,但不直接放大或缩小向量范数。
9. 高维 RoPE¶
实际 Q/K 的 head dimension 通常是偶数,例如 64、80、128。RoPE 会把向量按相邻两维分组,每组做二维旋转。 示例:
q = [q0, q1, q2, q3, ..., q_{d-2}, q_{d-1}]
(q0, q1) 使用 theta_0
(q2, q3) 使用 theta_1
...
(q_{d-2}, q_{d-1}) 使用 theta_{d/2-1}
base = 10000,也有模型使用其他 base 或长上下文缩放策略。
高维 RoPE 相当于把多个不同频率的二维旋转拼在一起。不同频率对应不同位置尺度,使模型能感知短距离和长距离关系。
10. RoPE 的相对位置性质¶
RoPE 最重要的性质来自旋转矩阵乘法:
因此: 这意味着虽然q 和 k 分别按绝对位置 m 和 n 旋转,但它们的内积只通过 n-m 体现位置关系。
这种性质使 RoPE 可以被理解为“用绝对位置旋转实现相对位置建模”。它不是简单把位置向量加到 embedding,而是在 attention score 的核心内积中引入相对距离。
11. RoPE 作用在 Q/K 而不是 V¶
RoPE 通常作用在 Q 和 K 上,而不是 V 上。 原因是 attention 权重由 Q/K 点积决定:
位置关系应该影响“当前位置关注谁”,也就是影响 attention score。对 Q/K 注入位置后,score 会带有相对位置信息。 V 是被聚合的内容载体。通常不需要对 V 做 RoPE,因为 value 的职责是提供内容,而不是决定位置相关的匹配权重。 面试中可简洁表达:12. RoPE 与 Sinusoidal 的关系¶
RoPE 和 sinusoidal position encoding 都使用 sin/cos 和多频率思想。 区别在于:
Sinusoidal PE:
把 sin/cos 位置向量加到 token embedding。
是加性位置编码。
RoPE:
用 sin/cos 构造旋转矩阵,对 Q/K 做位置相关旋转。
是乘性或旋转式位置编码。
13. RoPE 的工程实现¶
直接构造完整旋转矩阵很浪费。实际实现通常使用 cos、sin 和 rotate_half。
对向量:
cos 和 sin 根据 position 和 inverse frequency 预先计算并缓存。
典型 shape:
q, k: [B, H, T, D]
cos, sin: [1, 1, T, D]
q_rot = q * cos + rotate_half(q) * sin
k_rot = k * cos + rotate_half(k) * sin
[B, T, H, D],但核心思想相同。
14. Position IDs 与 KV Cache¶
RoPE 依赖 token 的 position id。训练时,位置通常是:
推理时使用 KV cache 后,每次只输入新 token,但新 token 的 position id 必须等于它在完整上下文中的真实位置。 例如 prompt 长度为 128,生成第一个新 token 时 position id 应是 128,而不是 0。否则 Q/K 的旋转角度会错,模型看到的位置关系会混乱。 这也是 RoPE 工程实现中的常见 bug: - position_ids 没有随 cache 长度偏移。-
left padding 后 position_ids 处理错误。
-
sliding window 或 context extension 时位置编号不一致。
-
cos/sin cache 长度不足。
15. RoPE 与长上下文外推¶
RoPE 相比 learned absolute position embedding 更适合长度外推,因为它可以为更长位置继续计算旋转角度,不依赖固定位置 embedding 表。 但 RoPE 不是无限可靠的长上下文解决方案。模型训练时只见过有限长度,推理到更长位置时,旋转相位、频率分布和 attention 模式都可能偏离训练分布。尤其高频维度在长位置上会快速旋转,可能带来外推不稳定。 因此现代长上下文模型常使用 RoPE scaling 或变体,例如调整 base、线性缩放 position、NTK-aware scaling、YaRN、LongRoPE 等。第四天重点不是掌握所有变体,而是知道:
16. ALiBi 对照¶
ALiBi 是另一种位置方法。它不向 embedding 添加位置向量,也不旋转 Q/K,而是在 attention score 上加入与距离成比例的线性 bias:
对于 causal LM,bias 通常让距离越远的位置受到越大惩罚,从而引入近因偏置。 ALiBi 的优点是实现简单、内存开销小、长度外推能力强。缺点是表达形式较固定,主要提供线性距离偏置,不像 RoPE 那样通过旋转影响 Q/K 内积结构。 面试中可以把 ALiBi 作为对比:17. RoPE 的优点¶
RoPE 的主要优点包括: - 直接作用在 attention 的 Q/K 匹配上,使 score 感知相对位置。
-
不需要学习独立的位置 embedding 表。
-
能为任意位置计算 sin/cos,具备一定长度外推能力。
-
旋转矩阵正交,不改变向量范数,数值上较稳定。
-
与 multi-head attention 兼容,计算开销较小。
-
在 decoder-only LLM 中实践效果好,已经成为常见默认选择。
从面试角度,最核心的优点是:RoPE 用旋转方式把绝对位置注入 Q/K,同时让点积体现相对位置。
18. RoPE 的局限¶
RoPE 也有局限: - head dimension 通常需要偶数,或只对偶数维 rotary_dim 做旋转。
-
长度外推不是无限可靠,超出训练长度太多可能退化。
-
实现依赖 position_ids,KV cache、padding、截断、滑窗场景容易出错。
-
不同模型的 RoPE base、scaling、rotary_dim 可能不同,不能随意替换。
-
长上下文扩展通常需要配合 RoPE scaling 和继续训练。
因此 RoPE 不是“解决所有长上下文问题”的单独组件,而是位置建模方案的一部分。
19. 常见实现细节¶
常见 RoPE 实现包含这些步骤:
1. 根据 head_dim 构造 inv_freq。
2. 根据 position_ids 计算 freqs。
3. 得到 cos 和 sin cache。
4. 对 q/k 执行 rotate_half。
5. q_rot = q * cos + rotate_half(q) * sin。
6. k_rot = k * cos + rotate_half(k) * sin。
7. 用 q_rot 和 k_rot 计算 attention score。
def rotate_half(x):
x1 = x[..., 0::2]
x2 = x[..., 1::2]
return stack([-x2, x1], dim=-1).reshape_as(x)
def apply_rope(x, cos, sin):
return x * cos + rotate_half(x) * sin
q = apply_rope(q, cos, sin)
k = apply_rope(k, cos, sin)
scores = q @ k.transpose(-2, -1)
(0,1),(2,3);有些实现把前半维和后半维配对。不同实现只要 cos/sin 和 rotate 方式一致即可。
20. RoPE 常见错误¶
RoPE 常见错误包括: - 把 RoPE 加到 token embedding 上,而不是 Q/K 上。
-
只旋转 Q,不旋转 K,或 Q/K position id 不一致。
-
错误旋转 V。
-
rotate_half的维度配对方式和 cos/sin 构造不一致。 -
KV cache 推理时 position id 从 0 重新开始。
-
left padding 时 position id 没有排除 pad。
-
cos/sin cache 长度小于实际序列长度。
-
混用不同模型的 RoPE base 或 scaling。
-
对奇数 head_dim 直接两两配对导致 shape 错误。
这些 bug 往往不会立刻报错,但会导致 perplexity 异常、长文本能力退化、生成质量下降或缓存推理结果和无缓存不一致。
21. 面试中的核心表达¶
RoPE 的面试表达可以压缩为:
Transformer 的 self-attention 本身没有顺序信息,所以需要位置编码。
绝对位置编码把位置向量加到 embedding;相对位置编码直接建模 token 间距离。
RoPE 对 Q/K 按位置做二维旋转。
位置 m 的 q 乘 R_m,位置 n 的 k 乘 R_n。
由于 R_m^T R_n = R_{n-m},Q/K 点积自然依赖相对位置 n-m。
RoPE 通常不作用于 V,因为位置关系应影响 attention score。
工程上用 cos/sin cache 和 rotate_half 实现,推理时要正确处理 position_ids 和 KV cache。
22. 参考资料¶
-
RoFormer: Enhanced Transformer with Rotary Position Embedding: https://arxiv.org/abs/2104.09864
-
Attention Is All You Need: https://arxiv.org/abs/1706.03762
-
Self-Attention with Relative Position Representations: https://arxiv.org/abs/1803.02155
-
Train Short, Test Long: Attention with Linear Biases Enables Input Length Extrapolation: https://arxiv.org/abs/2108.12409
-
RoPE 作者苏剑林介绍:Transformer升级之路:2、博采众长的旋转式位置编码:https://spaces.ac.cn/archives/8265
-
相对位置编码和绝对位置编码:让研究人员绞尽脑汁的 Transformer 位置编码:https://kexue.fm/archives/8130
-
视频推荐:通俗易懂 - 大模型的关键技术之一:旋转位置编码 RoPE:https://www.bilibili.com/video/BV12x42127Pb/
-
一文通透位置编码与 RoPE 推导:https://blog.csdn.net/v_JULY_v/article/details/134085503
预览时标签不可点<div class="