绝对位置编码 vs 相对位置编码
绝对位置编码
绝对位置编码为序列中每个位置分配一个固定的编码向量,然后与词嵌入相加:
输入=词嵌入(token)+位置编码(pos) 输入 = 词嵌入(token) + 位置编码(pos)输入=词嵌入(token)+位置编码(pos)
典型代表是原始 Transformer 的正余弦位置编码:
PE(pos,2i)=sin(pos100002i/dmodel),PE(pos,2i+1)=cos(pos100002i/dmodel) PE(pos, 2i) = \sin\left(\frac{pos}{10000^{2i/d_{\text{model}}}}\right), \quad PE(pos, 2i+1) = \cos\left(\frac{pos}{10000^{2i/d_{\text{model}}}}\right)PE(pos,2i)=sin(100002i/dmodelpos),PE(pos,2i+1)=cos(100002i/dmodelpos)
优点:
- 无需训练,无额外参数;
- 数值稳定,值域[−1,1][-1, 1][−1,1];
- 理论上可外推到任意位置。
缺点:
- 直接建模的是绝对位置,而不是相对距离;
- 长序列性能会衰减,位置编码差异随距离增大而模糊;
- 实际外推能力有限,训练时没见过的位置表现差。
相对位置编码
相对位置编码不直接编码“我在第几个位置”,而是建模 token 之间的相对距离。它通常不在输入层加位置向量,而是在注意力计算中引入相对位置信息。
优点:
- 直接建模相对距离,符合注意力本质;
- 外推能力更强;
- 对长序列更友好。
缺点:
- 实现更复杂;
- 某些方法会增加计算量或参数量。
旋转位置编码(RoPE)是目前最流行的相对位置编码,被 LLaMA、GPT-J、PaLM 等大量先进模型采用。
RoPE(旋转位置编码)是什么?
核心思想
RoPE 的核心是:对 Query 和 Key 向量进行旋转,旋转角度与 token 的位置有关。
这样,两个 token 的 Q 和 K 做内积时,结果只依赖于它们的相对距离。
在二维空间中,一个向量(x,y)(x,y)(x,y)逆时针旋转角度θθθ可以通过旋转矩阵实现:
R(θ)=[cosθ−sinθsinθcosθ] R(\theta) = \begin{bmatrix} \cos\theta & -\sin\theta \\ \sin\theta & \cos\theta \end{bmatrix}R(θ)=[cosθsinθ−sinθcosθ]
RoPE 对位置mmm的向量乘以R(mθ)R(m\theta)R(mθ),对位置nnn的向量乘以R(nθ)R(n\theta)R(nθ)。
当计算注意力内积时:
(R(mθ)q)⊤(R(nθ)k)=q⊤R(mθ)⊤R(nθ)k=q⊤R((n−m)θ)k (R(m\theta)q)^\top (R(n\theta)k) = q^\top R(m\theta)^\top R(n\theta)k = q^\top R((n-m)\theta)k(R(mθ)q)⊤(R(nθ)k)=q⊤R(mθ)⊤R(nθ)k=q⊤R((n−m)θ)k
内积只依赖于相对距离n−mn-mn−m,与绝对位置无关。这就是 RoPE 的数学本质。
例子:二维子块旋转
为了手算,我们取一个很小的模型:
d_model = 4 分成 2 个二维子块 频率:θ_0 = 1, θ_1 = 0.1假设原始 Query 向量q=[1,0,1,0]q = [1, 0, 1, 0]q=[1,0,1,0],原始 Key 向量k=[1,0,1,0]k = [1, 0, 1, 0]k=[1,0,1,0]。
我们计算位置m=1m = 1m=1的 Q 和位置n=3n = 3n=3的 K 的内积。
位置 1 的 Q 旋转
第一个子块(1,0)(1, 0)(1,0),旋转角度1×1=11 \times 1 = 11×1=1:
R(1)[10]=[cos1−sin1sin1cos1][10]=[cos1sin1]=[0.54030.8415] R(1)\begin{bmatrix}1\\0\end{bmatrix}=\begin{bmatrix}\cos 1&-\sin 1\\\sin 1&\cos 1\end{bmatrix}\begin{bmatrix}1\\0\end{bmatrix}=\begin{bmatrix}\cos 1\\\sin 1\end{bmatrix}=\begin{bmatrix}0.5403\\0.8415\end{bmatrix}R(1)[10]=[cos1sin1−sin1cos1][10]=[cos1sin1]=[0.54030.8415]
第二个子块(1,0)(1, 0)(1,0),旋转角度1×0.1=0.11 \times 0.1 = 0.11×0.1=0.1:
R(0.1)[10]=[cos0.1−sin0.1sin0.1cos0.1][10]=[cos0.1sin0.1]=[0.99500.0998] R(0.1)\begin{bmatrix}1\\0\end{bmatrix}=\begin{bmatrix}\cos 0.1&-\sin 0.1\\\sin 0.1&\cos 0.1\end{bmatrix}\begin{bmatrix}1\\0\end{bmatrix}=\begin{bmatrix}\cos 0.1\\\sin 0.1\end{bmatrix}=\begin{bmatrix}0.9950\\0.0998\end{bmatrix}R(0.1)[10]=[cos0.1sin0.1−sin0.1cos0.1][10]=[cos0.1sin0.1]=[0.99500.0998]
所以旋转后的 Q:
qm=[0.5403,0.8415,0.9950,0.0998] q_m = [0.5403, 0.8415, 0.9950, 0.0998]qm=[0.5403,0.8415,0.9950,0.0998]
位置 3 的 K 旋转
第一个子块(1,0)(1, 0)(1,0),旋转角度3×1=33 \times 1 = 33×1=3:
R(3)[10]=[cos3sin3]=[−0.99000.1411] R(3)\begin{bmatrix}1\\0\end{bmatrix}=\begin{bmatrix}\cos 3\\\sin 3\end{bmatrix}=\begin{bmatrix}-0.9900\\0.1411\end{bmatrix}R(3)[10]=[cos3sin3]=[−0.99000.1411]
第二个子块(1,0)(1, 0)(1,0),旋转角度3×0.1=0.33 \times 0.1 = 0.33×0.1=0.3:
R(0.3)[10]=[cos0.3sin0.3]=[0.95530.2955] R(0.3)\begin{bmatrix}1\\0\end{bmatrix}=\begin{bmatrix}\cos 0.3\\\sin 0.3\end{bmatrix}=\begin{bmatrix}0.9553\\0.2955\end{bmatrix}R(0.3)[10]=[cos0.3sin0.3]=[0.95530.2955]
所以旋转后的 K:
kn=[−0.9900,0.1411,0.9553,0.2955] k_n = [-0.9900, 0.1411, 0.9553, 0.2955]kn=[−0.9900,0.1411,0.9553,0.2955]
计算内积
qm⋅kn=0.5403×(−0.9900)+0.8415×0.1411+0.9950×0.9553+0.0998×0.2955 q_m \cdot k_n = 0.5403 \times (-0.9900) + 0.8415 \times 0.1411 + 0.9950 \times 0.9553 + 0.0998 \times 0.2955qm⋅kn=0.5403×(−0.9900)+0.8415×0.1411+0.9950×0.9553+0.0998×0.2955
逐项:
- 0.5403×(−0.9900)=−0.53490.5403 \times (-0.9900) = -0.53490.5403×(−0.9900)=−0.5349
- 0.8415×0.1411=0.11870.8415 \times 0.1411 = 0.11870.8415×0.1411=0.1187
- 0.9950×0.9553=0.95050.9950 \times 0.9553 = 0.95050.9950×0.9553=0.9505
- 0.0998×0.2955=0.02950.0998 \times 0.2955 = 0.02950.0998×0.2955=0.0295
总和:
−0.5349+0.1187+0.9505+0.0295=0.5638 -0.5349 + 0.1187 + 0.9505 + 0.0295 = 0.5638−0.5349+0.1187+0.9505+0.0295=0.5638
验证只依赖于相对距离
相对距离n−m=3−1=2n - m = 3 - 1 = 2n−m=3−1=2。
我们再取位置m=0m = 0m=0的 Q 和位置n=2n = 2n=2的 K,相对距离也是 2。
位置 0 的 Q:角度为 0,旋转后仍是[1,0,1,0][1, 0, 1, 0][1,0,1,0]。
位置 2 的 K:
- 第一子块角度2×1=22 \times 1 = 22×1=2:[cos2,sin2]=[−0.4161,0.9093][\cos 2, \sin 2] = [-0.4161, 0.9093][cos2,sin2]=[−0.4161,0.9093]
- 第二子块角度2×0.1=0.22 \times 0.1 = 0.22×0.1=0.2:[cos0.2,sin0.2]=[0.9801,0.1987][\cos 0.2, \sin 0.2] = [0.9801, 0.1987][cos0.2,sin0.2]=[0.9801,0.1987]
所以k2=[−0.4161,0.9093,0.9801,0.1987]k_2 = [-0.4161, 0.9093, 0.9801, 0.1987]k2=[−0.4161,0.9093,0.9801,0.1987]。
内积:
q0⋅k2=1×(−0.4161)+0×0.9093+1×0.9801+0×0.1987=0.5640 q_0 \cdot k_2 = 1 \times (-0.4161) + 0 \times 0.9093 + 1 \times 0.9801 + 0 \times 0.1987 = 0.5640q0⋅k2=1×(−0.4161)+0×0.9093+1×0.9801+0×0.1987=0.5640
与之前算出的 0.5638 几乎相同(差异来自舍入误差)。这证明了:内积只依赖于相对距离n−mn - mn−m,与绝对位置无关。
为什么大家都喜欢用 RoPE?
| 优点 | 说明 |
|---|---|
| 显式相对位置 | 内积仅依赖相对距离,符合注意力本质 |
| 无限外推 | 旋转是正交变换,可无限延伸,理论上可处理任意长度 |
| 无参高效 | 零额外参数,计算开销可忽略 |
| 与注意力天然结合 | 直接在 Q、K 上旋转,不改变模型结构 |
| 多频率覆盖 | 不同维度对用不同频率,兼顾局部与全局 |
正因为这些优势,RoPE 已成为现代大模型位置编码的默认选择。
P-RoPE(Proportional RoPE)是什么?
2026 年 Gemma 4 引入了一种轻量变体 P-RoPE:
- 只对每个注意力头的前 25% 维度进行旋转,其余维度保持原样。
- 例如
head_dim = 512时,仅前 128 维参与旋转。 - Gemma 4 采用“双 RoPE”配置:
- 滑动窗口层:标准 RoPE(θ=10000\theta = 10000θ=10000)
- 全局注意力层:P-RoPE(θ=1,000,000\theta = 1,000,000θ=1,000,000)
背后的假设:
- 位置信息的高频变化只需少数维度就能充分表达;
- 大部分维度可以保留为纯内容表示,减少位置信号对语义空间的干扰。
效果:实现极其简单,但在 Gemma 4 中被验证有效,代表了位置编码从“全覆盖”向“按需分配”演变的新趋势。
总结
| 对比项 | 绝对位置编码(正弦) | 相对位置编码(RoPE) | P-RoPE |
|---|---|---|---|
| 编码对象 | 绝对位置 | 相对距离 | 部分维度相对距离 |
| 加入位置 | 输入层相加 | 注意力中旋转 Q、K | 仅旋转部分维度 |
| 参数量 | 0 | 0 | 0 |
| 外推能力 | 有限 | 强 | 强 |
| 典型模型 | 原始 Transformer | LLaMA、GPT-J、PaLM | Gemma 4 |
| 核心优势 | 简单、无参 | 相对位置、外推、高效 | 减少位置干扰、按需分配 |
一句话: RoPE 通过对 Q、K 做与位置相关的旋转,让注意力内积只依赖相对距离;它无参、高效、外推强,因此成为现代大模型的首选。
P-RoPE 则进一步只旋转部分维度,在 Gemma 4 中验证有效,代表了位置编码的新趋势。