Preliminary: What is RoPE
Introduction
旋转位置编码 (RoPE) 是一种新颖的、基于相对位置的编码方法,它被设计用于提高 Transformer 模型处理长序列的能力,同时保持计算效率。与传统的绝对位置编码 (如正弦/余弦位置编码) 或直接的相对位置编码 (如 T5 中使用的相对偏置) 不同,RoPE 将位置信息集成到自注意力机制的 Q 和 K 的表示中,使得 Q 和 K 的点积自然地编码了相对位置信息。
RoPE 的核心思想是,通过对查询和键向量应用特定的旋转操作,使得两个向量的点积结果只依赖于它们之间的相对距离,而不是它们的绝对位置。这使得模型能够更好地泛化到更长的序列,并且在处理位置信息时更加高效。
RoPE 的主要优点包括:
- 编码相对位置信息: 自然地将相对位置信息融入到注意力分数中。
- 长序列外推能力: 提高了模型在训练时未见过的更长序列上的性能。
- 与自注意力机制的兼容性: 无缝集成到 QKV 点积注意力中。
- 简单且高效: 实现相对简单,且不会显著增加计算复杂度。
Formular
RoPE 的主要思想是通过对查询 $q$ 和键 $k$ 应用一个旋转矩阵 $R_t$ (取决于其绝对位置 $t$) ,使得点积 $q_m^T k_n$ 能够通过某种方式转化为只依赖于相对位置 $m-n$ 的函数。
对于一个向量 $x \in \mathbb{R}^d$ 在位置 $m$ 处,RoPE 的变换函数 $f(x, m)$ 可以定义如下:
如果向量维度是偶数 $d$,我们可以将其分成 $d/2$ 对,每对执行一个二维旋转。 对于向量 $x = [x_0, x_1, \ldots, x_{d-1}]^T$,RoPE 对其每个维度对 $(x_{2i}, x_{2i+1})$ 应用旋转:
$$ f(x, m)_{2i} = x_{2i} \cos(m\theta_i) - x_{2i+1} \sin(m\theta_i) \\ f(x, m)_{2i+1} = x_{2i} \sin(m\theta_i) + x_{2i+1} \cos(m\theta_i) $$其中 $\theta_i$ 是预设的频率,通常定义为 $\theta_i = 10000^{-2i/d}$. $i=0, \dots, d/2 - 1$ 是维度对的索引。
用矩阵形式表示: 我们可以将这种旋转操作表示为一个稀疏的块对角矩阵 $R_m^d$,其形式为:
$$R_m^d = \begin{pmatrix} \cos(m\theta_0) & -\sin(m\theta_0) & 0 & 0 & \cdots \\ \sin(m\theta_0) & \cos(m\theta_0) & 0 & 0 & \cdots \\ 0 & 0 & \cos(m\theta_1) & -\sin(m\theta_1) & \cdots \\ 0 & 0 & \sin(m\theta_1) & \cos(m\theta_1) & \cdots \\ \vdots & \vdots & \vdots & \vdots & \ddots \end{pmatrix}$$那么,经过 RoPE 编码的查询和键可以表示为:
$$\mathbf{q}_m = R_m^d \mathbf{q}$$$$\mathbf{k}_n = R_n^d \mathbf{k}$$其中 $\mathbf{q}$ 和 $\mathbf{k}$ 是原始的查询和键向量 (不含位置信息) ,$\mathbf{q}_m$ 和 $\mathbf{k}_n$ 是经过 RoPE 处理后的查询和键向量。
RoPE 的关键特性:点积与相对位置 经过 RoPE 变换后,注意力机制中的点积可以分解为:
$$\mathbf{q}_m^T \mathbf{k}_n = (R_m^d \mathbf{q})^T (R_n^d \mathbf{k})$$由于 $R_m^d$ 是正交矩阵,其逆矩阵等于其转置,即 $(R_m^d)^T = (R_m^d)^{-1} = R_{-m}^d$. 因此有
$$\mathbf{q}_m^T \mathbf{k}_n = \mathbf{q}^T (R_m^d)^T R_n^d \mathbf{k} = \mathbf{q}^T R_{-m}^d R_n^d \mathbf{k} = \mathbf{q}^T R_{n-m}^d \mathbf{k}$$这个最终结果 $\mathbf{q}^T R_{n-m}^d \mathbf{k}$ 表明,两个向量的点积只依赖于它们的相对位置差 $n-m$,而与它们的绝对位置 $n$ 和 $m$ 无关。这就是 RoPE 能够编码相对位置信息的数学基础。
Workflow
Notation
- $d$: embedding 维度
- $d_h$: 每个注意力头的维度
- $\mathbf{h}_t\in\mathbb{R}^d$: 某个 attention 层第 t 个 token 的输入。
KV Compression
$$ \textcolor{red}{c_t^{KV}} = W^{DKV}h_t \tag{1} $$$$ [k_{t,1}^{C}, k_{t,2}^{C}, \ldots, k_{t,n_h}^{C}] = k_t^C = W^{UK}c_t^{KV} \tag{2} $$$$ \textcolor{red}{k_t^R} = \text{RoPE}(W^{KR}h_t) \tag{3} $$$$ k_{t,i} = [k_{t,i}^C, k_{t}^R] \tag{4} $$$$ [v_{t,1}^C, v_{t,2}^C, \ldots, v_{t,n_h}^C] = v_t^C = W^{UV}c_t^{KV} \tag{5} $$- $c_t^{KV} \in \mathbb{R}^{d_c}$: 压缩后的 KV 潜在向量。
- $d_c (\ll d_h n_h)$: KV 压缩到的维度。
- $W^{DKV} \in \mathbb{R}^{d_c \times d}$: KV 降维投影矩阵。
- $W^{UK}, W^{UV} \in \mathbb{R}^{d_h n_h \times d_c}$ 分别是 K & V 的升维投影矩阵。
- $W^{KR} \in \mathbb{R}^{d_h^R \times d}$: 用于生成携带 RoPE 的解耦键的矩阵 (Su et al., 2024)
红色的是需要缓存的向量,后续说明原因。注意到对 K 进行 RoPE 之前是对输入向量乘以了个投影再进行的。而且 K 的每个注意力头被拼接的都是同一个 $k_{t}^R$,有点类似于 MQA.
Q Compression
$$c_t^Q = W^{DQ}h_t \tag{6}$$$$[q_{t,1}^C, q_{t,2}^C, \ldots, q_{t,n_h}^C] = q_t^C = W^{UQ}c_t^Q \tag{7}$$$$[q_{t,1}^R, q_{t,2}^R, \ldots, q_{t,n_h}^R] = q_t^R = \text{RoPE}(W^{QR}q_t^C) \tag{8}$$$$q_{t,i} = [q_{t,i}^C, q_{t,i}^R] \tag{9}$$- $c_t^Q \in \mathbb{R}^{d_c'}$: Q 压缩后的潜在向量。
- $d_c'(\ll d_h n_h)$ 表示 Q 压缩后的维度。
- $W^{DQ} \in \mathbb{R}^{d_c' \times d}, W^{UQ} \in \mathbb{R}^{d_h n_h \times d_c'}$: 分别是 Q 的降维和升维矩阵。
- $W^{QR} \in \mathbb{R}^{d_h^R n_h \times d_c'}$ 是用于生成携带 RoPE 的解耦 Q 的矩阵。
注意到对 Q 的 RoPE 是在压缩后进行的,即为每个注意力头都生成了一个位置编码信息后进行拼接。
Attention Computation
最终 $q_{t,i}$, $k_{j,i}$, $v_{j,i}^C$ 被组合起来以生成最终的注意力输出 $u_t$
$$\mathbf{o}_{t,i} = \sum_{j=1}^{t} \text{Softmax}\left(\frac{q_{t,i}^T \mathbf{k}_{j,i}}{\sqrt{d_h + d_R}}\right)v_{j,i}^C \tag{10}$$$$\mathbf{u}_t = W^O[\mathbf{o}_{t,1}, \mathbf{o}_{t,2}, \ldots, \mathbf{o}_{t,n_h}] \tag{11}$$- $W^O \in \mathbb{R}^{d \times d_h n_h}$: 输出投影矩阵。
Why Decoupled RoPE
假设不加 RoPE 的情况下进行 $q_{t,i}$, $k_{j,i}$ 的内积则有
$$ q_{t,i}^{T}\times k_{j,i}=(W_{(i)}^{UQ}c_{t}^{Q})^{T}\times W_{(i)}^{UK}c_{j}^{KV}=(c_{t}^{Q})^{T}\times(W_{(i)}^{UQ})^{T}W_{(i)}^{UK}\times c_{j}^{KV} \tag{12} $$RoPE 通过对向量应用一个位置依赖的旋转变换来注入相对位置信息。对于一个向量 $X$ 在位置 $t$,RoPE 可以被表示为一个旋转矩阵 $R_t$ 乘以 $X$:
$$\text{RoPE}(X, t) = R_t X$$这里的 $R_t$ 是一个正交旋转矩阵,它取决于位置 $t$.
如果直接对压缩后 $k_t^C$ 的 使用 RoPE 那么情况会变成
$$ \begin{aligned} q_{t,i}^{T}\times k_{j,i}&=(\mathcal{R}_{t}W_{(i)}^{UQ}c_{t}^{Q})^{T}\times\mathcal{R}_{j}W_{(i)}^{UK}c_{j}^{KV} \\ &=(c_{t}^{Q})^{T}\times(W_{(i)}^{UQ})^{T}\mathcal{R}_{t}^{T}\mathcal{R}_{j}W_{(i)}^{UK}\times c_{j}^{KV}\\ &=(c_{t}^{Q})^{T}\times(W_{(i)}^{UQ})^{T}\mathcal{R}_{t-j}W_{(i)}^{UK}\times c_{j}^{KV} \end{aligned} \tag{13} $$中间的矩阵与相对位置有关,无法提前计算出来。因此文中就是对所有头都使用同一个 k 和计算 RoPE. 拼接后的向量再计算时
$$ q_{t,i}^T\times k_{j,i}=[q_{t,i}^C;q_{t,i}^R]^T\times[k_{j,i}^C;k_t^R]=(q_{t,i}^C,k_{j,i}^C)+(q_{t,i}^R,k_t^R) \tag{14} $$前一部分按照公式 (12) 进行计算,后一部分按照 MQA 方式计算。因此只用缓存 $c_t^{KV}$ 和 $k_t^R$.
Source Code
DeepSeek-V3 MLA 对应的源码位置
|
|