系列目录-大模型学习篇
问题场景(Problems)
旋转位置编码是是一种配合Attention机制能达到“绝对位置编码的方式实现相对位置编码”的设计,也正因为这种设计,它还是目前唯一一种可用于线性Attention的相对位置编码。
——苏剑林《Transformer升级之路:2、博采众长的旋转式位置编码》
解决方案(Solution)
在RoPE中,我们的出发点就是“通过绝对位置编码的方式实现相对位置编码”,这样做既有理论上的优雅之处,也有实践上的实用之处,比如它可以拓展到线性Attention中就是主要因为这一点。
为了达到这个目的,我们假设通过下述运算来给q,k添加绝对位置信息:
q
‾
m
=
f
(
q
,
m
)
,
k
‾
n
=
f
(
k
,
n
)
\overline{q}_{m}=f(q,m),\overline{k}_{n}=f(k,n)
qm=f(q,m),kn=f(k,n)
也就是说,我们分别为q,k设计操作
f
(
⋅
,
m
)
f(⋅,m)
f(⋅,m),
f
(
⋅
,
n
)
f(⋅,n)
f(⋅,n),使得经过操作后,
q
‾
m
\overline{q}_{m}
qm和
k
‾
n
\overline{k}_{n}
kn就带有了位置
m
m
m,
n
n
n的绝对位置信息。Attention的核心运算是内积,所以我们希望的内积的结果带有相对位置信息,因此假设存在恒等关系:
<
f
(
q
,
m
)
,
f
(
k
,
n
)
>
=
g
(
q
,
k
,
m
−
n
)
<f(q,m),f(k,n)>=g(q,k,m-n)
<f(q,m),f(k,n)>=g(q,k,m−n)
如果我们可以找出该恒等式的一个尽可能简单的解,那么我们就能得到满足要求的旋转位置函数,从而可以设计我们的编码方案。
关于如何求解的,这里涉及到很多线性代数运算以及虚数,并且篇幅很长,对于详细的证明过程,可以参考本文章的开头给出苏神的博客。这里我直接给出旋转位置编码函数:
f
(
q
,
m
)
=
R
f
(
q
,
m
)
e
i
Θ
f
(
q
,
m
)
=
∥
q
∥
e
i
(
Θ
(
q
)
+
m
θ
)
=
q
e
i
m
θ
f(q,m)=R_f(q,m)e^{iΘ_f(q,m)}=∥q∥e^{i(Θ(q)+mθ)}=qe^{imθ}
f(q,m)=Rf(q,m)eiΘf(q,m)=∥q∥ei(Θ(q)+mθ)=qeimθ
根据复数乘法的几何意义,该变换实际上对应着向量的旋转,所以我们称之为“旋转式位置编码”,它还可以写成矩阵形式:
f
(
q
,
m
)
=
(
c
o
s
(
m
θ
)
−
s
i
n
(
m
θ
)
s
i
n
(
m
θ
)
c
o
s
(
m
θ
)
)
(
q
0
q
1
)
f(q,m)=\left(\begin{matrix}cos(mθ)&-sin(mθ)\\sin(mθ)&cos(mθ)\end{matrix}\right)\left(\begin{matrix}q_0\\q_1\end{matrix}\right)
f(q,m)=(cos(mθ)sin(mθ)−sin(mθ)cos(mθ))(q0q1)
由于内积满足线性叠加性,因此任意偶数维的RoPE,我们都可以表示为二维情形的拼接,即:
将该式子进行变换后,可得:
其中⊗(哈达玛积)是逐位对应相乘,即Numpy、Tensorflow等计算框架中的∗运算。从这个实现也可以看到,RoPE可以视为是乘性位置编码的变体。
直观理解和解释
如果直接从苏神的公式和证明,可能会难以理解旋转位置编码。那么我们其实可以从结论来理解,旋转位置编码实际上是将每一个位置上的token的嵌入向量,在平面空间上进行了一次旋转。每个向量的旋转角由两个因素决定,第一个是该向量的对应token在原始句子中的位置m(比如是句子序列中的第m个token),第二个是该向量的维度数(例如,从0维到d-1维,我们将所有向量分成d/2组,两两一组,则是0和1,2和3,…,d-2和d-1)。
由于原始的两个token相乘,其实可以理解为求两个向量的相似度,假设这个夹角为A。由于不同位置的token向量具有不同的语义信息,所以在不同的若干个向量求内积时,如果他们的内积相等,模型会认为他们表达的语义信息是一样的。但是,我们需要让模型分清每个token的位置信息和相对位置,所以我们对句子中每个token的表征向量旋转 t ∗ θ t*θ t∗θ的度数。那么m位置上的token就旋转了 m ∗ θ m*θ m∗θ,n位置上的token就旋转了 n ∗ θ n*θ n∗θ,因此两个token向量的内积就具有了各自的相对位置信息,可以记为 ( m − n ) θ i (m-n)θ_i (m−n)θi,其中 i = b a s e − 2 i / d i=base^{-2i/d} i=base−2i/d。对于浅层的向量特征(这里我们定义从1到d时,向量特征维度逐渐加深),因为旋转幅度比较大,所以善于捕获短距离上的token信息,深层的向量特征,旋转幅度比较小,所以善于捕获长距离上的token信息。
外推和扩展性
由于旋转位置编码也是需要一种相对位置编码,所以需要在训练时指定编码最大长度为1024或者2048,因此在超长距离的上下文输入后会出现一种情况:对于m-n特别大的情况时,可能在向量空间没有提前训练时学习的对应旋转角度的信息,所以会出现效果不好的情况。但是,编码算法依然可以正常使用,只是效果会不好。
针对这种情况,我们可以考虑进行插值,也就是压缩。具体来讲,对于浅层的向量特征,因为旋转频率比较高,所以可以旋转到覆盖很多个完整的周期,因此在外推性能上很强。但是深层的向量特征,由于旋转频率比较小,可能无法旋转覆盖到完整的周期,因此在面对长距的上下文时外推能力很弱,我们可以采用插值法,按缩放比例将超过L长度的token位置映射到L以内。
经验总结(Conclusion)
针对RoPE旋转位置编码,需要记住的核心点包括:
f
(
q
,
m
)
=
(
c
o
s
(
m
θ
)
−
s
i
n
(
m
θ
)
s
i
n
(
m
θ
)
c
o
s
(
m
θ
)
)
(
q
0
q
1
)
f(q,m)=\left(\begin{matrix}cos(mθ)&-sin(mθ)\\sin(mθ)&cos(mθ)\end{matrix}\right)\left(\begin{matrix}q_0\\q_1\end{matrix}\right)
f(q,m)=(cos(mθ)sin(mθ)−sin(mθ)cos(mθ))(q0q1)
以及三个关键的理解:
1.不同位置,转角不一样。转角差包含了相对位置信息。
2.维度:分成高频和低频
高频:短距离
低频:长距离
3.高频外推性强,低频插值能力强。