Transformer升级之路:4、二维位置的旋转式位置编码
By 苏剑林 | 2021-05-10 | 123875位读者 |在之前的文章《Transformer升级之路:2、博采众长的旋转式位置编码》中我们提出了旋转式位置编码RoPE以及对应的Transformer模型RoFormer。由于笔者主要研究的领域还是NLP,所以本来这个事情对于笔者来说已经完了。但是最近一段时间,Transformer模型在视觉领域也大火,各种Vision Transformer(ViT)层出不穷,于是就有了问题:二维情形的RoPE应该是怎样的呢?
咋看上去,这个似乎应该只是一维情形的简单推广,但其中涉及到的推导和理解却远比我们想象中复杂,本文就对此做一个分析,从而深化我们对RoPE的理解。
二维RoPE #
什么是二维位置?对应的二维RoPE又是怎样的?它的难度在哪里?在这一节中,我们先简单介绍二维位置,然后直接给出二维RoPE的结果和推导思路,在随后的几节中,我们再详细给出推导过程。
二维位置 #
在NLP中,语言的位置信息是一维的,换句话说,我们需要告诉模型这个词是句子的第几个词;但是在CV中,图像的位置信息是二维的,即我们需要告诉模型这个特征是在第几行、第几列。这里的二维指的是完整描述位置信息需要两个数字,并不是指位置向量的维数。
有读者可能想:简单展平后当作一维的处理不行吗?确实不大行,比如一个h×h的feature map,位置(x,y)展平后就变成了xh+y,而位置(x+1,y)和(x,y+1)展平后就分别变成了xh+y+h和xh+y+1,两者与xh+y的差分别是h和1。然而,按照我们直观的认识,(x+1,y)、(x,y+1)它们与(x,y)的距离应该是一样的才对,但是展平后却得到了不一样的h和1,这未免就不合理了。
所以,我们需要专门为二维情形设计的位置编码,不能简单地展平为一维来做。
标准答案 #
经过后面的一番推导,得到二维RoPE的一个解为:
Rx,y=(cosxθ−sinxθ00sinxθcosxθ0000cosyθ−sinyθ00sinyθcosyθ)
其中这个解很容易理解,它是两个一维RoPE组成的分块矩阵,实现上它就是将输入向量分为两半,一半施加x的一维RoPE,一半施加y的一维RoPE。由此形式我们也不难类比三维、四维等位置的RoPE。
矩阵(1)是一个正交矩阵,它满足两个关键性质:
1、相对性:即R⊤x1,y1Rx2,y2=Rx2−x1,y2−y1,也正是由于这个性质,RoPE才具有通过绝对位置实现相对位置的能力;
2、可逆性:给定Rx,y可以反解出x,y,这意味着对位置信息的编码是无损的。
某种意义上来说,式(1)是满足上述两个性质的最简单解,也就是说,虽然存在略有不同的解满足上述两个性质,但是它们形式上和实现上都相对复杂些。
推导思路 #
事后来看,RoPE其实就是找到了矩阵Rn=(cosnθ−sinnθsinnθcosnθ),使得满足“相对性”条件:
R⊤mRn=Rn−m
所以,不难想到,二维RoPE的基本要求也是满足相对性,即要找到矩阵Rx,y,使得它满足二维的相对性条件R⊤x1,y1Rx2,y2=Rx2−x1,y2−y1。不过,如果仅仅是这个要求的话,可行解就很多了,比如直接让
Rx,y=(cos(x+y)θ−sin(x+y)θsin(x+y)θcos(x+y)θ)
但这个解的问题是,我们无法从x+y逆向推出(x,y),这意味着这个选择对位置信息来说是有损的,所以我们需要多一个“可逆性”,保证可以从位置矩阵中无损地重构出原始位置信号。
对此,我们有两个比较自然的途径选择:1、四元数;2、矩阵指数。接下来我们将会逐一介绍它们。
四元数 #
在一维RoPE的推导中,我们主要以复数为工具,而四元数(Quaternion)是复数的推广,它同时也保留了复数的很多性质,所以用它来推导二维RoPE也算是一个自然的思路。不过很遗憾,这是一条走不通的途径,但笔者仍然将思考过程放置在此,供大家参考。
复数与矩阵 #
在高中时我们就学习过,复数a+bi跟二维向量(a,b)时一一对应的(为了跟后面的四元数对齐,这里把虚数单位i也加粗了),但这个对应关系只能保持加减法对应(因为向量没有通用的乘法运算)。更精妙的对应是将复数与矩阵对应
a+bi↔(a−bba)
在这个映射下,复数的加减乘除与矩阵的加减乘除一一对应,比如
(a+bi)(c+di)=(ac−bd)+(ad+bc)i(a−bba)(c−ddc)=(ac−bd−ad−bcad+bcac−bd)
所以,矩阵映射才是复数域的完全同构,而向量映射只是直观的几何理解。
复数的矩阵映射也是RoPE的重要基础,在《Transformer升级之路:2、博采众长的旋转式位置编码》中我们已经推导得到RoPE的复数表示是qeniθ=(cosnθ+isinnθ)q,所以根据复数的矩阵映射,cosnθ+isinnθ就对应着矩阵
Rn=(cosnθ−sinnθsinnθcosnθ)
从而得到了一维RoPE的矩阵形式。
四元数简介 #
前面说了,四元数是复数是一种推广,事实上它还是矩阵的“鼻祖”,从历史上来说,是先有四元数然后才有一般的矩阵运算,并且四元数启发了矩阵的很多运算。早年笔者也写了《与向量的渊源极深的四元数》、《几何的数与数的几何:超复数的浅探究》等文章来介绍四元数,欢迎读者参考。
如果说复数是一个二维向量,那么四元数就是一个四维向量,表示为a+bi+cj+dk,这里的i2=j2=k2=−1,但是它们本身都各不相等,几个基之间的运算规则是:
×1ijk11ijkii−1k−jjj−k−1ikkj−i−1
在当时它给人们最大的冲击是非交换性,比如ij=−ji≠ji。但除此之外,它跟复数运算其实是高度相似的。
比如类似复数的欧拉公式
ea+bi+cj+dk=ea(cosr+bi+cj+dkrsinr)
这里r=‖bi+cj+dk‖=√b2+c2+d2。此外,还有类似的矩阵映射
a+bi+cj+dk↔(a−b−c−dba−dccda−bd−cba)
违背相对性 #
关于这些公式背后的起源,那就说来话长了,这里也不打算细谈,有兴趣的读者请自行搜索资料阅读。有了欧拉公式和指数映射后,读者或许反应过来:一维RoPE无非是eniθ对应的矩阵映射,那么二维RoPE的话将exiθ+yjθ映射为矩阵形式不就行了?
笔者一开始也是这样想的,很遗憾,这是错的。错在哪里呢?在一维RoPE中,我们利用了内积的复数表示:
⟨q,k⟩=Re[qk∗]
该恒等式在四元数中同样成立,因此可以照搬。接着我们利用了复指数:
⟨qemiθ,kqeniθ⟩=Re[(qemiθ)(keniθ)∗]=Re[qemiθe−niθk∗]=Re[qe(m−n)iθk∗]
前两个等号都可以照搬到四元数中,关键是第三个等号在四元数中并不恒成立!一般地,对于两个四元数p,q,等式ep+q=epeq并不成立!更广义来说,对于两个乘法不满足交换律的对象,一般都有ep+q≠epeq。
所以,推导到最后,由于指数乘法无法转换为加法,最后的相对性没法得到保证。因此通过四元数推导这条路,就此夭折了...
矩阵指数 #
四元数的矩阵映射表明四元数事实上代表了一簇特定的4×4矩阵,四元数推导走不通,那么或许使用一般的矩阵分析可以走得通。事实上确实如此,在这一节中,我们将利用矩阵指数给出一个推导结果。
矩阵指数 #
这里的矩阵指数,并不是神经网络的用指数函数作为激活函数的逐位运算,而是是按照幂级数定义的运算:
expB=∞∑k=0Bkk!
其中Bk是指按照矩阵乘法将k个B连乘。关于矩阵指数,笔者之前曾写过《恒等式 det(exp(A)) = exp(Tr(A)) 赏析》,也欢迎参考阅读。
矩阵指数是非常重要的一种矩阵运算,它可以直接写出常系数微分方程组ddtxt=Axt的解:
xt=(exptA)x0
当然这跟本文的主题关系不大。对于RoPE的推导,我们主要利用到矩阵指数的如下性质:
AB=BA⇒(expA)(expB)=exp(A+B)
也就是说,如果A,B的乘法可以交换,那么矩阵指数就可以像数的指数一样将乘法转换为加法。不过要注意这是一个充分不必要条件。
至于怎么把矩阵指数算出来,这里没法再展开介绍了,但是很多软件库已经自带了矩阵指数运算,比如数值计算库scipy和tensorflow都有expm
函数,而符号计算的话,Mathematica里边有MatrixExp
函数。
一维通解 #
为什么能够将RoPE跟矩阵指数联系起来呢?因为一维的RoPE存在比较简单的指数表达式:
Rn=(cosnθ−sinnθsinnθcosnθ)=exp{nθ(0−110)}
于是笔者开始思考如下形式的矩阵作为RoPE的解:
Rn=expnB
其中B是一个跟n无关的矩阵。RoPE的必要条件是满足“相对性”条件(2),于是我们分析
(expmB)⊤(expnB)=(expmB⊤)(expnB)
这里先假设B⊤,B是可交换的,那么根据式(13)有
(expmB⊤)(expnB)=exp(mB⊤+nB)
要让mB⊤+nB=(n−m)B,只需要满足
B⊤=−B
这便是“相对性”给出的约束条件,刚才我们还假设了B⊤,B是可交换的,现在可以检验满足这个等式的B⊤,B一定是可交换的,所以结果是自洽的。
这也就是说,对于任何满足B⊤+B=0的矩阵B,expnB都是方程(2)的解,并且还可以证明它一定是正交矩阵。当然,根据expnB=(expB)n,我们更直接的得到:对于任意正交矩阵O,Rn=On都是方程(2)的解。
对于2×2的矩阵来说,B⊤+B=0的通解是B=(0−θθ0),于是就有了如式(14)的解。
二维约束 #
类似地,对于二维RoPE,我们考虑
Rx,y=exp(xB1+yB2)
作为候选解。重复上述关于“相对性”条件的推导:先假设x1B⊤1+y1B⊤2与x2B1+y2B2是可交换的,那么我们可以得到如下约束条件:
B⊤1+B1=0,B⊤2+B2=0
然而,x1B⊤1+y1B⊤2与x2B1+y2B2可交换,意味着(B1,B⊤1)、(B2,B⊤2)、(B1,B⊤2)和(B2,B⊤1)都可交换,但是上述两个约束只能保证(B1,B⊤1)和(B2,B⊤2)可交换,不能保证后两者的交换性,所以我们需要把它作为约束条件补充上去,得到:
{B⊤1+B1=0B⊤2+B2=0B1B⊤2=B⊤2B1
不难证明在前两个条件下,新增的约束条件也相当于B1B2=B2B1。
RoPE现身 #
由于满足前两个条件的2×2矩阵只有一个独立参数,不满足“可逆性”,所以我们至少要考虑3×3矩阵,它有3个独立参数
(0−a−ba0−cbc0)
为了保证可逆性,我们不妨设B1,B2是“正交”的,比如设:
B1=(0−a0a00000),B2=(00−b00−cbc0)
不失一般性还可以设a=1,那么由条件(21)解得b=0,c=0,即B2只能是全零解,这不符合我们的要求。Mathematica的求解代码为:
B[a_, b_, c_] = {{0, -a, -b}, {a, 0, -c}, {b, c, 0}};
B1 = B[1, 0, 0];
B2 = B[0, b, c];
Solve[{Dot[B1, B2] == Dot[B2, B1]}, {b, c}]
因此,我们至少要考虑4×4矩阵,它有6个独立参数,不失一般性,考虑正交分解:
B1=(0−a−b0a0−c0bc000000),B2=(000−d000−e000−fdef0)
解得
d=cf,e=−bf
求解代码:
B[a_, b_, c_, d_, e_,
f_] = {{0, -a, -b, -d}, {a, 0, -c, -e}, {b, c, 0, -f}, {d, e, f,
0}};
B1 = B[1, b, c, 0, 0, 0];
B2 = B[0, 0, 0, d, e, f];
Solve[{Dot[B1, B2] == Dot[B2, B1]}, {b, c, d, e, f}]
可以发现结果没有对f提出约束,所以从最简单起见,我们可以让f=1,剩下的b,c,d,e全部为0,此时
Rx,y=exp(0−x00x000000−y00y0)
可以增加个参数θ,完成展开,就得到:
Rx,y=exp{(0−x00x000000−y00y0)θ}=(cosxθ−sinxθ00sinxθcosxθ0000cosyθ−sinyθ00sinyθcosyθ)
延伸故事 #
至此,关于二维RoPE的推导介绍完毕。现在读者可能想问的是效果如何?很遗憾,现在还没有很完整的实验结果,毕竟笔者之前也没做过ViT相关的工作,而这个二维RoPE的推导也刚完成没多久,所以进展比较慢,只能说初步的结果显示还是挺有效的。EleutherAI团队的成员也实验过这个方案,效果也比已有的其他位置编码好。
说到EleutherAI团队,这里再多说几句。EleutherAI团队是前段时候比较火的号称要“复现GPT3”的那个团队,我们在文章《Transformer升级之路:2、博采众长的旋转式位置编码》中提出了RoPE及RoFormer后,有幸得到了EleutherAI团队的关注,他们做了很多补充实验,确认了RoPE比很多其他位置编码都更加有效(参考他们的博客《Rotary Embeddings: A Relative Revolution》),这促使我们完成了英文论文《RoFormer: Enhanced Transformer with Rotary Position Embedding》并提交到了Arxiv上。而关于二维RoPE的疑问,最初也是来源于EleutherAI团队。
文章小结 #
本文介绍了我们对RoPE的二维推广,主要以“相对性”、“可逆性”为出发点来确定二维RoPE的最终形式,尝试了四元数和矩阵指数两种推导过程,最终通过矩阵指数来给出了最终的解,从推导过程中我们还可以深化对RoPE的理解。
转载到请包括本文地址:https://spaces.ac.cn/archives/8397
更详细的转载事宜请参考:《科学空间FAQ》
如果您还有什么疑惑或建议,欢迎在下方评论区继续讨论。
如果您觉得本文还不错,欢迎分享/打赏本文。打赏并非要从中获得收益,而是希望知道科学空间获得了多少读者的真心关注。当然,如果你无视它,也不会影响你的阅读。再次表示欢迎和感谢!
如果您需要引用本文,请参考:
苏剑林. (May. 10, 2021). 《Transformer升级之路:4、二维位置的旋转式位置编码 》[Blog post]. Retrieved from https://spaces.ac.cn/archives/8397
@online{kexuefm-8397,
title={Transformer升级之路:4、二维位置的旋转式位置编码},
author={苏剑林},
year={2021},
month={May},
url={\url{https://spaces.ac.cn/archives/8397}},
}
May 12th, 2021
来拜读文章了
May 12th, 2021
估计过不了多久苏神的idea又要被盗了……
WhiteningBERT。。。
这个位置编码的改进会降低收敛速度吗?我改了代码之后,同样跑一个epoch,二维位置编码的任务准确率远低于随机初始化一个矩阵的训练式编码
按照目前有限的实验结果实现,如果是从零训练的话,RoPE收敛速度和效果都是好于可训练式绝对位置编码
June 9th, 2021
想请教第14步的等号是怎么得来的?
你是想知道怎么算还是想知道哪里可以查到呢?查的话,维基百科旋转矩阵条目就有;算的话,其实直接按照定义去算就行了,主要是(0−110)的k次方有周期性,很容易算。
好的,查到了,感谢解答!
September 10th, 2021
公式(1)矩阵的[3,4]位置 ,sin(−xθ)应该是笔误吧,是不是应该是sin(−yθ)。
是的,已经修正,谢谢。
June 24th, 2022
学习了,涨姿势啊!!
January 14th, 2023
试了一下在ddpm(就是苏神写的ddpm)里加入注意力层,然后引入RoPE 2D,发现收敛速度大幅提升,生成效果也有肉眼可见的提升。基本上效果:绝对位置编码 < 无位置编码 < 2D旋转位置编码,看起来图像中的位置编码必须能计算相对距离才行。
注意力层提升这么大吗?我倒是没有测过注意力模块。
确实是有提升的,在模型规模较小时比较明显,主要是对细节的建模提升较大,精细度上升了,当然显存占用也变大了。此外加入RoPE后,生成的图样各部分之间的位置更加符合“逻辑”,比如几乎不会出现眼睛错位之类的。
好的,感谢分享结果。
可耻的求一份RoPE 2D的实现代码可以吗。
大致实现:
position1_ids = position_ids // T # shape=[b, n]
position2_ids = position_ids % T # shape=[b, n]
position1_encoding = sinusoidal(position1_ids) # shape=[b, n, d]
position2_encoding = sinusoidal(position2_ids) # shape=[b, n, d]
position_encoding = concat([position1_encoding, position2_encoding], axis=-1) # shape=[b, n, 2d]
q, k = rope(position_encoding, q, k)
苏神,假设一张图片的抽取的特征图大小为hxh,特征图中每个元素为16维的向量,那么是不是可以理解为前8维是按照该元素x轴坐标确定旋转角度,后8维是按照该元素y轴坐标确定旋转角度,且后八维的θi(i是下标)中的i要从1开始索引。
对的。
好的,感谢苏神
April 4th, 2023
苏神,请问为什么“是否满足交换律”会决定“Θp+q=ΘpΘq”是否成立呢?比如矩阵乘法也不满足交换律,但是这个等式也是成立的。
是p,q的交换律成立与否,决定了ep+q=epeq的成立与否。对于两个矩阵A,B,eA+B与eAeB一般也是不相等的。
October 28th, 2023
想请教一下,二维里面的最简单的解不应该是B1 = B2, 然后 旋转矩阵就是exp(B(x + y))吗
“推导思路”一节已经提过了啊,这个解的问题是我们无法从x+y反推出x,y,是有损的位置编码。
January 16th, 2024
苏神,想请教一下,如果q不仅有有x1、y1,还有heading,如何把(x2−x1,y2−y1)再按照-heading进行旋转呢?还是只能把x、y、heading当成三个维度?
微信群已经交流过,感觉有点难~
January 28th, 2024
苏老师,您好,如果2维旋转位置编码成立,那么推理到三维RoPE,我的理解是对位置(x,y,z),假设维度是48,那么可以把这48个维度分成三个16维,分别对x,y,z进行索引+编码?是这样理解的吗?四维就是把维度分成四个部分。
是的