位置编码是什么?RoPE 为什么很常用?
位置编码是什么?RoPE 为什么在大模型中很常用?

注意力机制不知道"谁先说话"
上一篇文章我们聊了注意力机制。
它能算出每个词和每个词有多相关。
但你有没有想过一个问题:注意力机制其实"脸盲"。
不管词在哪个位置,它都一视同仁。
"I love you" 和 "You love I",在它眼里是一回事。
这显然不对。
"我打你"和"你打我"意思完全相反。
主语和宾语的位置一旦交换,语义就翻转了。
问题出在哪?
自注意力在算相似度的时候,只看内容。
不看位置。
它不知道"我"是第一个词,"你"是第三个词。
它只知道这两个词的向量长什么样。
这就好像一个会议室里,每个人发言只说内容,不说自己是谁。
听众听完一堆话,分不清谁先说、谁后说。
顺序信息完全丢失了。
所以 Transformer 需要一个额外的机制:告诉模型每个词"住在哪里"。
这就是位置编码要解决的问题。

最直接的想法是什么?
给每个位置分配一个专属的向量。
第一个词加上"1号向量",第二个词加上"2号向量"。
这样模型不就知道词在哪了吗?
这个思路叫做绝对位置编码。
有两种常见实现方式。
第一种是训练式。
把位置也当成一个可学习的参数。
模型训练的时候,位置向量和词向量一起学。
就像给会议室的每个座位都配一个"座位标签",这些标签也是要训练的。
简单直接,但有个问题。
模型学到的位置信息是"死"的。
训练时最多见过1024个位置。
实际用的时候序列更长?对不起,没见过。
模型会困惑。
第二种是Sinusoidal编码。
不用学习,用数学公式直接算出来。
给位置m,生成一个向量,每个维度用不同的sin或cos函数。
不同位置的向量不一样,但有规律可循。
相邻位置的向量比较像,相隔远的向量差异大。
这样模型也许能"推理"出没见过的位置。
但本质上还是绝对位置的思路:给每个位置贴个标签。
问题是:语言真正在乎的是相对距离。
"我"和"打"离得很近,"我"和"的"隔了一个词。
这种"谁离谁近"的信息,比"这个词在第5位"重要得多。
绝对位置编码很难学到这种相对关系。

相对位置编码:换个角度思考距离
于是有人想:能不能不告诉模型词在哪,而是告诉模型词和词之间隔了多远?
这是一个思路上的大转弯。
不关心"这个词是第几位"。
关心"这两个词之间差了几个位置"。
token-2 和 token-1 的距离,等于 token-10002 和 token-10001 的距离。
这个信息对语言理解更有意义。
"小狗追大狗"和"大狗追小狗",主语和宾语的关系取决于谁追谁。
距离信息才是关键。
相对位置编码就是干这个的。
Google、XLNet、T5 都提出过自己的相对位置编码方案。
思路大致相同:在注意力计算时,把绝对位置换成相对位置。
但实现起来比较复杂,需要改attention内部的计算逻辑。
而且各种变体各有优缺点,没有统一标准。
这时候有人问了:能不能用更简单的方式,实现相对位置编码的效果?
这个问题引出了RoPE。

RoPE:以绝对之形,行相对之实
2021年,苏剑林提出了RoPE。
全称Rotary Position Embedding,旋转位置编码。
这个名字已经暗示了它的核心:旋转。
RoPE解决了一个矛盾:
相对位置编码效果好,但实现复杂。
绝对位置编码实现简单,但学不到相对关系。
RoPE说:我可以用绝对位置编码的形式,实现相对位置编码的效果。
怎么做到的?
关键洞察藏在数学里。
两个向量做内积运算。
如果给这两个向量都旋转一下。
旋转后的内积,等于旋转角度之差决定的那个值。
听不懂?没关系,看个类比。
两个人在环形跑道上跑步。
不管他们的起点在哪,只要知道他们转过的角度差,就知道谁领先、谁落后。
起点不重要,相对转角才重要。
RoPE就是这个思想。
不给词向量加一个"位置标签"。
而是把位置信息"编织"进向量的方向里。
通过旋转向量,让内积运算自然携带相对位置信息。
数学上可以证明:两个旋转后的向量做内积,结果和它们的相对位置有关。
完美。

从复数到高维:RoPE的工程实现
理论优美,但768维的向量怎么旋?
把高维向量拆成多个二维向量。
768维拆成384个"小组"。
每组当成一个二维向量,各自独立旋转。
每组用不同的旋转频率。
这借用的是Sinusoidal编码的设计。
高频维度转得快,低频维度转得慢。
就像多个转速不同的唱片机叠加在一起。
每两张唱片同步旋转,合起来记录完整的位置信息。
旋转操作只改变方向,不改变长度。
这很重要。
attention需要向量的大小来衡量重要程度。
旋转让位置信息进来了,但不影响向量长度。
这就是为什么RoPE效果好。
数学上优雅,实现上简洁。
而且旋转只发生在Q和K的输入阶段。
不需要改动attention内部计算。
工程实现异常简单。

大模型为什么都爱RoPE?
现在你理解了RoPE是什么。
再问一个问题:为什么它成了大模型的事实标准?
LLaMA用RoPE,PaLM用RoPE,Qwen用RoPE。
几乎所有主流大模型都在用。
原因有五个。
第一,理论优美。
用绝对编码的形式,实现了相对编码的效果。
数学简洁,证明优雅。
搞学术的看了会心一笑。
第二,实现简洁。
只需要在Q/K输入前做一次旋转矩阵乘法。
不改attention逻辑,不加额外参数。
搞工程的挑不出毛病。
第三,长文本友好。
远程衰减特性让模型对远距离token的注意力自然减弱。
符合语言规律:离得越远,关系通常越弱。
第四,外推能力强。
可以处理训练时未见过的更长序列。
不再受"座位不够"的限制。
第五,兼容线性Attention。
为O(n)复杂度的线性attention提供了位置编码方案。
这是其他方案很难做到的。
想象一下瑞士军刀。
功能全面,实现简洁,谁不爱用?
RoPE就是大模型世界的瑞士军刀。

写在最后
RoPE的成功告诉我们一个道理:
有时候最好的解决方案不是另起炉灶。
而是在现有框架中找到那个"刚刚好"的设计。
不用颠覆attention,不用引入复杂计算。
只是把向量转一转,位置信息就"恰到好处"地进去了。
这个设计值得记住。
下次你面试被问到位置编码,可以从这个角度聊聊。
聊完RoPE,下一个问题自然来了。
Transformer里还有个叫FFN的层,它又是干什么的?
为什么现在的大模型都在用SwiGLU?
这个问题,我们下篇再聊。
