• 作者:老汪软件技巧
  • 发表时间:2024-08-30 04:01
  • 浏览量:

1. 什么是位置编码

位置编码(Positional Encoding)是一种在处理序列数据时,用于向模型提供序列中每个元素位置信息的技术。

在自然语言处理(NLP)中,尤其是在使用Transformer模型时,位置编码尤为重要,因为Transformer模型本身并不包含处理序列顺序的机制。

位置编码的主要目的是让模型能够区分输入序列中词的顺序,从而更好地理解句子的结构和含义。

2. 好的位置编码

位置编码的远程衰减性是指随着序列中元素之间相对位置的增加,位置编码对模型性能的影响逐渐减弱的特性。这种特性在理论上对于Transformer模型是有益的,因为它可以模拟人类在处理长文本时注意力逐渐分散的现象

3. 位置编码的种类

位置编码通常分为两种类型:绝对位置编码和相对位置编码。

绝对位置编码:

这是最常见的一种位置编码方法,其核心思想是在每个输入序列的元素上添加一个位置向量,以表示该元素在序列中的具体位置。这个位置向量通常通过正弦和余弦函数生成,具有周期性,能够捕捉序列中的相对位置信息 。

相对位置编码:

这种编码方式侧重于考虑元素之间的距离信息。在自注意力机制中,通过加入位置偏置项,使模型能够感知到元素间的相对位置关系。常见的相对位置编码方法包括Sinusoidal Positional Encoding和Learned Positional Encoding,前者通过不同频率的正弦和余弦函数来计算位置编码,后者则是通过学习得到的参数来计算位置编码

4. 绝对位置编码的实现

绝对位置编码的实现通常采用正弦和余弦函数的组合,这种编码方式最早由Vaswani等人在《Attention is All You Need》中提出,被广泛应用于Transformer模型中。

绝对位置编码的实现通常涉及以下步骤:

4.1. 生成位置向量:

为序列中的每个位置生成一个位置向量。这个向量通常具有与模型的词嵌入维度相同的大小。

4.2 使用正弦和余弦函数:

绝对位置编码的计算公式如下:对于每个位置 pos 和每个维度索引 i,计算正弦和余弦函数的值:

PE(pos,2i)=sin(pos/10000(2i/dmodel))PE(pos, 2i) = sin( pos / 10000^{(2i / d_{model})})PE(pos,2i)=sin(pos/10000(2i/dmodel​))

PE(pos,2i+1)=cos(pos/10000(2i+1/dmodel))PE(pos, 2i+1) = cos( pos / 10000^{(2i+1 / d_{model})})PE(pos,2i+1)=cos(pos/10000(2i+1/dmodel​))

其中,

4.3. 添加到词嵌入:

将计算得到的位置向量添加到相应的词嵌入向量中。这样,每个词的嵌入不仅包含了语义信息,还包含了位置信息。

4.4. 训练模型:

在训练过程中,模型将学习如何利用这些位置编码来更好地理解序列数据。

绝对位置编码的设计允许模型捕捉序列中的相对位置信息,这对于理解语言结构和执行如机器翻译、文本摘要等任务至关重要。通过这种方式,Transformer模型能够区分相同词在不同位置的不同含义,从而提高模型的性能和准确性。

5.绝对位置编码FAQ

Q1:为什么是三角函数?

A1:正弦和余弦函数是周期性函数,可以捕捉序列中元素之间的相对位置信息。这种函数的周期性特征使得模型能够更好地理解序列中元素的位置关系,从而提高模型的性能和准确性。

Q2:为什么要除以10000?

A2:除以10000是为了缩放位置编码的值,使其在不同位置之间具有一定的差异性。这样,模型可以更好地区分不同位置的元素,通过调整10000这个缩放因子,可以控制模型对不同位置之间距离的敏感性。较小的缩放因子会使得位置编码对距离更敏感,而较大的缩放因子则使得模型对更广泛的位置范围敏感。

Q3:为什么要使用正弦和余弦函数交替?

A3:正弦和余弦函数交替使用是为了使位置编码具有不同的周期性特征。这样,模型可以更好地捕捉序列中元素之间的相对位置信息,从而提高模型的性能和准确性。

6. 相对位置编码

相对位置编码不是为序列中的每个位置分配一个固定的位置向量,而是在计算注意力权重时考虑了元素之间的相对位置关系。

相对位置编码的关键特点包括:

7.外推性

位置编码的外推性是指模型在处理推理阶段比训练阶段更长的序列时,如何有效地扩展其位置编码以保持性能。

在大模型中,由于显存资源的限制,通常在预训练时设计的最大序列长度有限,例如4k左右,但推理时可能需要处理更长的序列,如32K的文本。因此,设计合适的位置编码对于提升模型在更长序列上的外推性至关重要。

8.旋转位置编码RoPE

Rotation Position Encoding

RoPE提出为了能利用上 token 之间的相对位置信息,假定 query 向量qmq_mqm​ 和 key 向量 knk_nkn​之间的内积操作可以被一个函数ggg表示,该函数ggg的输入是词嵌入向量xmx_mxm​,xnx_nxn​ 和它们之间的相对位置m−nm-nm−n:

大胆假设,小心求证。 现在我们的目标就是找到一个合适的函数ggg,使得g(xm,xn,m−n)g(x_m, x_n, m-n)g(xm​,xn​,m−n)能够捕捉到词向量之间的相对位置信息。

RoPE提出,在词向量是二维的情况下,将平面转化为复平面,如果我们按照如下的方式定义函数fff,则可以找到对应的ggg

ReReRe指的是复数的实数部分,更近一步,我们可以将函数fff定义为:

这边,不就是原来的query矩阵乘上了一个旋转矩阵吗?也就是说,加上mmm这个位置信息后,如果使用RoPE的设计方案,就相当于将原query矩阵进行了旋转。这就是旋转的由来。

同理,fKf_KfK​可以表示为:

那么,对应的ggg函数就是:

9. 从二维到多维

在二维场景下,我们引入了复平面,是为了使用欧拉公式获取漂亮的数学特性,来简化过程。但是在多维场景下,我们可以直接使用矩阵的特性,来简化过程。将2维的RoPE推广到多维的RoPE,只需要将2维的RoPE的旋转矩阵RRR替换为多维的旋转矩阵RRR即可。

因为内积满足线性叠加性质,所以任意偶数维的RoPE都可以表示为二维情形拼接而成的形式。

即是在原来的q∗kq*kq∗k矩阵的基础上,加上了一个旋转矩阵Rθ,mdR^d_{\theta,m}Rθ,md​,这就是RoPE的设计思路。

在原始paper中,有一个直观的图

10.总结

旋转位置编码由苏剑林大神设计,其引入数学中最美丽的公式-欧拉公式。

大家可以关注他的博客《科学空间》kexue.fm/, 会学到很多东西。

后面我会专门讲欧拉公式和RoPE的设计思路。

参考

[1] 十分钟读懂旋转编码(RoPE)

[2] 让研究人员绞尽脑汁的Transformer位置编码

[3] Transformer升级之路:2、博采众长的旋转式位置编码

[4] Transformer学习笔记一:Positional Encoding(位置编码)

[5] RoFormer: Enhanced Transformer with Rotary Position Embedding

[6] GitHub: LLMForEverybody