概述
Transformer模型本身不具备处理序列顺序的能力(自注意力机制是排列不变的),因此需要位置编码(Position Embedding)来为输入序列的每个位置注入位置信息。在经典的 Transformer 中,我们可以:
- 直接加一个位置向量(绝对位置编码),例如把 “位置 m m m” 的向量记为 x m + p m x_m + p_m xm+pm;
- 或在注意力公式里显式注入相对位置信息(相对位置编码),例如对注意力分数 q i T k j q_i^Tk_j qiTkj 额外加上和 ( i − j ) (i-j) (i−j) 有关的bias。
但是,这两种方法各有优缺点:
- 绝对位置编码实现简单、计算开销小,但它本身并不直接表达“相对位置”,对于长序列外推往往有局限。
- 相对位置编码能让注意力“直接感知”相对位置信息,但实现时常要改动注意力公式,结构更复杂。
因此作者提出 RoPE,出发点是为了能利用上 token 之间的相对位置信息,“通过绝对位置编码的方式实现相对位置编码”。为了达到这个目的,假设通过下述运算来对 q, k 添加绝对位置信息:
q
~
m
=
f
(
q
,
m
)
,
k
~
n
=
f
(
k
,
n
)
\tilde{q}_m = f(q, m), \quad \tilde{k}_n = f(k, n)
q~m=f(q,m),k~n=f(k,n)
也就是说,我们分别对 q, k 设计 f(⋅,m) 和 f(⋅,n),使得经过该变换后, q ~ m \tilde{q}_m q~m 和 k ~ n \tilde{k}_n k~n 就带有了 ”绝对位置信息”。
Attention的核心运算是内积,所以只要 让两个带位置信息的向量 q ~ m \tilde{q}_m q~m 和 k ~ n \tilde{k}_n k~n 在内积时自动带出相对位置信息(也就是让内积只和 n − m n-m n−m 有关),就能让模型感知到相对位置。
因此假设存在恒等关系:
⟨
f
(
q
,
m
)
,
f
(
k
,
n
)
⟩
=
g
(
q
,
k
,
(
n
−
m
)
)
⟨f(q,m),f(k,n)⟩=g(q,k,(n−m))
⟨f(q,m),f(k,n)⟩=g(q,k,(n−m))
所以我们要求出该恒等式的一个(尽可能简单的)解。
RoPE(旋转位置编码)就是作者设计的一个具体的函数 f。它的核心思想是:
-
把向量分成两两一组,在每个二维子空间做一个跟位置索引 m 相关的旋转。
-
类似地,对 k 向量在位置 n 上做相应旋转。
-
由于旋转矩阵有 R m ⊤ R n = R n − m \mathcal{R}_m^\top \mathcal{R}_n = \mathcal{R}_{n-m} Rm⊤Rn=Rn−m 这样的性质,最终就得到:
q ~ m T k ~ n = q T R n − m k , \tilde{q}_m^T \tilde{k}_n = q^T \mathcal{R}_{n-m} k, q~mTk~n=qTRn−mk,
只和 (n−m) 有关,从而实现了“相对位置编码”的效果。
RoPE求解过程
📌欧拉公式: e i θ = cos θ + i sin θ e^{i\theta}=\cos\theta + i\sin\theta eiθ=cosθ+isinθ
-
在二维情形的推导思路
1.1 二维旋转的数学表示
在二维空间中,向量 q = [ q x , q y ] q=[q_x,q_y] q=[qx,qy] 绕原点旋转角度 θ \theta θ 的操作可通过旋转矩阵实现:
R θ = [ cos θ − sin θ sin θ cos θ ] , q ′ = R θ q R_{\theta} = \begin{bmatrix}\cos \theta & -\sin \theta \\\sin \theta & \cos \theta\end{bmatrix}, \quad q' = R_{\theta} \, q Rθ=[cosθsinθ−sinθcosθ],q′=Rθq
这一操作保持向量长度不变,仅改变方向。向量 k k k 同理。
复数视角的旋转:
二维旋转也可用复数乘法表示。将向量 q q q 视为复数 q = q x + i q y q=q_x+iq_y q=qx+iqy,那么绕原点逆时针旋转一个角度 θ ,就可以用“复数乘以复指数”的形式来表达:
q ′ = q ⋅ e i θ = ( q x + i q y ) ( cos θ + i sin θ ) q' = q \cdot e^{i\theta} = (q_x + i \, q_y) \bigl(\cos \theta + i \,\sin \theta\bigr) q′=q⋅eiθ=(qx+iqy)(cosθ+isinθ)
展开可以得到:
q ′ = q x ′ + i q y ′ = ( q x c o s θ − q y s i n θ ) + i ( q x s i n θ + q y c o s θ ) q' = q_x' + iq_y' = (q_xcosθ−q_ysinθ)+i(q_xsinθ+q_ycosθ) q′=qx′+iqy′=(qxcosθ−qysinθ)+i(qxsinθ+qycosθ)
即:
q x ′ = q x c o s ( θ ) − q y s i n ( θ ) q_x'=q_xcos(θ)−q_ysin(θ) qx′=qxcos(θ)−qysin(θ)
q y ′ = q x s i n ( θ ) + q y c o s ( θ ) q_y'=q_xsin(θ)+q_ycos(θ) qy′=qxsin(θ)+qycos(θ)
这恰好就是一个 2D 旋转矩阵作用在向量 ( q x , q y ) (q_x, q_y) (qx,qy) 上的结果:
( q x ′ q y ′ ) = ( cos ( θ ) − sin ( θ ) sin ( θ ) cos ( θ ) ) ( q x q y ) \begin{pmatrix} q_x' \\ q_y' \end{pmatrix} = \begin{pmatrix} \cos(\theta) & -\sin(\theta) \\ \sin(\theta) & \cos(\theta) \end{pmatrix} \begin{pmatrix} q_x \\ q_y \end{pmatrix} (qx′qy′)=(cos(θ)sin(θ)−sin(θ)cos(θ))(qxqy)
这样,“向量的内积”可以转化为“复数相乘后取实部”的形式(如果我们考虑 ⟨ q , k ⟩ = R e ( q ′ ∗ k ′ ‾ ) ⟨q,k⟩ = Re(q' * \,\overline{k'}) ⟨q,k⟩=Re(q′∗k′))1.2 让内积只依赖 n − m n-m n−m
将向量 q q q 视为复数: z q = q x + i q y z_q = q_x + iq_y zq=qx+iqy
我们要在 z q z_q zq 上注入位置 m m m 的信息,记为:
z q , m = f ( z q , m ) z_{q,m} = f\bigl(z_q, m\bigr) zq,m=f(zq,m)
同理,
z k , n = f ( z k , n ) z_{k,n} = f\bigl(z_k, n\bigr) zk,n=f(zk,n)
我们希望
R e [ z q , m z k , n ‾ ] Re[z_{q,m}\,\overline{z_{k,n}}\bigr] Re[zq,mzk,n]
只和 (n - m) 有关,其中 z k , n ‾ \, \overline{z_{k,n}} zk,n表示共轭, 一个自然的做法是,在复数上“乘一个随位置改变的相位因子”(详细推导过程可见 参考链接),即:
z q , m = z q ⋅ e i m θ , z k , n = z k ⋅ e i n θ z_{q,m}=z_q⋅e^{imθ}, z_{k,n} = z_k⋅e^{inθ} zq,m=zq⋅eimθ,zk,n=zk⋅einθ
其中 θ 是一个常数。
为什么这样就可以?
-
两者相乘时:
z q , m z k , n ‾ = ( z q e i m θ ) ( z k e i n θ ) ‾ = z q z k ‾ ⋅ e i m θ e − i n θ = z q z k ‾ ⋅ e i ( m − n ) θ . z_{q,m}\, \overline{z_{k,n}}=(z_qe^{imθ})\, \overline{(z_ke^{inθ})}=z_q\,\overline{z_k}⋅e^{imθ}e^{−inθ}=z_q\,\overline{z_k}⋅e^{i(m−n)θ}. zq,mzk,n=(zqeimθ)(zkeinθ)=zqzk⋅eimθe−inθ=zqzk⋅ei(m−n)θ. -
这样其实部就是:
R e [ z q , m z k , n ‾ ] = R e [ z q z k ‾ ∗ ⋅ e i ( m − n ) θ ] , Re[z_{q,m}\,\overline{z_{k,n}}]=Re[z_q\,\overline{z_k}∗⋅e^{i(m−n)θ}], Re[zq,mzk,n]=Re[zqzk∗⋅ei(m−n)θ],
只依赖于 (m - n),这样就达到了我们的目标。1.3 确定幅度和相位
刚才我们只给出了一个“相位旋转” e i m θ e^{im\theta} eimθ。要更加严格的满足
⟨ f ( q , m ) , f ( k , n ) ⟩ = g ( q , k , ( n − m ) ) ⟨f(q,m),f(k,n)⟩=g(q,k,(n−m)) ⟨f(q,m),f(k,n)⟩=g(q,k,(n−m))
可能还需要考虑幅度是否也跟 m m m 有关。经过仔细推敲(或直接对比实验),通常让幅度保持不变是最简单可行的:也就是只做“纯旋转”而不改变向量模长。
因此,在二维情况下,最终我们定
z q , m = z q ⋅ e i m θ , z_{q,m}=z_q⋅e^{imθ}, zq,m=zq⋅eimθ,
并不会再多乘一个 α ( m ) \alpha(m) α(m) 这样的幅度函数。这样即可保证
z q , m z k , n ‾ = ( z q z k ‾ ) ⋅ e i ( m − n ) θ z_{q,m}\,\overline{z_{k,n}}=(z_q\,\overline{z_k})⋅e^{i(m−n)θ} zq,mzk,n=(zqzk)⋅ei(m−n)θ
只跟 m−n 有关。1.4 回到实数向量形式
从几何上,这就对应旋转矩阵:
( cos ( m θ ) − sin ( m θ ) sin ( m θ ) cos ( m θ ) ) ( q x q y ) \begin{pmatrix} \cos(m\theta) & -\sin(m\theta) \\ \sin(m\theta) & \cos(m\theta) \end{pmatrix} \begin{pmatrix} q_x \\ q_y \end{pmatrix} (cos(mθ)sin(mθ)−sin(mθ)cos(mθ))(qxqy)
所以我们把二维向量 ( q x , q y ) (q_x,q_y) (qx,qy) 在平面上“逆时针旋转” m θ m\theta mθ 的角度,这就完成了“在位置 m m m上对向量 q \boldsymbol{q} q 做编码”。
- 推广到高维空间
多维向量可以“拆分成若干个 2D 子空间”来做同样的旋转。
- 例如一个 4 维向量 q = (q₀, q₁, q₂, q₃),可以拆成两组:(q₀, q₁) 和 (q₂, q₃),分别旋转不同频率的角度。
- 更一般的 d 维向量(d 为偶数)可以拆成 d/2 组,每组用
θ i = 1 1000 0 2 i d \theta_i = \frac {1} {10000^{\frac{2i}{d}}} θi=10000d2i1
等不同的角度。这样就类似于多频率的"分块旋转",形成 RoPE 在实际 Transformer 里的实现方式。
这样我们就得到了 RoPE 最常见的形式:
R m = ( cos ( m θ 0 ) − sin ( m θ 0 ) sin ( m θ 0 ) cos ( m θ 0 ) ⋱ cos ( m θ d 2 − 1 ) − sin ( m θ d 2 − 1 ) sin ( m θ d 2 − 1 ) cos ( m θ d 2 − 1 ) ) \mathcal{R_m} = \begin{pmatrix}\cos(m\theta_0) & -\sin(m\theta_0) & & & \\\sin(m\theta_0) & \cos(m\theta_0) & & & \\ & & \ddots & & \\ & & & \cos\bigl(m\theta_{\frac{d}{2}-1}\bigr) & -\sin\bigl(m\theta_{\frac{d}{2}-1}\bigr) \\ & & & \sin\bigl(m\theta_{\frac{d}{2}-1}\bigr) & \cos\bigl(m\theta_{\frac{d}{2}-1}\bigr)\end{pmatrix} Rm= cos(mθ0)sin(mθ0)−sin(mθ0)cos(mθ0)⋱cos(mθ2d−1)sin(mθ2d−1)−sin(mθ2d−1)cos(mθ2d−1)
对应地,RoPE 的编码可写为:
f ( q , m ) = R m q f(q,m)= \mathcal{R_m}q f(q,m)=Rmq
此外,利用正交矩阵的性质(不改变向量模长),经过旋转后的内积满足:
( R m q ) ⊤ ( R n k ) = q ⊤ R n − m k (\mathcal{R_m}q)^⊤(\mathcal{R_n}k)=q^⊤\mathcal{R_{n−m}}k (Rmq)⊤(Rnk)=q⊤Rn−mk
这正好实现了仅依赖于相对位置信息的效果。
- 高效实现
由于 R m {\mathcal{R}}_m Rm矩阵存在大量零元素,直接用矩阵乘法计算会浪费算力。实际中推荐使用分组的方式,通过逐位对应的乘法实现:
f ( q , m ) = ( q 0 q 1 q 2 q 3 ⋮ q d − 2 q d − 1 ) ⊗ ( cos ( m θ 0 ) cos ( m θ 0 ) cos ( m θ 1 ) cos ( m θ 1 ) ⋮ cos ( m θ d 2 − 1 ) cos ( m θ d 2 − 1 ) ) + ( − q 1 q 0 − q 3 q 2 ⋮ − q d − 1 q d − 2 ) ⊗ ( sin ( m θ 0 ) sin ( m θ 0 ) sin ( m θ 1 ) sin ( m θ 1 ) ⋮ sin ( m θ d 2 − 1 ) sin ( m θ d 2 − 1 ) ) . f(\mathbf{q}, m)= \begin{pmatrix} q_0 \\ q_1 \\ q_2 \\ q_3 \\ \vdots \\ q_{d-2}\\ q_{d-1} \end{pmatrix} \otimes \begin{pmatrix} \cos\bigl(m\theta_0\bigr) \\ \cos\bigl(m\theta_0\bigr) \\ \cos\bigl(m\theta_1\bigr) \\ \cos\bigl(m\theta_1\bigr) \\ \vdots \\ \cos\bigl(m\theta_{\tfrac{d}{2}-1}\bigr) \\ \cos\bigl(m\theta_{\tfrac{d}{2}-1}\bigr) \end{pmatrix} \;+\; \begin{pmatrix} -\,q_1 \\ q_0 \\ -\,q_3 \\ q_2 \\ \vdots \\ -\,q_{d-1}\\ q_{d-2} \end{pmatrix} \otimes \begin{pmatrix} \sin\bigl(m\theta_0\bigr) \\ \sin\bigl(m\theta_0\bigr) \\ \sin\bigl(m\theta_1\bigr) \\ \sin\bigl(m\theta_1\bigr) \\ \vdots \\ \sin\bigl(m\theta_{\tfrac{d}{2}-1}\bigr) \\ \sin\bigl(m\theta_{\tfrac{d}{2}-1}\bigr) \end{pmatrix}. f(q,m)= q0q1q2q3⋮qd−2qd−1 ⊗ cos(mθ0)cos(mθ0)cos(mθ1)cos(mθ1)⋮cos(mθ2d−1)cos(mθ2d−1) + −q1q0−q3q2⋮−qd−1qd−2 ⊗ sin(mθ0)sin(mθ0)sin(mθ1)sin(mθ1)⋮sin(mθ2d−1)sin(mθ2d−1) .
小结
总结下来,求解 f(q,m) 的过程可以概括为:
-
目标:让带位置索引的 q̃ₘ 和 k̃ₙ 做内积时只与相对位置 (n−m) 相关。
-
二维简化:先考虑二维向量,将其映射为复数 z q z_q zq。
-
设计思路:在复数上乘以相位因子 eⁱᵐᶿ,使得相乘结果只依赖于 (m−n)。
-
得到:
z q , m = z q ⋅ e i m θ ⟺ ( 实数形式 ) ( cos ( m θ ) − sin ( m θ ) sin ( m θ ) cos ( m θ ) ) ( q x q y ) . z_{q,m} = z_q·eⁱᵐᶿ ⟺ (实数形式) \begin{pmatrix} \cos(m\theta) & -\sin(m\theta) \\ \sin(m\theta) & \cos(m\theta) \end{pmatrix} \begin{pmatrix} q_x \\ q_y \end{pmatrix}. zq,m=zq⋅eimθ⟺(实数形式)(cos(mθ)sin(mθ)−sin(mθ)cos(mθ))(qxqy).
-
高维推广:将高维向量按两两一组分块进行旋转,并使用不同的 θ 来捕捉多种频率。
通过这种"旋转"方式,我们构造出了 RoPE 的位置编码函数 f,实现了将"绝对位置 (m,n)"转化为注意力内积中的相对位置 (n−m) 的效果。
一些补充知识
f(q,m) 和 f(k,n) 各表示什么?
-
q
~
m
=
f
(
q
,
m
)
\tilde{q}_m = f(q,m)
q~m=f(q,m):可以理解为"对原向量
q
q
q 做了一个跟位置
m
m
m 相关的变换"。
- 因为位置 m m m 是一个整数或索引,所以 f f f 其实是"(向量)×(位置索引)→(新向量)"的映射。
- 例如 RoPE 中就是通过"旋转矩阵"对向量进行旋转,旋转角度取决于 m m m。
- 同理, k ~ n = f ( k , n ) \tilde{k}_n = f(k,n) k~n=f(k,n) 表示对原向量 k k k 做了与位置 n n n 相关的变换。
这样做的目的:
- 每个位置(绝对位置)都有自己的"旋转"或"变换"方式,这就叫做"绝对位置编码"。
- 但是当我们把 q ~ m \tilde{q}_m q~m 和 k ~ n \tilde{k}_n k~n 做内积时,希望这个内积只和 n−m 有关,也就是能体现出相对位置。
q T k q^Tk qTk 和原论文中的 Q K T QK^T QKT 有什么区别
只是标量点积与矩阵乘法的两种视角:
在谈到“注意力公式”时,最核心的一步是 向量与向量之间的点积(内积),其结果应该是一个标量,用于衡量两者的相似度。在数学计法中,如果 q q q 和 k k k 都是列向量(形状为 (d, 1)), 那么它们的点积就是
q T k ∈ R q^T k \in \mathbb{R} qTk∈R
这种写法更偏向数学定义,把每个 token 的 Query/Key 看成单独向量去做内积。
在实际的 Transformer 实现中,我们常常一次处理整条序列。
- 设序列长度为 n,词向量维度为 d。
- 将所有 Query 向量拼成一个矩阵
Q
\mathbf{Q}
Q,形状通常是 (n,d)。
- 其中第 i 行 Q_i 就是 token i 的 Query(通常是行向量)。
- 同理,将所有 Key 向量拼成一个矩阵 K \mathbf{K} K,形状也是 (n,d)。
此时做矩阵乘法:
Q K T ∈ R n × n QK^T \in \mathbb{R}^{n \times n} QKT∈Rn×n
- 结果是一个 n ∗ n n*n n∗n 的矩阵,每个元素 (i, j) 对应第 i 个 Query 和第 j 和 key 的内积:
[ Q K T ] i , j = Q i K j T = q i T k j . [QK^T]_{i,j} = Q_i K_j^T = q_i^T k_j. [QKT]i,j=QiKjT=qiTkj.
- 这正好构成了整条序列上所有 (i,j) 两两 token 间的相似度分数。
因此, Q K T QK^\mathsf{T} QKT 是把所有单个向量点积拼成一个矩阵的做法,二者本质一致。