第 07 篇 · 第二部分 · 注意力和 Transformer
位置编码:模型怎么知道"我打你"和"你打我"不一样
注意力本身对词序没有感知,位置编码就是为它补上的那一点"顺序感"。这一篇从最朴素的加法讲起,一路走到目前主流的 RoPE,并说明长上下文扩展的那些方法各自在做什么。贯穿全程的其实只有一句话:语言在意的是相对关系,位置表示也应当向"相对"靠拢。
一、把问题再摆一次:注意力对词序无感
自注意力打分靠的是 Q·KT,也就是一组点积。点积关心两个向量像不像,完全不关心谁在前面、谁在后面。把输入的顺序打乱,输出也会跟着打乱,可每个位置拿到的数值集合几乎没变——它只是换了位置。
后果很直接:"我打你"和"你打我"输入进去,纯注意力分不出区别。可语言里语序就是信息本身,主谓一颠倒,所要表达的意思就反了。
那怎么办?既然注意力自己长不出顺序感,就在它的输入里额外塞一份位置信息,让它间接感知。这份信息就是位置编码。它看似补丁,其实是 Transformer 能处理序列的前提。
再具体一点:把一句正常的话和它被打乱的版本分别输入一层注意力,两者每个位置的输出向量,分布上几乎一样——顺序换了,每个位置自己那行的数值没怎么动。模型缺的不是计算能力,缺的是一条判断谁先谁后的线索。
二、最朴素的做法:把位置"加"进向量里
最直接的办法:给第 pos 个位置造一个和词向量同维度的向量,和词嵌入直接相加。位置 1 一份,位置 2 一份,各自相加。
为什么能直接相加而不冲突?因为嵌入向量的空间足够宽,位置信息与语义信息叠加在同一批维度上也不会彼此淹没,模型在训练中会学会把两者分开读取。加完之后送进第一层,此后每层的注意力都能从"向量里残留的位置痕迹"里间接读出顺序。
原论文试过两套方案:一套是用可训练参数学出来的位置嵌入,一套是固定公式算出来的正弦余弦编码。两者效果接近,作者选了固定公式那一套——不占额外参数,在长于训练序列的输入上也能勉强外推一些。这个取舍本身就说明:位置编码的重点在"能不能表达相对关系",不在"多能拟合训练数据"。
这个"加"是逐元素相加,维度不变。也能这么理解:先给每个位置发一张写着编号的牌子,再把牌子上的数字贴进词向量里,跟着它一起往前走。
三、正弦余弦编码:那组奇怪的公式是怎么想出来的
原论文那套编码长这样,d 是向量维度,i 从 0 数到 d/2 − 1:
PE(pos, 2i) = sin( pos / 100002i/d )PE(pos, 2i+1) = cos( pos / 100002i/d )
初看像一组难解的公式。拆开来看:每个维度对应一根频率不同的正弦波,偶数维走 sin,奇数维走 cos,频率由低维到高维逐级降低——低维波长短、变化快,高维波长长、变化慢。
找个生活里的参照物,就是钟表。秒针转得很快,一天要转上千圈;时针缓慢地移动一格。看一串编码的时候,变化快的那些维度负责精确位置,变化慢的那些维度负责粗略方位,合起来既能分辨"第 3 个词"和"第 4 个词",也不至于因为位置一大就全都乱掉。
分母里的 10000 控制的是频率铺开的范围:最低维的角频率接近 1(对应波长 2π),最高维降到约万分之一。这样每一段位置都有对应的"指针读数",不至于重复到无法分辨。
为什么不直接用 0、1、2 这样的位置编号?因为编号会随位置不断增大,数值尺度与词向量对不上,训练时梯度也容易失控。摊成有界的一串波之后,位置再大,取值也始终落在 -1 到 1 之间,正是这层考虑催生了那组看似曲折的公式。
四、为什么非得用 sin/cos:相对位置可以被线性推出来
选 sin 和 cos 不是随手挑的三角函数,它们有个别的函数没有的性质:两角和差展开。从 sin(a+b) = sin a·cos b + cos a·sin b 能推出来一件事——
意思是:往后挪 k 个位置的那个编码,可以由当前位置的编码乘一个固定的矩阵得到,而这个矩阵只跟 k 有关,跟 pos 无关。
这条性质价值极大。模型只要学一个"转多少度"的线性操作,就能表达"往后看 k 个位置";相对距离 k 的信息,是从绝对编码里线性推出来的。注意力想要的本来就是相对关系,这套编码等于提前把它写入了。
还有个实用好处:公式不掺任何参数,算多长都行,不会遇上"第 513 个位置没参数了"的尴尬。这一条在后面讲长上下文时会反复提到。
这条线性性质还有个别名,叫等变性——你平移输入,输出的位置也跟着平移,规律不变。正是它让"相对"二字有了严格的数学落脚点,而不只是一句感觉上的话。
五、可学习位置编码和它的短板
BERT 走的是另一条路:建一张 max_len × d 的表,第 pos 行就是位置 pos 的向量,和词嵌入一起训练。这就是可学习位置编码。
好处是贴合模型自身的数据,学到什么由数据决定,不受公式形式的束缚。短板也很明显:表有长度上限。BERT 那张表只到 512,碰上第 513 个位置就没参数可查,只能截断或者临时插值。
更麻烦的是外推。训练时一直见的是 512 以内,推理时突然给长序列,模型对超出范围的位置一无所知,表现会明显下降。它记住的是"每个绝对位置长什么样",而不是"两个位置差多远",一旦越过训练边界就不灵了。
另外,正因为短板的根子在于"绑死了绝对位置",后来的方案才纷纷转向相对位置。下面要讲的 RoPE,就是这条线上最成功的一个。
六、RoPE:把位置编码进向量的旋转角
RoPE 是苏剑林等 2021 年在 RoFormer 里提出的,全称旋转位置编码。它换了个思路:不再往输入上加一个位置向量,而是直接在 Q、K 上动手。
做法是这样的:把向量的每一对维度看成复平面上的一个点,按位置给它旋转一个角度,第 m 个位置的旋转角正比于 m。于是第 m 个位置的向量和第 n 个位置的向量做点积时,旋转角之差只剩下 (m-n) 那一项——绝对位置被消掉了,点积结果天然带上的是相对距离。
关键差别在于作用点。正弦编码是加在输入上,位置信息得一层层传进去;RoPE 直接作用在注意力打分这一步,等于从根上影响"谁看谁"。而且它只动 Q 和 K,不动 V,也不改输入向量,动的地方小而准。
旋转这个动作听上去抽象,落到具体维度就好懂:相邻两维组成一个二维平面,模型在这个平面里把向量转一个角度,转多少由位置决定。转完之后向量长度没变,改的只是方向。
七、RoPE 为什么成了主流
几个原因叠在一起,让它成了后来开源模型的默认选择。
- 相对位置是自然长出来的,不用额外设计,垫平了绝对位置和相对位置的落差;
- 不占额外参数,就是一套固定的旋转操作,参数量和原来一样;
- 作用在注意力分数上,效果比"加在输入端"更直接;
- 和 KV Cache 相处融洽:缓存 K 时位置信息跟着一起存,推理时不用重算。
Llama 系列、很多国产大模型,用的都是它。可以说正弦编码是教科书上的经典,RoPE 则是工程实践中胜出的方案。
还有个容易忽略的好处:它对"处理多长"这件事更宽容。同一套旋转规则在任何长度上都成立,训练见过的长度和推理要用的长度之间,不再有一道硬墙,只要后续处理得当,往外推的空间比固定编码大得多。
八、长上下文扩展:位置插值与 NTK 等方法
模型训练时只见过 4K 长度,现在想让它读 128K,直接拉长多半会失效——模型对那么大的位置几乎没有经验。工程上因此出现了一批延长上下文的手段。
位置插值(Chen 等,2023)的办法是把超范围的位置按比例压回训练见过的尺度。32K 的第 30000 个位置,被映射成训练里 4K 的某个位置,相当于把一张大图缩回训练时的分辨率。代价是相邻位置被拉近,局部精度会下降一些,需要再微调加以弥补。
NTK 类做法走的是调频率的路子:不改位置数值,改正弦波频率的分布,让高频维度保住局部精度、低频维度负责照顾远处,等于把"分辨率"重新分配一遍。
ALiBi(Press 等,2021)干脆不编码位置,直接在注意力分数上按距离扣分:离得越远扣得越多。它简单、外推还不错,是另一条思路的代表。
这些方法目标一致:让模型在未训练过的长度上也不至于严重失效。它们是位置编码这套机制的延伸,不是另起炉灶。
这些手段各有各的代价。位置插值会轻微损伤短距离的分辨力,NTK 那类重调频率的做法需要重新校准才稳,ALiBi 简单,但当任务本身需要精确的位置信息时,就显得力不从心。选哪种,取决于你要在多长、多准之间找平衡。
九、小结
从正弦余弦,到可学习的位置表,再到把位置编码成旋转角的 RoPE,主线其实只有一条:把"绝对位置"往"相对位置"上转。原因不难想——"隔了三个词"比"排在第 384 个"对语言有用得多。谁离得近、谁跟着谁,才是语序真正要表达的东西。
下一篇进入新板块,讲 GPT:Transformer 砍掉编码器之后,怎么靠"猜下一个词"这么一道题,长成了通用模型。
补一句:位置编码不是训练完就能扔的配角。它决定了模型能稳定处理多长的文本,换一套位置方案,对长文本任务的影响,往往比单纯加参数更明显。
参考资料
- Ashish Vaswani 等, Attention Is All You Need, NeurIPS 2017. arXiv:1706.03762(正弦余弦位置编码的原始出处)
- Jianlin Su 等, RoFormer: Enhanced Transformer with Rotary Position Embedding, 2021. arXiv:2104.09864(RoPE 原始论文)
- Shouyuan Chen 等, Extending Context Window of Large Language Models via Positional Interpolation, 2023. arXiv:2306.15595(位置插值)
- Ofir Press, Noah A. Smith, Mike Lewis, Train Short, Test Long: Attention with Linear Biases Enables Input Length Extrapolation, 2021. arXiv:2108.12409(ALiBi)
- EleutherAI, Rotary Embeddings: A Relative Revolution. blog.eleuther.ai/rotary-embeddings(RoPE 的图解讲解)