AI summary
type
status
date
slug
summary
category
tags
icon
password

位置编码

不同于 RNN、CNN 等模型,对于 Transformer 模型来说,位置编码的加入是必不可少的,因为纯粹的 Attention 模块是无法捕捉输入顺序的,即无法区分不同位置的 Token。为此我们大体有两个选择:
  1. 想办法将位置信息融入到输入中,这构成了绝对位置编码的一般做法;
  1. 想办法微调一下 Attention 结构,使得它有能力分辨不同位置的 Token,这构成了相对位置编码的一般做法。

绝对位置编码

💡
训练式
直接将位置编码当作可训练参数,比如最大长度为 512,编码维度为 768,那么就初始化一个 512×768 的矩阵作为位置向量,让它随着训练过程更新。
对于这种训练式的绝对位置编码,一般的认为它的缺点是没有外推性,即如果预训练最大长度为 512 的话,那么最多就只能处理长度为 512 的句子,再长就处理不了了。
💡
三角式
三角函数式位置编码,一般也称为Sinusoidal(正弦)位置编码,是 Google 的论文《Attention is All You Need》所提出来的一个显式解:
其中 分别是位置 k 的编码向量的第 2i 个分量,d 是位置向量的维度。
很明显,三角函数式位置编码的特点是有显式的生成规律,因此可以期望于它有一定的外推性。另外一个使用它的理由是:由于三角函数的性质,位置 的向量可以表示成位置 和位置 的向量组合,这提供了表达相对位置信息的可能性。
💡
递归式
可以用 RNN 模型来学习一种绝对位置编码,比如从一个向量 出发,通过递归格式 来得到各个位置的编码向量。
ICML 2020的论文《Learning to Encode Position for Transformer with Continuous Dynamical Model》把这个思想推到了极致,它提出了用微分方程(ODE) 的方式来建模位置编码,该方案称之为 FLOATER。显然,FLOATER 也属于递归模型,函数 可以通过神经网络来建模,因此这种微分方程也称为神经微分方程。
理论上来说,基于递归模型的位置编码也具有比较好的外推性,同时它也比三角函数式的位置编码有更好的灵活性(比如容易证明三角函数式的位置编码就是 FLOATER 的某个特解)。但是很明显,递归形式的位置编码牺牲了一定的并行性,可能会带速度瓶颈。
💡
相乘式
似乎将“加”换成“乘”,也就是 的方式,似乎比 能取得更好的结果。具体效果笔者也没有完整对比过,只是提供这么一种可能性。关于实验来源,可以参考《中文语言模型研究:(1) 乘性位置编码》

相对位置编码

相对位置并没有完整建模每个输入的位置信息,而是在算 Attention 的时候考虑当前位置与被 Attention 的位置的相对距离,由于自然语言一般更依赖于相对位置,所以相对位置编码通常也有着优秀的表现。
💡
经典式
相对位置编码起源于 Google 的论文《Self-Attention with Relative Position Representations》,华为开源的 NEZHA 模型也用到了这种位置编码,后面各种相对位置编码变体基本也是依葫芦画瓢的简单修改。
一般认为,相对位置编码是由绝对位置编码启发而来,考虑一般的带绝对位置编码的 Attention:
为了引入相对位置信息,Google 把第一项位置去掉,第二项 改为二元位置向量 ,变成:
以及 换成
所谓相对位置,是将本来依赖于二元坐标的向量,改为只依赖于相对距离 i-j,并且通常来说会进行截断,以适应不同任意的距离:
这样一来,只需要有限个位置编码,就可以表达出任意长度的相对位置(因为进行了截断),不管 是选择可训练式的还是三角函数式的,都可以达到处理任意长度文本的需求。
💡
XLNET 式
XLNET 式位置编码其实源自 Transformer-XL 的论文《Transformer-XL: Attentive Language Models Beyond a Fixed-Length Context》,只不过因为使用了 Transformer-XL 架构的 XLNET 模型并在一定程度上超过了 BERT 后,Transformer-XL 才算广为人知,因此这种位置编码通常也被冠以 XLNET 之名。
XLNET 式位置编码源于对上述 的完全展开。
Transformer-XL的做法很简单,直接将 替换为相对位置向量 ,至于两个 ,则干脆替换为两个可训练的向量 u,v,
该编码方式中的 没有像经典模型那样进行截断,而是直接用了正弦式的生成方案,由于其编码空间与 不一定相同,所以 前面的 换了另一个独立的矩阵 ,还有 可以直接合并为单个 u,v,所以最终使用的式子是:
此外, 上的位置偏置就直接去掉了,即直接令 ,似乎从这个工作开始,后面的相对位置编码都只加到 Attention 矩阵上去,而不加到 上去了。
💡
T5 式
T5模型出自文章《Exploring the Limits of Transfer Learning with a Unified Text-to-Text Transformer》,里边用到了一种更简单的相对位置编码。思路依然源自 展开式。
如果非要分析每一项的含义,那么可以分别理解为“输入-输入”、“输入-位置”、“位置-输入”、“位置-位置”四项注意力的组合。如果我们认为输入信息与位置信息应该是独立(解耦)的,那么它们就不应该有过多的交互,所以“输入-位置”、“位置-输入”两项Attention可以删掉,而 实际上只是一个只依赖于 i,j 的标量,我们可以直接将它作为参数训练出来,即简化为:
说白了,它仅仅是在Attention矩阵的基础上加一个可训练的偏置项而已,而跟XLNET式一样,在 上的位置偏置则直接被去掉了。
比较“别致”的是,不同于常规位置编码对将 视为 i-j 的函数并进行截断的做法,T5对相对位置进行了一个“分桶”处理,即相对位置是 i-j 的位置实际上对应的是 f(i-j) 位置,映射关系如下:
ij
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
f(i−j)
0
1
2
3
4
5
6
7
8
8
8
8
9
9
9
9
i−j
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
...
f(i−j)
10
10
10
10
10
10
10
11
11
11
11
11
11
11
11
...
这个设计的思路其实也很直观,就是比较邻近的位置(0~7),需要比较得精细一些,所以给它们都分配一个独立的位置编码,至于稍远的位置(比如8~11),我们不用区分得太清楚,所以它们可以共用一个位置编码,距离越远,共用的范围就可以越大,直到达到指定范围再clip。
💡
DoBERTa 式
DeBERTa也是微软搞的,论文为《DeBERTa: Decoding-enhanced BERT with Disentangled Attention》
其实DeBERTa的主要改进也是在位置编码上,同样还是从展开式出发,T5是干脆去掉了第2、3项,只保留第4项并替换为相对位置编码,而DeBERTa则刚刚相反,它扔掉了第4项,保留第2、3项并且替换为相对位置编码(果然,科研就是枚举所有的排列组合看哪个最优):
不过,DeBERTa比较有意思的地方,是提供了使用相对位置和绝对位置编码的一个新视角,它指出NLP的大多数任务可能都只需要相对位置信息,但确实有些场景下绝对位置信息更有帮助,于是它将整个模型分为两部分来理解。以Base版的MLM预训练模型为例,它一共有13层,前11层只是用相对位置编码,这部分称为Encoder,后面2层加入绝对位置信息,这部分它称之为Decoder,还弄了个简称EMD(Enhanced Mask Decoder);至于下游任务的微调截断,则是使用前11层的Encoder加上1层的Decoder来进行。
SuperGLUE上的成绩肯定了DeBERTa的价值,但是它论文的各种命名真的是让人觉得极度不适,比如它自称的“Encoder”、“Decoder”就很容易让人误解这是一个Seq2Seq模型,比如EMD这个简称也跟Earth Mover's Distance重名。虽然有时候重名是不可避免的,但它重的名都是ML界大家都比较熟悉的对象,相当容易引起误解,真不知道作者是怎么想的...

其他位置编码

绝对位置编码和相对位置编码虽然花样百出,但仍然算是经典范围内,从上述介绍中我们依然可以体会到满满的套路感。除此之外,还有一些并不按照常规套路出牌,它们同样也表达了位置编码。
(1)CNN式
尽管经典的将CNN用于NLP的工作《Convolutional Sequence to Sequence Learning》往里边加入了位置编码,但我们知道一般的CNN模型尤其是图像中的CNN模型,都是没有另外加位置编码的,那CNN模型究竟是怎么捕捉位置信息的呢?
如果让笔者来回答,那么答案可能是卷积核的各项异性导致了它能分辨出不同方向的相对位置。不过ICLR 2020的论文《How Much Position Information Do Convolutional Neural Networks Encode?》给出了一个可能让人比较意外的答案:CNN模型的位置信息,是Zero Padding泄漏的!
我们知道,为了使得卷积编码过程中的feature保持一定的大小,我们通常会对输入padding一定的0,而这篇论文显示该操作导致模型有能力识别位置信息。也就是说,卷积核的各向异性固然重要,但是最根本的是zero padding的存在,那么可以想象,实际上提取的是当前位置与padding的边界的相对距离。
不过,这个能力依赖于CNN的局部性,像Attention这种全局的无先验结构并不适用。
(2)复数式
复数式位置编码可谓是最特立独行的一种位置编码方案了,它来自ICLR 2020的论文《Encoding word order in complex embeddings》。论文的主要思想是结合复数的性质以及一些基本原理,推导出了它的位置编码形式(Complex Order)为:
这里的i是虚数单位,j代表某个词,k代表该词所在的位置,而:
代表词j的三组词向量。你没看错,它确实假设每个词有三组跟位置无关的词向量了(当然可以按照某种形式进行参数共享,使得它退化为两组甚至一组),然后跟位置k相关的词向量就按照上述公式运算。
你以为引入多组词向量就是它最特立独行的地方了?并不是!我们看到上式还是复数形式,你猜它接下来怎么着?将它实数化?非也,它是将它直接用于复数模型!也就是说,它走的是一条复数模型路线,不仅仅输入的Embedding层是复数的,里边的每一层Transformer都是复数的,它还实现和对比了复数版的Fasttext、LSTM、CNN等模型!这篇文章的一作是Benyou Wang,可以搜到他的相关工作基本上都是围绕着复数模型展开的,可谓复数模型的铁杆粉了~
(3)融合式(RoPE)
  • RoPE通过绝对位置编码的方式实现相对位置编码,综合了绝对位置编码和相对位置编码的优点。
  • 主要就是对attention中的q, k向量注入了绝对位置信息,然后用更新的q,k向量做attention中的内积就会引入相对位置信息了

RoPE

RoPE旋转位置编码是苏神提出来的一种相对位置编码,之前主要用在自研的语言模型roformer上,后续谷歌Palm和meta的LLaMA等都是采用此位置编码,通过复数形式来对于三角式绝对位置编码的改进。
论文中提出为了能利用上 token 之间的相对位置信息,假定 query 向量和 key 向量之间的内积操作可以被一个函数 g 表示,该函数的输入是词嵌入向量 ,和它们之间的相对位置 m-n:
接下来的目标就是找到一个等价的位置编码方式,从而使得上述关系成立。
推导过程略了,这里直接放结果:
假设 表示角度为 a 的旋转矩阵,那么具有如下性质:
回到旋转位置编码,我们可以去证明:
我们上面得到了满足要求的2*2矩阵,但是attention的q向量是d维,
需要对于d//2组的位置编码进行设计。
让我们先忘掉上面的矩阵,如何把第m个位置表示为一个d//2维的向量M,让m在增加时,向量M的变化很均匀。
可以进行设计,把位置变成一个 进制的编码,比如104的10进制表示为(1,0,4),而105的10进制表示为(1,0,5)只变化了1,还比较均匀,这里的
最终,RoPE矩阵可以拆解为2步生成:
  • 把位置 m,转成 进制,构成一个 d//2 维的向量。
  • 每维的数值,映射到一个 2*2 的矩阵上。
于是得到:
notion image
因为RoPE矩阵的稀疏性,可以用等价的实现:
notion image
其中 符号 ⊗ 代表哈达玛积(Hadamard Product),哈达玛积是对应元素相乘的逐元素乘法(element-wise multiplication)。
💡
为什么取 10k?
举个例子
比如d=8,也就是我们要把输入向量转换成一个4维的向量,采用10进制。
某个token的位置是第9999位的话,他的向量表示是(9,9,9,9)
按照transformers的计算公式的思路,会在每个位置做除法,也就是说按位除(1,10,100,1000),每个位置上的结果(9999,999.9,99.99,9.99)。
这个(9,9,9,9)与(9999,999.9,99.99,9.99)差距太大了,如果只保留个位数及以下的部分(9,9.9,9.99,9.99)才是我们可以接受的范畴,也就是说需要进行一个取余数的操作。
考虑到cos和sin的周期性,我们可以通过引入三角函数来近似取余数。
但是引入周期函数又会带来新的问题,如果函数周期是10,那么在0和1的表示很接近的同时,9和0也会很接近。因为0和10的表示一致,而9和10很接近。
也就是说(0,0,0,0)和(9,9,9,9)可能很接近,但实际上,两者一个是序列开头,一个是序列结尾,我们期望他们相距很远。
为了避免这一问题,比如BERT限制长度512,但是我们的base不能设置为512,而是要远大于512。
所以transformer会使用一个在当时超长的base:10000,在那个年代10k长度已经是不可能达到的长度了。
当然,这个数看起来取的如此随意,也说侧面证明了模型对β进制的β其实不大敏感?更说明NTK-Aware Scaled RoPE在外推性上的成功是合理的。
NTK-Aware Scaled RoPE 通过 缩放 RoPE 的旋转角度 来适应更长的序列长度,使得模型可以在 更长的上下文窗口 内保持良好的性能。
NTK(Neural Tangent Kernel,神经切核) 是一个用于分析 神经网络训练动态 的数学工具。它描述了 无限宽神经网络 在梯度下降训练过程中的行为,并揭示了深度学习模型的 收敛性 和 泛化能力

ALiBi (Attention with Linear Biases)

💡
用处和用法?
用处:可解决训练推理文本长度不一致,如论文中训练采用1024,推理采用2048。
思想:不直接输入position Embedding,然后 计算时加入一个偏置,偏置其实就包含了Q和K的元素相对位置.
Alibi 的方法也算较为粗暴,是直接作用在attention score中,给 attention score 加上一个预设好的偏置矩阵,相当于 q 和 k 相对位置差 1 就加上一个 -1 的偏置。其实相当于假设两个 token 距离越远那么相互贡献也就越低。
notion image
其中Alibi 位置编码是不需要通过训练的,给定的预设矩阵中还会乘上m的调节因子,m的设置与attention的头数有关,是2的指数差值。论文中也做了尝试把m作为学习参数,但是并没有获得更好的效果。
Alibi 位置编码的外推性比旋转位置编码外推性要好一些,旋转位置编码也是基于正余弦三角式位置编码改进融入相对位置信息,但是正余弦三角式位置编码外推性缺点也很明显,看起来是不需要训练可以直接推演无限长度位置编码,但是忽略了一点就是周期性函数有位置衰减(pos太大时 会变得很小,相邻位置编码相似),到远处的位置信息趋于直线震荡,基本很难有位置信息区分了,所以外推性比训练式的好不了多少,旋转位置编码基于此改进的自然也是如此。

长度外推问题

💡
是什么?
大模型的外推性问题是指大模型在训练时和预测时的输入长度不一致,导致模型的泛化能力下降的问题。在目前的大模型中,一般指的是超出预训练设置的上下文长度时,依旧保持良好推理效果的能力。
长度外推性=train short, test long
train short:1)受限于训练成本;2)大部分文本的长度不会特别长,训练时的max_length特别特别大其实意义不大(长尾)。
test long:这里long是指比训练时的max_length长,希望不用微调就能在长文本上也有不错的效果。
💡
解决方法有哪些?
(1)进制表示
我们将整数n以一个三维向量[a,b,c]来输入,a,b,c分别是n的百位、十位、个位。这样,我们既缩小了数字的跨度,又没有缩小相邻数字的差距,代价了增加了输入的维度——刚好,神经网络擅长处理高维数据。
如果想要进一步缩小数字的跨度,我们还可以进一步缩小进制的基数,如使用8进制、6进制甚至2进制,代价是进一步增加输入的维度。
(2)直接外推
简单来说,假如原来位置编码用三维向量表示,那外插就是直接增加一维。
可以提前预留多几维,训练阶段设为0,推理阶段直接改为其他数字,这就是外推(Extrapolation)。
notion image
然而,训练阶段预留的维度一直是0,如果推理阶段改为其他数字,效果不见得会好,因为模型对没被训练过的情况不一定具有适应能力。也就是说,由于某些维度的训练数据不充分,所以直接进行外推通常会导致模型的性能严重下降
(3)线性插值
就是将2000以内压缩到1000以内,比如通过除以2,1749就变成了874.5,然后转为三维向量[8,7,4.5]输入到原来的模型中。从绝对数值来看,新的[7,4,9]实际上对应的是1498(749*2),是原本对应的2倍,映射方式不一致;从相对数值来看,原本相邻数字的差距为1,现在是0.5,最后一个维度更加“拥挤”。所以,做了内插修改后,通常都需要微调训练,以便模型重新适应拥挤的映射关系。
notion image
不过,内插方案也不尽完美,当处理范围进一步增大时,相邻差异则更小,并且这个相邻差异变小集中在个位数,剩下的百位、十位,还是保留了相邻差异为1。换句话说,内插方法使得不同维度的分布情况不一样,每个维度变得不对等起来,模型进一步学习难度也更大
(4)进制转换
有没有不用新增维度,又能保持相邻差距的方案呢?进制转换!三个数字的10进制编码可以表示0~999,如果是16进制呢?它最大可以表示163−1=4095>1999。所以,只需要转到16进制,如1749变为[6,13,5],那么三维向量就可以覆盖目标范围,代价是每个维度的数字从0~9变为0~15。
notion image
这个进制转换的思想,实际上就对应着文章开头提到的NTK-aware scaled RoPE!
notion image
💡
长度外推的两个核心问题?
  1. 预测时位置编码的外推:没见过的就无法保证很好的泛化,不仅学习式位置编码如此;像正弦位置编码、RoPE也有这样的问题,它们自身虽然不用学习,但是会影响上层参数的学习;
  1. 预测时序列更长,导致注意力相比训练时更分散:序列长度增大意味着attention分布的熵增大了,注意力更分散了;
可见,长度外推性问题并不完全与设计一个良好的位置编码等价。
然后,还有个问题是,虽然PE一直是transformer类模型中的重要的基础组件,很多位置编码也在尝试做一些外推性的工作,但整体来看早期的LLM其实没有特别关注或者说纠结长度外推性,直到后面各种NLG模型的崛起,尤其是ChatGPT的出现,大家才惊觉原来上下文可以做的这么长了?
为什么目前市面上的LLM鲜有使用呢(据目前所知,好像只有BLOOM/MPT/采用了ALiBi)?可能的原因:
  1. 专注于长度外推性的工作主要是在21/22年后才逐渐出现,效果尚未经过充分检验;
  1. 长度外推性的评测指标与LLM的评测指标并不完全match:目前长度外推性主要看PPL,这其实不够全面。PPL这类语言模型的指标,可能更关注局部上下文的预测,因此局部注意力相关的方案可能在这类评测上天然占优。
  1. 目前的长度外推性工作似乎更多的在强调外推性如何如何,但更重要的应该还是max_length内的效果,从LLM的角度来看,应该在保证max_length内的效果后再去追求外推性。比如,从GLM的消融实验来看,ALiBi的效果还是不如RoPE的。