一.位置编码

1.1正余弦位置编码(Sinusoidal Positional Encoding)

对于注意力机制来说,句子 [A, B, C] 和 [C, B, A] 的计算结果是完全一样的,因为它只是在算词与词之间的相似度,完全没有“语序”的概念。为了让模型知道词的先后顺序,我们必须给每个词的向量额外注入一个位置信息。最直接的想法是:
方法一:用整数。第 0 个词加上 0,第 1 个词加上 1。问题:随着句子变长,数值会无限变大,导致梯度不稳定。
方法二:归一化到 [0, 1]。第 0 个词是 0,最后一个词是 1。问题:不同长度的句子中,相邻两个词的步长是不一样的,模型很难学习到统一的相对距离。
正余弦位置编码就是为了完美解决上述问题而诞生的。
给定一个词在句子中的位置 p o s pos pos(比如第 0 个词、第 1 个词),以及它的特征向量维度 d m o d e l d_{model} dmodel(对应 MiniMind 里的 hidden_size,比如 768)。Transformer 为这个位置生成一个与特征向量维度相同的向量 P E PE PE(Position Embedding),其计算公式如下: P E ( p o s , 2 i ) = sin ⁡ ( p o s 10000 2 i / d m o d e l ) PE_{(pos, 2i)} = \sin\left(\frac{pos}{10000^{2i/d_{model}}}\right) PE(pos,2i)=sin(100002i/dmodelpos) P E ( p o s , 2 i + 1 ) = cos ⁡ ( p o s 10000 2 i / d m o d e l ) PE_{(pos, 2i+1)} = \cos\left(\frac{pos}{10000^{2i/d_{model}}}\right) PE(pos,2i+1)=cos(100002i/dmodelpos) p o s pos pos:词在序列中的绝对位置( 0 , 1 , 2 , … 0, 1, 2, \dots 0,1,2,)。 i i i:向量空间的维度索引( 0 , 1 , 2 , … , d m o d e l / 2 − 1 0, 1, 2, \dots, d_{model}/2 - 1 0,1,2,,dmodel/21)。偶数维度( 0 , 2 , 4 … 0, 2, 4\dots 0,2,4)使用 sin ⁡ \sin sin 函数。奇数维度( 1 , 3 , 5 … 1, 3, 5\dots 1,3,5)使用 cos ⁡ \cos cos 函数。将计算出的 P E PE PE 向量直接与原始的词嵌入向量相加,就完成了位置信息的注入。
三角函数形式的位置编码具有一个极其优雅的数学性质:相对位置可以表示为绝对位置的线性变换。假设我们有两个位置 p o s pos pos p o s + k pos + k pos+k(其中 k k k 是相对偏移量)。我们考察维度对 ( 2 i , 2 i + 1 ) (2i, 2i+1) (2i,2i+1)。对于位置 p o s + k pos + k pos+k,其位置编码为: P E ( p o s + k , 2 i ) = sin ⁡ ( ω i ⋅ ( p o s + k ) ) = sin ⁡ ( ω i p o s ) cos ⁡ ( ω i k ) + cos ⁡ ( ω i p o s ) sin ⁡ ( ω i k ) PE_{(pos+k, 2i)} = \sin(\omega_i \cdot (pos + k)) = \sin(\omega_i pos)\cos(\omega_i k) + \cos(\omega_i pos)\sin(\omega_i k) PE(pos+k,2i)=sin(ωi(pos+k))=sin(ωipos)cos(ωik)+cos(ωipos)sin(ωik) P E ( p o s + k , 2 i + 1 ) = cos ⁡ ( ω i ⋅ ( p o s + k ) ) = cos ⁡ ( ω i p o s ) cos ⁡ ( ω i k ) − sin ⁡ ( ω i p o s ) sin ⁡ ( ω i k ) PE_{(pos+k, 2i+1)} = \cos(\omega_i \cdot (pos + k)) = \cos(\omega_i pos)\cos(\omega_i k) - \sin(\omega_i pos)\sin(\omega_i k) PE(pos+k,2i+1)=cos(ωi(pos+k))=cos(ωipos)cos(ωik)sin(ωipos)sin(ωik)如果我们将其写成矩阵乘法的形式: [ P E ( p o s + k , 2 i ) P E ( p o s + k , 2 i + 1 ) ] = [ cos ⁡ ( ω i k ) sin ⁡ ( ω i k ) − sin ⁡ ( ω i k ) cos ⁡ ( ω i k ) ] [ P E ( p o s , 2 i ) P E ( p o s , 2 i + 1 ) ] \begin{bmatrix} PE_{(pos+k,2i)} \\ PE_{(pos+k,2i+1)} \end{bmatrix} = \begin{bmatrix} \cos(\omega_i k) & \sin(\omega_i k) \\ -\sin(\omega_i k) & \cos(\omega_i k) \end{bmatrix} \begin{bmatrix} PE_{(pos,2i)} \\ PE_{(pos,2i+1)} \end{bmatrix} [PE(pos+k,2i)PE(pos+k,2i+1)]=[cos(ωik)sin(ωik)sin(ωik)cos(ωik)][PE(pos,2i)PE(pos,2i+1)]核心结论: 中间那个 2 × 2 2 \times 2 2×2 的变换矩阵 M k \mathbf{M}_k Mk 仅仅依赖于相对偏移量 k k k,而与绝对位置 p o s pos pos 完全无关。从线性代数和几何的角度来看, M k \mathbf{M}_k Mk 是一个旋转矩阵(Rotation Matrix)。这意味着,在位置编码的高维空间中,“向前移动 k k k 个步长”这个操作,等价于在各个二维子空间中进行了一次角度为 ω i k \omega_i k ωik 的严格旋转。这使得自注意力机制在计算点积时,能够很容易地捕捉到词与词之间的相对距离信息。
最后,我们来看看引入 P E \mathbf{PE} PE 后,自注意力矩阵相乘时到底发生了什么。在自注意力中,我们需要计算 Query 和 Key 的点积。 Q = ( X e m b + P E ) W Q \mathbf{Q} = (\mathbf{X}_{emb} + \mathbf{PE})\mathbf{W}^Q Q=(Xemb+PE)WQ K = ( X e m b + P E ) W K \mathbf{K} = (\mathbf{X}_{emb} + \mathbf{PE})\mathbf{W}^K K=(Xemb+PE)WK注意力得分矩阵 S \mathbf{S} S (忽略缩放因子 d k \sqrt{d_k} dk )计算如下: S = Q K T = ( X e m b + P E ) W Q ⋅ ( ( X e m b + P E ) W K ) T \mathbf{S} = \mathbf{Q} \mathbf{K}^T = (\mathbf{X}_{emb} + \mathbf{PE})\mathbf{W}^Q \cdot \left((\mathbf{X}_{emb} + \mathbf{PE})\mathbf{W}^K\right)^T S=QKT=(Xemb+PE)WQ((Xemb+PE)WK)T S = ( X e m b + P E ) W Q ( W K ) T ( X e m b + P E ) T \mathbf{S} = (\mathbf{X}_{emb} + \mathbf{PE})\mathbf{W}^Q (\mathbf{W}^K)^T (\mathbf{X}_{emb} + \mathbf{PE})^T S=(Xemb+PE)WQ(WK)T(Xemb+PE)T将括号完全展开,我们会得到四个项: S = X e m b W Q ( W K ) T X e m b T ⏟ ( 1 ) + X e m b W Q ( W K ) T P E T ⏟ ( 2 ) + P E W Q ( W K ) T X e m b T ⏟ ( 3 ) + P E W Q ( W K ) T P E T ⏟ ( 4 ) \mathbf{S} = \underbrace{\mathbf{X}_{emb}\mathbf{W}^Q (\mathbf{W}^K)^T \mathbf{X}_{emb}^T}_{(1)} + \underbrace{\mathbf{X}_{emb}\mathbf{W}^Q (\mathbf{W}^K)^T \mathbf{PE}^T}_{(2)} + \underbrace{\mathbf{PE}\mathbf{W}^Q (\mathbf{W}^K)^T \mathbf{X}_{emb}^T}_{(3)} + \underbrace{\mathbf{PE}\mathbf{W}^Q (\mathbf{W}^K)^T \mathbf{PE}^T}_{(4)} S=(1) XembWQ(WK)TXembT+(2) XembWQ(WK)TPET+(3) PEWQ(WK)TXembT+(4) PEWQ(WK)TPET
在这里插入图片描述

低索引高频维度(细粒度局部表征):负责记录极其局部的微观位置。它让模型能够极其敏锐地察觉到“这个词和它紧挨着的下一个词”的区别(因为相邻哪怕 1 个位置,高频维度的数值都会发生剧烈翻转)。
高索引低频维度(长程全局坐标):负责记录跨越长距离的宏观位置。它让模型能够感知到“这个词是在文章的开头,还是在文章的结尾”(因为距离几百个词,低频维度的数值才会发生明显变化)。

1.2 RoPE (Rotary Position Embedding,旋转位置编码)

传统的绝对位置编码(如原版 Transformer):就像是给每个词贴标签。第 1 个词的向量加上标签 1,第 2 个词加上标签 2。模型在做点积(算注意力)时,要从混合了词义和标签的杂乱数据中(就是上一回合我们拆解的那 4 个展开项),辛苦地剥离出相对距离。
RoPE 的核心思想:不再使用加法,而是使用旋转(乘法)。你可以把词向量(比如 Query 和 Key)想象成钟表上的指针。当词出现在第 1 个位置时,把它的特征向量(指针)顺时针旋转 10 ∘ 10^\circ 10。当词出现在第 2 个位置时,把它的特征向量旋转 20 ∘ 20^\circ 20。出现在第 m m m 个位置,就旋转 m × 10 ∘ m \times 10^\circ m×10
假设我们有一个二维的词向量 q = ( q 0 , q 1 ) \mathbf{q} = (q_0, q_1) q=(q0,q1),它在句子中的绝对位置是 m m m
我们要把它旋转一个角度 θ \theta θ(通常 θ = m ⋅ ω \theta = m \cdot \omega θ=mω ω \omega ω 是基础频率)。旋转后的向量 q ~ \tilde{\mathbf{q}} q~ 可以通过乘以一个旋转矩阵 R m \mathbf{R}_m Rm 来实现: q ~ = R m q = ( cos ⁡ ( m ω ) − sin ⁡ ( m ω ) sin ⁡ ( m ω ) cos ⁡ ( m ω ) ) ( q 0 q 1 ) = ( q 0 cos ⁡ ( m ω ) − q 1 sin ⁡ ( m ω ) q 0 sin ⁡ ( m ω ) + q 1 cos ⁡ ( m ω ) ) \tilde{\mathbf{q}} = \mathbf{R}_m \mathbf{q} = \begin{pmatrix} \cos(m\omega) & -\sin(m\omega) \\ \sin(m\omega) & \cos(m\omega) \end{pmatrix} \begin{pmatrix} q_0 \\ q_1 \end{pmatrix} = \begin{pmatrix} q_0 \cos(m\omega) - q_1 \sin(m\omega) \\ q_0 \sin(m\omega) + q_1 \cos(m\omega) \end{pmatrix} q~=Rmq=(cos()sin()sin()cos())(q0q1)=(q0cos()q1sin()q0sin()+q1cos())在实际的大模型中,特征维度 d m o d e l d_{model} dmodel 不是二维的,而是很长(比如 head_dim = 96)。高维空间怎么旋转呢?RoPE 的做法极其简单粗暴且有效:两两分组,互不干涉。把 96 维的向量,每 2 个维度看作一个二维平面(一共分成 48 组二维平面)。然后在每一个二维平面里,分别套用上面那个 2 × 2 2 \times 2 2×2 的旋转矩阵。并且,每一组使用的转速(频率 ω i \omega_i ωi)是不一样的:靠前的维度分组(低维),使用大频率(转得快,负责微观局部位置)。靠后的维度分组(高维),使用小频率(转得慢,负责宏观全局位置)。这与原版 Transformer 的频率衰减设计一脉相承。
最终,作用于整个高维向量的旋转矩阵 R Θ , m d \mathbf{R}_{\Theta, m}^{d} RΘ,md 是一个庞大的分块对角矩阵: R Θ , m d = ( cos ⁡ ( m ω 0 ) − sin ⁡ ( m ω 0 ) 0 0 ⋯ 0 0 sin ⁡ ( m ω 0 ) cos ⁡ ( m ω 0 ) 0 0 ⋯ 0 0 0 0 cos ⁡ ( m ω 1 ) − sin ⁡ ( m ω 1 ) ⋯ 0 0 0 0 sin ⁡ ( m ω 1 ) cos ⁡ ( m ω 1 ) ⋯ 0 0 ⋮ ⋮ ⋮ ⋮ ⋱ ⋮ ⋮ 0 0 0 0 ⋯ cos ⁡ ( m ω d / 2 − 1 ) − sin ⁡ ( m ω d / 2 − 1 ) 0 0 0 0 ⋯ sin ⁡ ( m ω d / 2 − 1 ) cos ⁡ ( m ω d / 2 − 1 ) ) \mathbf{R}_{\Theta, m}^{d} = \begin{pmatrix} \cos(m\omega_0) & -\sin(m\omega_0) & 0 & 0 & \cdots & 0 & 0 \\ \sin(m\omega_0) & \cos(m\omega_0) & 0 & 0 & \cdots & 0 & 0 \\ 0 & 0 & \cos(m\omega_1) & -\sin(m\omega_1) & \cdots & 0 & 0 \\ 0 & 0 & \sin(m\omega_1) & \cos(m\omega_1) & \cdots & 0 & 0 \\ \vdots & \vdots & \vdots & \vdots & \ddots & \vdots & \vdots \\ 0 & 0 & 0 & 0 & \cdots & \cos(m\omega_{d/2-1}) & -\sin(m\omega_{d/2-1}) \\ 0 & 0 & 0 & 0 & \cdots & \sin(m\omega_{d/2-1}) & \cos(m\omega_{d/2-1}) \end{pmatrix} RΘ,md= cos(mω0)sin(mω0)0000sin(mω0)cos(mω0)000000cos(mω1)sin(mω1)0000sin(mω1)cos(mω1)000000cos(mωd/21)sin(mωd/21)0000sin(mωd/21)cos(mωd/21)
在这里插入图片描述

1.2.1 RoPE特性证明

当带有绝对位置 m m m 的 Query 向量 q m \mathbf{q}_m qm 和带有绝对位置 n n n 的 Key 向量 k n \mathbf{k}_n kn 相遇,并在自注意力机制中进行点积(内积)时,魔法发生了。
首先,假设我们有一个 2D 查询向量 q = [ q 1 , q 2 ] T \mathbf{q} = [q_1, q_2]^T q=[q1,q2]T 和一个 2D 键向量 k = [ k 1 , k 2 ] T \mathbf{k} = [k_1, k_2]^T k=[k1,k2]T。我们通过给它们乘以一个旋转矩阵来注入绝对位置信息。对于位置 m m m(旋转角度为 m θ m\theta mθ),旋转矩阵定义为: R m = ( cos ⁡ ( m θ ) − sin ⁡ ( m θ ) sin ⁡ ( m θ ) cos ⁡ ( m θ ) ) \mathbf{R}_m = \begin{pmatrix} \cos(m\theta) & -\sin(m\theta) \\ \sin(m\theta) & \cos(m\theta) \end{pmatrix} Rm=(cos(mθ)sin(mθ)sin(mθ)cos(mθ))同理,位置 n n n 的旋转矩阵为 R n \mathbf{R}_n Rn
在 Attention 机制中,我们需要计算加上位置信息后的 q \mathbf{q} q k \mathbf{k} k 的内积: ⟨ q m , k n ⟩ = ( R m q ) T ( R n k ) \langle \mathbf{q}_m, \mathbf{k}_n \rangle = (\mathbf{R}_m \mathbf{q})^T (\mathbf{R}_n \mathbf{k}) qm,kn=(Rmq)T(Rnk)利用矩阵转置的性质 ( A B ) T = B T A T (AB)^T = B^T A^T (AB)T=BTAT,我们可以把上式展开: = q T R m T R n k = \mathbf{q}^T \mathbf{R}_m^T \mathbf{R}_n \mathbf{k} =qTRmTRnk首先,写出 R m \mathbf{R}_m Rm 的转置(沿主对角线翻转): R m T = ( cos ⁡ ( m θ ) sin ⁡ ( m θ ) − sin ⁡ ( m θ ) cos ⁡ ( m θ ) ) \mathbf{R}_m^T = \begin{pmatrix} \cos(m\theta) & \sin(m\theta) \\ -\sin(m\theta) & \cos(m\theta) \end{pmatrix} RmT=(cos(mθ)sin(mθ)sin(mθ)cos(mθ))然后,我们写出反向旋转 − m θ -m\theta mθ 角度的矩阵 R − m \mathbf{R}_{-m} Rm,并利用三角函数的奇偶性( cos ⁡ ( − x ) = cos ⁡ ( x ) \cos(-x) = \cos(x) cos(x)=cos(x), sin ⁡ ( − x ) = − sin ⁡ ( x ) \sin(-x) = -\sin(x) sin(x)=sin(x))进行化简: R − m = ( cos ⁡ ( − m θ ) − sin ⁡ ( − m θ ) sin ⁡ ( − m θ ) cos ⁡ ( − m θ ) ) = ( cos ⁡ ( m θ ) sin ⁡ ( m θ ) − sin ⁡ ( m θ ) cos ⁡ ( m θ ) ) \mathbf{R}_{-m} = \begin{pmatrix} \cos(-m\theta) & -\sin(-m\theta) \\ \sin(-m\theta) & \cos(-m\theta) \end{pmatrix} = \begin{pmatrix} \cos(m\theta) & \sin(m\theta) \\ -\sin(m\theta) & \cos(m\theta) \end{pmatrix} Rm=(cos(mθ)sin(mθ)sin(mθ)cos(mθ))=(cos(mθ)sin(mθ)sin(mθ)cos(mθ))对比发现,两者完全一致!所以我们得到了一个优雅的中间结论: R m T = R − m \mathbf{R}_m^T = \mathbf{R}_{-m} RmT=Rm现在我们把上一步的结论代入核心部分,即计算 R − m R n \mathbf{R}_{-m} \mathbf{R}_n RmRn。为了不被繁杂的 m θ m\theta mθ n θ n\theta nθ 晃晕,我们做一个简单的换元,记 α = − m θ \alpha = -m\theta α=mθ β = n θ \beta = n\theta β=nθ。此时,矩阵乘法变成了两个标准旋转矩阵的相乘: R − m R n = ( cos ⁡ α − sin ⁡ α sin ⁡ α cos ⁡ α ) ( cos ⁡ β − sin ⁡ β sin ⁡ β cos ⁡ β ) \mathbf{R}_{-m} \mathbf{R}_n = \begin{pmatrix} \cos\alpha & -\sin\alpha \\ \sin\alpha & \cos\alpha \end{pmatrix} \begin{pmatrix} \cos\beta & -\sin\beta \\ \sin\beta & \cos\beta \end{pmatrix} RmRn=(cosαsinαsinαcosα)(cosβsinβsinβcosβ)按照矩阵乘法规则展开: = ( cos ⁡ α cos ⁡ β − sin ⁡ α sin ⁡ β − cos ⁡ α sin ⁡ β − sin ⁡ α cos ⁡ β sin ⁡ α cos ⁡ β + cos ⁡ α sin ⁡ β − sin ⁡ α sin ⁡ β + cos ⁡ α cos ⁡ β ) = \begin{pmatrix} \cos\alpha \cos\beta - \sin\alpha \sin\beta & -\cos\alpha \sin\beta - \sin\alpha \cos\beta \\ \sin\alpha \cos\beta + \cos\alpha \sin\beta & -\sin\alpha \sin\beta + \cos\alpha \cos\beta \end{pmatrix} =(cosαcosβsinαsinβsinαcosβ+cosαsinβcosαsinβsinαcosβsinαsinβ+cosαcosβ)这恰好是标准的三角函数两角和公式!直接合并: = ( cos ⁡ ( α + β ) − sin ⁡ ( α + β ) sin ⁡ ( α + β ) cos ⁡ ( α + β ) ) = \begin{pmatrix} \cos(\alpha + \beta) & -\sin(\alpha + \beta) \\ \sin(\alpha + \beta) & \cos(\alpha + \beta) \end{pmatrix} =(cos(α+β)sin(α+β)sin(α+β)cos(α+β))最后,把 α \alpha α β \beta β 替换回原来的变量: α + β = − m θ + n θ = ( n − m ) θ \alpha + \beta = -m\theta + n\theta = (n - m)\theta α+β=mθ+nθ=(nm)θ = ( cos ⁡ ( ( n − m ) θ ) − sin ⁡ ( ( n − m ) θ ) sin ⁡ ( ( n − m ) θ ) cos ⁡ ( ( n − m ) θ ) ) = \begin{pmatrix} \cos((n-m)\theta) & -\sin((n-m)\theta) \\ \sin((n-m)\theta) & \cos((n-m)\theta) \end{pmatrix} =(cos((nm)θ)sin((nm)θ)sin((nm)θ)cos((nm)θ))你会发现,这不就是位置为 n − m n-m nm 的旋转矩阵吗?所以我们得出: R m T R n = R n − m \mathbf{R}_m^T \mathbf{R}_n = \mathbf{R}_{n-m} RmTRn=Rnm将化简结果代入: ⟨ q m , k n ⟩ = q T ( R m T R n ) k = q T R n − m k \langle \mathbf{q}_m, \mathbf{k}_n \rangle = \mathbf{q}^T (\mathbf{R}_m^T \mathbf{R}_n) \mathbf{k} = \mathbf{q}^T \mathbf{R}_{n-m} \mathbf{k} qm,kn=qT(RmTRn)k=qTRnmk两个词在经过 RoPE 编码后的内积(注意力得分),严格等价于原始词向量在不带位置编码的情况下,先进行了一次相对距离为 ( n − m ) (n-m) (nm) 的相对旋转,再求内积!

1.2.2 RoPE优势

(1)数学极度纯粹:没有任何多余的“词义与位置”交叉噪音。它从数学的公理底层保证了注意力机制只受相对距离控制。
(2)零显存负担:我们之前看代码时提过,它不需要像其他相对位置编码那样,专门在内存里维护一个庞大的相对距离矩阵(形状为 seq_len * seq_len)。它是在 Q Q Q K K K 生成的一瞬间(1D 级别)就以极其轻量的方式原地完成了旋转,显存占用极小,计算速度极快。(3)原生支持长度外推:既然它是通过“旋转频率”来控制位置的,那么当我们想让模型处理比训练时更长的文本时,只需要像 YaRN 算法那样,稍微修改一下旋转频率(把转速拨慢一点),就能无缝支持 32K 甚至 1M 的超长文本,而不需要重新从头训练模型。


“只对特定距离上的特定语义,产生最高强度的共鸣。”

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐