ROPE 阅读苏神博客有感

120 阅读2分钟

最近再次推到了ROPE,又产生了很多疑惑,故而做如下笔记记录。苏神科学空间,原文:spaces.ac.cn/archives/82…

一、背景知识

1. 二维向量复数表示

二维向量的复数表示是什么意思?

二维向量的复数表示是指将二维向量 (a,b)(a, b) 映射为复数 a+bia + bi,其中:

  • aa 是向量的实部(横坐标),对应实轴方向的分量。
  • bb 是向量的虚部(纵坐标),对应虚轴方向的分量。
  • ii 是虚数单位,满足 i2=1i^2 = -1

这种表示的本质是将二维向量与复平面中的点或向量一一对应。复数的几何意义在于:

  • (长度):复数的模 r=a2+b2r = \sqrt{a^2 + b^2} 对应向量的长度。
  • 辐角(相位角):复数的辐角 θ=arctan(b/a)\theta = \arctan(b/a) 对应向量与实轴正方向的夹角。

为什么要用复数表示二维向量?

复数表示二维向量的核心优势在于 简化几何变换的运算,尤其是在旋转、缩放等操作中。

复数乘法在几何上可以分解为:

  • 模的乘积:两个复数相乘,其模等于各自模的乘积。
  • 辐角的相加:两个复数相乘,其辐角等于各自辐角的和。

例如,将复数 z1=a+biz_1 = a + bi 乘以 z2=cosθ+isinθz_2 = \cos\theta + i\sin\theta(即单位复数表示旋转),结果为:

z1z2=(acosθbsinθ)+i(asinθ+bcosθ),z_1 \cdot z_2 = (a\cos\theta - b\sin\theta) + i(a\sin\theta + b\cos\theta),

这相当于将向量 (a,b)(a, b) 逆时针旋转 θ\theta 角度后的向量。

对比传统方法

  • 若用矩阵表示旋转,需要计算旋转矩阵:
    [cosθsinθsinθcosθ][ab].\begin{bmatrix} \cos\theta & -\sin\theta \\ \sin\theta & \cos\theta \end{bmatrix} \cdot \begin{bmatrix} a \\ b \end{bmatrix}.
  • 复数乘法直接通过代数运算完成旋转,无需显式构造矩阵。

复数表示的本质是 将代数与几何统一,通过复数的代数性质(如乘法、极坐标形式)高效地描述二维向量的几何变换。这种表示方式在数学理论和工程实践中均具有重要价值。

2. 矩阵

正交矩阵
  • 定义:一个 n×nn \times n 的实数方阵 QQ 满足 QTQ=IQ^T Q = I,即其列向量(或行向量)两两正交且为单位向量。
  • 行列式det(Q)=±1\det(Q) = \pm 1
    • det(Q)=1\det(Q) = 1,称为旋转矩阵(纯旋转)。
    • det(Q)=1\det(Q) = -1,称为反射矩阵(包含反射操作)。
  • 逆矩阵:正交矩阵的逆矩阵为其转置,即 Q1=QTQ^{-1} = Q^T
  • 几何意义:保持向量长度和角度不变,但可能改变方向(反射时反转方向)。
  • 封闭性:正交矩阵的乘积、逆矩阵仍是正交矩阵。
旋转矩阵
  • 定义:行列式为1的正交矩阵,即 RTR=IR^T R = Idet(R)=1\det(R) = 1
  • 几何意义:仅表示纯旋转操作,不改变空间方向(如右手定则)。
  • 迹与旋转角的关系:在三维空间中,旋转矩阵的迹为 1+2cosθ1 + 2\cos\theta,其中 θ\theta 是旋转角。
  • 封闭性:旋转矩阵的乘积仍为旋转矩阵。
  • 旋转矩阵的乘积:两个旋转矩阵相乘的结果仍为旋转矩阵,其对应的旋转角度是两者的。例如,R(α)R(β)=R(α+β)R(\alpha) \cdot R(\beta) = R(\alpha + \beta)
验证示例(二维空间)
  • 旋转矩阵公式
    R(θ)=[cosθsinθsinθcosθ]R(\theta) = \begin{bmatrix} \cos\theta & -\sin\theta \\ \sin\theta & \cos\theta \end{bmatrix}
  • 计算 R(m)R(n)R(-m) \cdot R(n)
    R(m)=[cosmsinmsinmcosm],R(n)=[cosnsinnsinncosn]R(-m) = \begin{bmatrix} \cos m & \sin m \\ -\sin m & \cos m \end{bmatrix}, \quad R(n) = \begin{bmatrix} \cos n & -\sin n \\ \sin n & \cos n \end{bmatrix}
    乘积结果为:
    R(m)R(n)=[cos(nm)sin(nm)sin(nm)cos(nm)]=R(nm)R(-m) \cdot R(n) = \begin{bmatrix} \cos(n - m) & -\sin(n - m) \\ \sin(n - m) & \cos(n - m) \end{bmatrix} = R(n - m)

二、 ROPE解释

1. Transformer 的局限性

Transformer 架构的核心是自注意力机制,其计算方式 Attention(Q,K,V)=softmax(QKT/sqrt(dk))VAttention(Q, K, V) = softmax(QK^T / sqrt(d_k)) V。这种计算方式的本质是计算 Query 和 Key 之间的点积相似度。

然而,点积操作本身不包含任何位置信息。这意味着,如果我们将输入序列的词序打乱,Transformer 在理论上会得到相同的注意力分数(因为 QKTQK^T 是对所有 Q 和 K 的点积,与它们的原始顺序无关)。这就是 Transformer 的置换不变性

为了引入位置信息,传统的做法有:

  • 绝对位置编码 (Absolute PE):将位置编码pi p_i 直接加到词向量 xix_i 上,即 qi=xi+piq_i = x_i + p_ikj=xj+pjk_j = x_j + p_j

    • 此时 qiTkj=(xi+pi)T(xj+pj)=xiTxj+xiTpj+piTxj+piTpjq_i^T k_j = (x_i + p_i)^T (x_j + p_j) = x_i^T x_j + x_i^T p_j + p_i^T x_j + p_i^T p_j
    • 这种方法的问题在于,点积结果包含了词向量自身的相似度、词向量与位置编码的交互、以及位置编码自身的相似度。相对位置信息 (ij)(i-j) 无法被简洁地表示,并且在外推(训练时没见过的长序列)时表现不佳。
  • 相对位置编码 (Relative PE):尝试直接在 QKTQK^T 中引入相对位置信息。例如 Shaw et al. (Transformer-XL) 的方法在计算注意力分数时额外考虑相对位置。

RoPE 的目标是设计一种简洁、高效的位置编码方法,使得点积操作天然地包含相对位置信息,并且能够很好地外推

2. 核心思想:通过旋转引入相对位置

RoPE 的核心思想是:能否找到一种函数 f(x,m)f(x, m),它能将位置 mm 的信息编码到向量 xx 中,使得任意两个向量 qqkk 在经过位置编码后,它们的点积只依赖于它们的相对位置 mnm-n

即,我们希望 f(q,m)Tf(k,n)=g(q,k,mn)f(q, m)^T f(k, n) = g(q, k, m-n)

考虑二维向量 v=(x,y)v = (x, y),我们可以将其看作复数 z=x+iyz = x + iy

复数乘法 ze(iθ)z * e^{(iθ)} 对应于在复平面上将 zz 旋转 θθ 角。

e(iθ)=cos(θ)+isin(θ)e^{(iθ)} = cos(θ) + i sin(θ)

那么 (x+iy)(cos(θ)+isin(θ))=(xcos(θ)ysin(θ))+i(xsin(θ)+ycos(θ))(x + iy)(cos(θ) + i sin(θ)) = (x cos(θ) - y sin(θ)) + i(x sin(θ) + y cos(θ))

这在实数域中,对应于对向量 (x,y)(x, y) 应用一个旋转矩阵:

R(θ)=[cosθsinθsinθcosθ]R(\theta) = \begin{bmatrix} \cos\theta & -\sin\theta \\ \sin\theta & \cos\theta \end{bmatrix}

所以,R(θ)[x,y]R(θ) * [x, y] 就是将向量 (x,y)(x, y) 旋转 θθ 角。

现在,我们将这个旋转操作应用到我们的 f(x,m)f(x, m) 函数中:

f(q,m)=R(mθ)qf(q, m) = R(mθ) qf(k,n)=R(nθ)kf(k, n) = R(nθ) k,其中 θθ 是一个与位置相关的角度参数。

那么,它们的点积为:

f(q,m)Tf(k,n)=(R(mθ)q)T(R(nθ)k)=qTR(mθ)TR(nθ)kf(q, m)^T f(k, n) = (R(mθ) q)^T (R(nθ) k)= q^T R(mθ)^T R(nθ) k

由于 R(θ)R(θ) 是正交矩阵,所以 R(θ)T=R(θ)R(θ)^T = R(-θ)

qTR(mθ)TR(nθ)k=qTR(mθ)R(nθ)kq^T R(mθ)^T R(nθ) k= q^T R(-mθ) R(nθ) k

由于 R(θ)R(θ) 是旋转矩阵,有 R(A)R(B)=R(A+B)R(A) R(B) = R(A+B) (两次旋转等价于一次旋转角度之和),

qTR(mθ)R(nθ)k=qTR(nθmθ)k=qTR((nm)θ)kq^T R(-mθ) R(nθ) k= q^T R(nθ - mθ) k= q^T R((n-m)θ) k

我们得到了一个非常漂亮的结果:f(q,m)Tf(k,n)f(q, m)^T f(k, n) 只依赖于相对位置 (nm)(n-m)!这正是我们想要的 g(q,k,nm)g(q, k, n-m) 形式。

3. 从二维推广到高维

要将二维旋转矩阵进行推广,最直接的思路是,把维度两两分组。假设词向量维度为 d(d 为 2 的倍数):

Mq=[cosmθ0sinmθ000sinmθ0cosmθ00000cosmθd/21sinmθd/2100sinmθd/21cosmθd/21][q0q1qd2qd1]M·q= \left [ \begin{matrix} \cos m\theta_0 & -\sin m\theta_0 & \cdots & 0 & 0 \\ \sin m\theta_0 & \cos m\theta_0 & \cdots & 0 & 0 \\ \vdots & \vdots & \ddots & \vdots & \vdots \\ 0 & 0 & \cdots & \cos m\theta_{d/2-1} & -\sin m\theta_{d/2-1} \\ 0 & 0 & \cdots & \sin m\theta_{d/2-1} & \cos m\theta_{d/2-1} \\ \end{matrix} \right ] \left [ \begin{matrix} q_0\\ q_1\\\vdots\\q_{d-2}\\q_{d-1} \end{matrix} \right]

如此,d 个维度被分为了 d/2 组,θ 也有了分别 d/2个取值。

在代码实现上可以用以下思路来等效计算 M⋅q,节省资源:

Mq=[q0q1q2q3qd2qd1][cosmθ0cosmθ0cosmθ1cosmθ1cosmθd/21cosmθd/21]+[q1q0q3q2qd1qd2][sinmθ0sinmθ0sinmθ1sinmθ1sinmθd/21sinmθd/21]M·q= \left [ \begin{matrix} q_0\\ q_1\\q_2\\q_3\\\vdots\\q_{d-2}\\q_{d-1} \end{matrix} \right] \odot \left [ \begin{matrix} \cos m\theta_0\\ \cos m\theta_0\\ \cos m\theta_1\\ \cos m\theta_1\\ \vdots\\ \cos m\theta_{d/2 - 1}\\ \cos m\theta_{d/2 - 1}\\ \end{matrix} \right] + \left [ \begin{matrix} -q_1\\ q_0\\-q_3\\q_2\\\vdots\\-q_{d-1}\\q_{d-2} \end{matrix} \right] \odot \left [ \begin{matrix} \sin m\theta_0\\ \sin m\theta_0\\ \sin m\theta_1\\ \sin m\theta_1\\ \vdots\\ \sin m\theta_{d/2 - 1}\\ \sin m\theta_{d/2 - 1}\\ \end{matrix} \right]

这样,RoPE 巧妙地将位置信息编码到了 Query 和 Key 向量中,使得它们在计算点积时,天然地反映了相对位置。

4. θ 函数

θkθ_k 是 RoPE 中非常关键的参数,它决定了每个维度对的旋转频率。

(1) θkθ_k 的公式

RoPE 中 θkθ_k 的计算方式与原始 Transformer 的正弦/余弦位置编码中的频率设置非常相似:

θk=1(base(2k/d))=base(2k/d)θ_k = \frac{1}{(base^{(2k/d)})} =base^{-(2k/d)}

其中:

  • kk:维度对的索引,从 00d/21d/2 - 1
  • dd:向量的维度 (hidden size)。
  • basebase:一个超参数,通常取 1000010000 (与原始 Transformer PE 相同),LLaMA 1 用的是 1000010000,LLaMA 2 则将其扩展到了 500000500000, Qwen3更是扩展到 1,000,000
(2) 为什么选择10000作为基数?
  • 历史借鉴:RoPE的θ设计借鉴了Transformer的Sinusoidal位置编码,后者同样使用10000作为基数。这种设计保证了不同维度的频率范围合理,且具有一定的外推性(能够处理超出训练长度的序列)。
  • 频率分布:10000的指数衰减使得不同维度的频率覆盖从高频到低频的连续范围,从而能够捕捉不同尺度的相对位置关系。
(3) θ的作用示例

假设一个128维的向量,其θ的计算如下:

  • 第0维(i=0):θ0=1000020/128=1\theta_0 = 10000^{-2 \cdot 0 / 128} = 1
  • 第1维(i=2):θ2=1000022/128=100001/320.95\theta_2 = 10000^{-2 \cdot 2 / 128} = 10000^{-1/32} \approx 0.95
  • 第64维(i=128):θ64=10000264/128=100001=0.0001\theta_{64} = 10000^{-2 \cdot 64 / 128} = 10000^{-1} = 0.0001

结果:低维(如i=0)的θ较大,对应高频旋转;高维(如i=64)的θ较小,对应低频旋转。

(4) 远程衰减
import numpy as np
import matplotlib.pyplot as plt

# 定义参数
d = 128

# 定义Theta函数
def theta(t):
    return 10000 **(-2 * t / d)

# 定义f(m)函数
def f(m):
    total = 0.0
    # 外循环,j从0到d/2 - 1
    for j in range(int(d/2)):
        # 内循环,i从0到j
        inner_sum = 0.0j  # 使用复数类型
        for i in range(j + 1):
            inner_sum += np.exp(1j * m * theta(i))
        # 计算复数的模并累加到总和
        total += np.abs(inner_sum)
    # 除以d/2并返回结果
    return total / (d/2)

# 生成m的取值范围
m_values = np.linspace(0, 256, 1000)  # 使用1000个点以获得平滑曲线

# 计算每个m对应的f(m)值
f_values = [f(m) for m in m_values]

# 绘制图像
plt.figure(figsize=(10, 6))
plt.plot(m_values, f_values)
plt.xlabel('相对距离')  # 设置x轴标签
plt.ylabel('相对大小')  # 设置y轴标签
plt.title('f(m)的图像')
plt.grid(True)
plt.show()

image.png 从图中可以看到随着相对距离的变大,内积结果有衰减趋势的出现。因此,选择θi=100002i/dθ_i=10000^{−2i/d},确实能带来一定的远程衰减性。几乎任意的光滑单调函数都可以,带来远程衰减性。

苏神还试过以θi=100002i/dθ_i=10000^{−2i/d}为初始化,将θiθ_i视为可训练参数,然后训练一段时间后发现θiθ_i并没有显著更新,因此干脆就直接固定θi=100002i/dθ_i=10000^{−2i/d}了。