IT技术之家

首页 > Android

Android

Transformer之Positional encoding_安静到无声

发布时间:2023-12-10 02:20:58 Android 28次 标签:transformer 深度学习 自然语言处理
我在学习NLP的时候,围绕着我不懂得技术点,逐个击破,以此期望能够把各个模块理解的更深入,使我在今后的学习中,能够更深入的分析,让自己更通透。接下来切入正题,介绍下Transformer中需要使用的Positional encoding,它主要为Transformer这种并行计算模型,难以理解输入句子的语序而针对性设计的。...

1. 前言

我在学习NLP的时候,围绕着我不懂得技术点,逐个击破,以此期望能够把各个模块理解的更深入,使我在今后的学习中,能够更深入的分析,让自己更通透。接下来切入正题,介绍下Transformer中需要使用的Positional encoding,它主要为Transformer这种并行计算模型,难以理解输入句子的语序而针对性设计的。

2. 产生背景

我看了很多关于RNN和LSTM的资料,这种模型有一个突出的特点就是串行输出(尽管计算起来比较慢),具有语句顺序。可是,在Transformer中利用的大量self attention,是并行计算的,也就是说每个token的位置是等价的,是没有真正的语言顺序,如下图所示:

对于人来讲,我们可以直观的知道token的位置,但是机器是却不能了解,如何让机器了解他的位置信息呢,即:

绝对位置信息,即a1排在第1个,a3排在第3个(全局层面)。相对位置信息,即a2在a1的后面,a3在a2的前面(元素层面)。不同位置间的距离。a1和a3差两个位置,a1和a4差三个位置
一个直观的方法就是,我们构建一个位置向量告诉模型,每个token在模型中所处的位置。

3. 位置编码的演变历程

如何构建一个非常合适的Positional encoding,是一个关键的问题,在原始论文中,作者采用了sin与con三角函数进行表示,但是并没有在文中解释为什么这么做,网上有很多材料进行分析,从傅里叶级数等进行分析,很有深度。知乎上,有位作者猛猿的回答, 简单易懂地解释了Positional encoding作用和实现方式,下面我们就沿着他的行文思路,对整个过程进行一个简单梳理,旨在加深印象。

3.1 用整数型标记位置

在对token进行Positional encoding时,一种特别直观的方法是采用整数数据的方式,比如【1,2,3,4,5,6,…】。可是这种方法存在一些问题。

    模型可能遇见比训练时所用的序列更长的序列。不利于模型的泛化。模型的位置表示是无界的。随着序列长度的增加,位置值会越来越大,这样数据分布不平衡,可能会引起扰动,难以训练。

3.2 用【0,1】范围进行标记

沿着3.1小节的思路,很容易想到的是,将整数标记的Positional encoding向量进行归一化操作。假设句子长度为 L L L,则产生的位置向量为 [ 1 L , 2 L , . . . , L L ] \left[ {{1 \over L},{2 \over L},...,{L \over L}} \right] [L1?,L2?,...,LL?]。上述方法解决的整数标记位置存在的问题(存在更长的位置序列;位置表示无界),但是也导师了的新的问题,就是位置距离的不一致。假设一句话有4个单词,位置向量为 [ 0.25 , 0.5 , 0.75 , 1 ] \left[ {0.25,0.5,0.75,1} \right] [0.25,0.5,0.75,1],如果一句话有两个单词,则位置向量为 [ 0.5 , 1 ] \left[ {0.5,1} \right] [0.5,1]。第一句话之间的位置距离是0.25,第二段话之间的位置距离为0.5。
因此,我们需要这样一种位置表示方式,满足于:

    它能用来表示一个token在序列中的绝对位置在序列长度不同的情况下,不同序列中token的相对位置/距离也要保持一致可以用来表示模型在训练过程中从来没有看到过的句子长度

3.3 利用二进制向量表述位置信息

这一种方法,我认为理解起来还是特别的容易的。与BCD编码类似,假设一个句子叫zero one two three four five six three我采用二进制编码的如下所示:

尽管这种方法有上界1,但是这种方法是离散不连续,难以直接训练。

3.4 用周期函数(sin)来表示位置

经过上文分析,我们知晓好的Positional encoding方式,不仅可以让机器知道每个token的位置信息,而且最好上有界且连续的。其中sin是有这种良好性质的函数。所以可以考虑将每一个token位置向量元素用sin函数表示。所以第k个token的位置向量可以定义为:
但是缺点在于三角函数具有周期性,可能出现pos值(一句话中的第几个单词,这里的表达和 t t t基本一致)不同但是PE值相同的情况。我在阅读原作者这里分析时,当时并不理解,在看到这篇博文时Positional Encoding的原理和计算,我深刻明白了作者想要表达的意思。

简单解释就是,sin是一个周期性震荡函数,当我们选择较大的频率时,很有可能出 t t t值不同,但是 P E t PE_t PEt?相同的这种情况。其实想象一下也是比较容易理解的,如果频率偏大,sin函数的波长就很短,当t位置比较大时,计算出的位置向量的值,大概率不是在第一个周期计算得到,这样位置向量呈现的结果将不是单调的,所以可能会相同。这仅仅是推测,知乎作者
给出了一个图,来证实这个想法,具体如下所示,在d_model = 3时,图中的点表示每个token的位置向量,颜色越深,token的位置越往后,在频率偏大的情况下,位置响亮点连成了一个闭环,靠前位置(黄色)和靠后位置(棕黑色)竟然靠得非常近:

为了避免这种情况,我们尽量将函数的波长拉长。一种简单的解决办法是同一把所有的频率都设成一个非常小的值。具体如下:
P E t = [ sin ? ( w 0 t ) , sin ? ( w 1 t ) … , sin ? ( w i ? 1 t ) , … , sin ? ( w d model? ? 1 t ) ] P E_t=\left[\sin \left(w_0 t\right), \sin \left(w_1 t\right) \ldots, \sin \left(w_{i-1} t\right), \ldots, \sin \left(w_{d_{\text {model }}-1} t\right)\right] PEt?=[sin(w0?t),sin(w1?t),sin(wi?1?t),,sin(wdmodel???1?t)] w i = 1 1000 0 i / ( d model? ? 1 ) w_i=\frac{1}{10000^{i /\left(d_{\text {model }}-1\right)}} wi?=10000i/(dmodel???1)1?
到此位置这个Positional encoding,我认为已经是非常的巧妙了,他解决的连续性和唯一性的问题,但是论文原始作者更精进一步,通过sin和cos交替解决了相对位置的表达。

3.5 用sin和cos交替来表达位置

这一块我认为知乎作者解释的特别好,便直接引述了他的表达,下式不仅可以表达绝对位置信息,也可以表达相对位置信息
P E t + Δ t = T Δ t ? P E t P E_{t+\Delta t}=T_{\Delta t} * P E_t PEt+Δt?=TΔt??PEt?
其中,T表示一个线性变换矩阵。观察这个目标式子,联想到在向量空间中一种常用的线形变换——旋转。在这里,我们将t想象为一个角度,那么 Δ t \Delta t Δt 就是其旋转的角度,则上面的式子可以进一步写成:
( sin ? ( t + △ t ) cos ? ( t + △ t ) ) = ( cos ? △ t sin ? △ t ? sin ? △ t cos ? △ t ) ( sin ? t cos ? t ) \left(\begin{array}{c} \sin (t+\triangle t) \\ \cos (t+\triangle t) \end{array}\right)=\left(\begin{array}{cc} \cos \triangle t & \sin \triangle t \\ -\sin \triangle t & \cos \triangle t \end{array}\right)\left(\begin{array}{c} \sin t \\ \cos t \end{array}\right) (sin(t+△t)cos(t+△t)?)=(cos△t?sin△t?sin△tcos△t?)(sintcost?)
有了这个构想,就可以把原来元素全都是sin函数的 P E T PE_T PET?做一个替换,让位置两两一组,分别用sin和cos的函数对来表示它们,则现在有:
P E t = [ sin ? ( w 0 t ) , cos ? ( w 0 t ) , sin ? ( w 1 t ) , cos ? ( w 1 t ) , … , sin ? ( w d model? 2 ? 1 t ) cos ? ( w d model? 2 ? 1 t ) ] \begin{aligned} &P E_t=\left[\sin \left(w_0 t\right), \cos \left(w_0 t\right), \sin \left(w_1 t\right), \cos \left(w_1 t\right), \ldots, \sin \left(w_{\frac{d_{\text {model }}}{2}-1} t\right)\right. &\left.\cos \left(w_{\frac{d_{\text {model }}}{2}-1} t\right)\right] \end{aligned} ?PEt?=[sin(w0?t),cos(w0?t),sin(w1?t),cos(w1?t),,sin(w2dmodel????1?t)?cos(w2dmodel????1?t)]?
在这样的表示下,我们可以很容易用一个线性变换,把 P E t PE_t PEt?转变为 P E t + Δ t P E_{t+\Delta t} PEt+Δt?:

参考

如何理解Transformer论文中的positional encoding,和三角函数有什么关系?
Positional Encoding的原理和计算