跳转至

四:位置编码与 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 内积天然包含相对位置信息
面试中 RoPE 常被追问: - 为什么 Transformer 需要位置编码。

  • 绝对位置编码和相对位置编码有什么区别。

  • sinusoidal position encoding 的公式和直觉。

  • RoPE 作用在 Q/K/V 的哪个部分。

  • RoPE 为什么能体现相对位置。

  • RoPE 的二维旋转矩阵怎么写。

  • rotate_halfcos/sin cacheposition_ids 的工程实现。

  • RoPE 对长上下文外推有什么优点和局限。

2. Self-Attention 的位置缺失问题

self-attention 的核心计算是:

Attention(Q, K, V) = softmax(QK^T / sqrt(d_k))V
如果不加入任何位置信息,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。
实际模型会选择其中一种或某种变体。原始 Transformer 使用 sinusoidal absolute positional encoding;BERT 使用 learned absolute position embedding;T5 使用 relative position bias;很多现代 decoder-only LLM 使用 RoPE;ALiBi 是另一种长上下文外推友好的方案。

4. 绝对位置编码

绝对位置编码给每个位置一个位置向量 p_m,然后和 token embedding 相加:

h_m = token_embedding_m + position_embedding_m
这样第 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 时,更直接有用的信息往往是:

relative distance = i - j
相对位置编码可以有多种实现:

score_{i,j} = q_i^T k_j + bias_{i-j}
或者:

score_{i,j} = q_i^T (k_j + r_{i-j})
这里 bias_{i-j}r_{i-j} 都依赖相对距离。 相对位置编码更贴近语言中的距离关系。例如“当前词更关注前一个词”“主谓之间相隔 3 个 token”等模式,本质上与相对距离有关。 缺点是某些相对位置实现会引入额外 attention bias 矩阵或相对位置表,实现和缓存相对复杂。

7. RoPE 的核心思想

RoPE 的目标是用一种优雅方式同时获得绝对位置和相对位置的好处。 它不把位置向量加到 token embedding 上,而是在 attention 内部对 Q 和 K 做位置相关的旋转:

q_m_rot = R_m q_m
k_n_rot = R_n k_n
其中 mn 是位置,R_mR_n 是由位置决定的旋转矩阵。 attention score 变成:

score_{m,n} = (R_m q_m)^T (R_n k_n)
由于旋转矩阵有良好的正交性质,这个内积可以变形为:

(R_m q)^T (R_n k) = q^T R_{n-m} k
这说明 attention score 最终依赖相对位置 n-m。这就是 RoPE 的关键:它看起来对 Q/K 注入绝对位置旋转,但 Q/K 点积后自然产生相对位置信息。

8. 二维旋转矩阵

RoPE 的基本单元是二维旋转。对一个二维向量:

x = [x_0, x_1]^T
位置 m 对应的旋转角度是 m * theta。旋转矩阵为:

R_m =
[ cos(m theta)  -sin(m theta)
  sin(m theta)   cos(m theta) ]
旋转后:

R_m x =
[ x_0 cos(m theta) - x_1 sin(m theta)
  x_0 sin(m theta) + x_1 cos(m theta) ]
旋转矩阵是正交矩阵,不改变向量模长:

||R_m x|| = ||x||
这也是 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}
每个维度对使用不同频率:

theta_i = base^(-2i / d)
常见 base = 10000,也有模型使用其他 base 或长上下文缩放策略。 高维 RoPE 相当于把多个不同频率的二维旋转拼在一起。不同频率对应不同位置尺度,使模型能感知短距离和长距离关系。

img

10. RoPE 的相对位置性质

RoPE 最重要的性质来自旋转矩阵乘法:

R_m^T R_n = R_{n-m}
因此:

(R_m q)^T (R_n k)
= q^T R_m^T R_n k
= q^T R_{n-m} k
这意味着虽然 qk 分别按绝对位置 mn 旋转,但它们的内积只通过 n-m 体现位置关系。 这种性质使 RoPE 可以被理解为“用绝对位置旋转实现相对位置建模”。它不是简单把位置向量加到 embedding,而是在 attention score 的核心内积中引入相对距离。

img

img

11. RoPE 作用在 Q/K 而不是 V

RoPE 通常作用在 Q 和 K 上,而不是 V 上。 原因是 attention 权重由 Q/K 点积决定:

weights = softmax(QK^T / sqrt(d))
位置关系应该影响“当前位置关注谁”,也就是影响 attention score。对 Q/K 注入位置后,score 会带有相对位置信息。 V 是被聚合的内容载体。通常不需要对 V 做 RoPE,因为 value 的职责是提供内容,而不是决定位置相关的匹配权重。 面试中可简洁表达:

RoPE 加在 Q/K 上,是为了让 attention score 感知相对位置;一般不加在 V 上。

12. RoPE 与 Sinusoidal 的关系

RoPE 和 sinusoidal position encoding 都使用 sin/cos 和多频率思想。 区别在于:

Sinusoidal PE:
  把 sin/cos 位置向量加到 token embedding。
  是加性位置编码。

RoPE:
  用 sin/cos 构造旋转矩阵,对 Q/K 做位置相关旋转。
  是乘性或旋转式位置编码。
sinusoidal PE 把位置作为输入表示的一部分,后续 attention 需要自己学习如何利用这些绝对位置。RoPE 直接改变 Q/K 的点积结构,使 attention score 显式依赖相对距离。 因此 RoPE 更贴近 relative position 的建模目标。

13. RoPE 的工程实现

直接构造完整旋转矩阵很浪费。实际实现通常使用 cossinrotate_half。 对向量:

x = [x0, x1, x2, x3, ...]
定义:

rotate_half(x) = [-x1, x0, -x3, x2, ...]
则 RoPE 可以写成:

x_rot = x * cos + rotate_half(x) * sin
其中 cossin 根据 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
实际框架中也可能使用不同 layout,例如 [B, T, H, D],但核心思想相同。

14. Position IDs 与 KV Cache

RoPE 依赖 token 的 position id。训练时,位置通常是:

position_ids = [0, 1, 2, ..., T-1]
推理时使用 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 等。第四天重点不是掌握所有变体,而是知道:

RoPE 具备一定长度外推潜力,但长上下文扩展仍需要额外缩放和训练策略。

16. ALiBi 对照

ALiBi 是另一种位置方法。它不向 embedding 添加位置向量,也不旋转 Q/K,而是在 attention score 上加入与距离成比例的线性 bias:

score_{i,j} = q_i^T k_j / sqrt(d) + bias_{i,j}
对于 causal LM,bias 通常让距离越远的位置受到越大惩罚,从而引入近因偏置。 ALiBi 的优点是实现简单、内存开销小、长度外推能力强。缺点是表达形式较固定,主要提供线性距离偏置,不像 RoPE 那样通过旋转影响 Q/K 内积结构。 面试中可以把 ALiBi 作为对比:

RoPE: 旋转 Q/K,使 score 自然依赖相对位置。
ALiBi: 直接给 score 加距离相关 bias。

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)
实际代码中要注意偶奇维排列方式。有些实现使用 interleaved pair,即 (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="