在做 self-attention 之前,会用词嵌入向量x计算q,k,v向量同时加入位置信息,函数公式表达如下:
qm=fq(xm,m)kn=fk(xn,n)vn=fv(xn,n)
而基于 transformer 的位置编码方法都是着重于构造一个合适的f(q,k,v)函数形式。
对于位置编码,常规的做法是在计算 query, key 和 value 向量之前,会计算一个位置编码向量pi加到词嵌入xi上,位置编码向量pi同样也是d维向量,然后再乘以对应的变换矩阵W:
ft:t∈{q,k,v}(xi,i):=Wt:t∈{q,k,v}(xi+pi)
而经典的位置编码向量pi的计算方式是使用 Sinusoidal 函数:
pi,2t=sin(k/100002t/d)pi,2t+1=cos(k/100002t/d)
旋转位置编码(Rotary Position Embedding,RoPE)是一种能够将相对位置信息依赖集成到 self-attention 中并提升 transformer 架构性能的位置编码方式。而目前很火的 LLaMA、GLM 模型也是采用该位置编码方式。和相对位置编码相比,RoPE 具有更好的外推性,目前是大模型相对位置编码中应用最广的方式之一。
备注:什么是大模型外推性?
外推性是指大模型在训练时和预测时的输入长度不一致,导致模型的泛化能力下降的问题。例如,如果一个模型在训练时只使用了512个 token 的文本,那么在预测时如果输入超过512个 token,模型可能无法正确处理。这就限制了大模型在处理长文本或多轮对话等任务时的效果。
为了能利用上 token 之间的相对位置信息,假定 query 向量和 key 向量之间的内积操作可以被一个函数g表示,该函数g的输入是词嵌入向量xm,xn和它们之间的相对位置m−n:
⟨fq(xm,m),fk(xn,n)⟩=g(xm,xn,m−n)
接下来的目标就是找到一个等价的位置编码方式,从而使得上述关系成立。
假定现在词嵌入向量的维度是两维,这样就可以利用上2维度平面上的向量的几何性质,然后论文中提出了一个满足上述关系的f和g的形式如下:
fq(xm,m)=(Wqxm)eimθfk(xn,n)=(Wkxn)einθg(xm,xn,m−n)=Re[(Wqxm)(Wkxn)∗ei(m−n)θ]
fq(xm,m)=(cosmθsinmθ−sinmθ)cosmθ)(Wq(1,1)Wq(2,1)Wq(1,2)Wq(2,2))(xm(1)xm(2))=(cosmθsinmθ−sinmθ)cosmθ)(qm(1)qm(2))
g(xm,xn,m−n)=(qm(1)qm(2))(cos((m−n)θ)sin((m−n)θ)−sin((m−n)θ)cos((m−n)θ))(kn(1)kn(2))
RΘ,md=Wmcosmθ0sinmθ000⋮00−sinmθ0cosmθ000⋮0000cosmθ1sinmθ1⋮0000−sinmθ1cosmθ1⋮00⋯⋯⋯⋯⋱⋯⋯0000⋮cosmθd/2−1sinmθd/2−10000⋮−sinmθd/2−1cosmθd/2−1Θ={θi=10000−2(i−1)/d,i∈[1,2,…,d/2]}
由于这个矩阵具有很高的稀疏性,直接用矩阵乘法会很浪费算力,推荐通过下述方式来实现 RoPE:
RΘ,mdx=x0x1x2x3⋮xd−2xd−1⊗cosmθ0cosmθ0cosmθ0cosmθ1cosmθ1⋮cosmθd/2−1cosmθd/2−1+−x1x0−x3x2⋮−xd−1xd−2⊗sinmθ0sinmθ0sinmθ1sinmθ1⋮sinmθd/2−1sinmθd/2−1
其中⊗是逐位对应相乘,即计算框架中∗的运算。从这个实现也可以看到,RoPE可以视为是乘性位置编码的变体。
位置编码的前世今生:从绝对到相对open in new window
大部分长度外推的工作都在优化相对位置编码,因为绝对只能够关注特定窗口信息,而相对可以关注滑动窗口信息,这更加符合外推性的直觉。
最基础的训练式相对位置编码方式:本质上是学习相对位置的Embedding,再在Attention计算时将位置信息融入其中。
函数式相对位置编码,不再需要额外的训练参数,它的本质在于通过给原始的q,k向量经过一系列变换来表示其相对位置。(RoPE)
融合其实也非常简单,在模型的前k层只使用相对位置信息,而在后几层加入绝对位置信息,方式也非常粗暴:直接学习一个绝对位置Embedding,将其作为后面几层的q,这样就完成了融合!