自从2017年transformer模型被提出以来,它已经从论文最初的machine translation领域,转向images,audio,video等等方面的应用(完成作者们在论文conclusion里的大同之梦)。原论文的篇幅很严密,不看代码的话,缺少了很多细节描绘(便是很痛苦一直在犯难的意思)。我的学历阅历大概是两周啃paper+代码 => 两周挖细节=>未来这个模型还有很多值得打量。在transformer系列的笔迹里,我把模型拆成了各个零件进行学习,终究把这些零件拼装成transformer,学习的road map如下:

  1. Positional Encoding
  2. Self-attention
  3. Batch Norm & Layer Norm
  4. ResNet,残差衔接
  5. subword,子词分词器
  6. 拼装:Transformer

这是transformer系列的第一篇,这一篇来探求Positional Encoding,方位编码。

一、什么是Positional Encoding

在transformer的encoder和decoder的输入层中,使用了Positional Encoding,使得终究的输入满足:

input = input_embedding + positional_encoding

这儿,input_embedding是经过惯例embedding层,将每一个token的向量维度从vocab_size映射到d_model,因为是相加关系,自然而然地,这儿的positional_encoding也是一个d_model维度的向量。(在原论文里,d_model = 512)

那么,咱们为什么需求position encoding呢?在transformer的self-attention模块中,序列的输入输出如下(不了解self-attention没关系,这儿只要关注它的输入输出就行):

在self-attention模型中,输入是一整排的tokens,关于人来说,咱们很简单知道tokens的方位信息,比方:

(1)肯定方位信息。a1是第一个token,a2是第二个token……

(2)相对方位信息。a2在a1的后边一位,a4在a2的后边两位……

(3)不同方位间的间隔。a1和a3差两个方位,a1和a4差三个方位….

可是这些关于self-attention来说,是无法分辩的信息,因为self-attention的运算是无向的。因为,咱们要想办法,把tokens的方位信息,喂给模型。

二、构造Positional Encoding的或许办法

2.1 用整型值符号方位

一种自然而然的想法是,给第一个token符号1,给第二个token符号2…,以此类推。

这种办法产生了以下几个主要问题:

(1)模型或许遇见比练习时所用的序列更长的序列。不利于模型的泛化。

(2)模型的方位表明是无界的。跟着序列长度的添加,方位值会越来越大。

2.2 用[0,1]规模符号方位

为了处理整型值带来的问题,能够考虑将方位值的规模限制在[0, 1]之内,其间,0表明第一个token,1表明终究一个token。比方有3个token,那么方位信息就表明成[0, 0.5, 1];若有四个token,方位信息就表明成[0, 0.33, 0.69, 1]。

但这样产生的问题是,当序列长度不一起,token间的相对间隔是不相同的。例如在序列长度为3时,token间的相对间隔为0.5;在序列长度为4时,token间的相对间隔就变为0.33。

因而,咱们需求这样一种方位表明办法,满足于:

(1)它能用来表明一个token在序列中的肯定方位

(2)在序列长度不同的状况下,不同序列中token的相对方位/间隔也要保持一致

(3)能够用来表明模型在练习过程中从来没有看到过的语句长度。

2.3 用二进制向量符号方位

考虑到方位信息效果在input embedding上,因而比起用单一的值,更好的计划是用一个和input embedding维度相同的向量来表明方位。这时咱们就很简单想到二进制编码。如下图,假设d_model = 3,那么咱们的方位向量能够表明成:

图解Transformer系列一:Positional Encoding(位置编码)

这下一切的值都是有界的(坐落0,1之间),且transformer中的d_model本来就足够大,基本能够把咱们要的每一个方位都编码出来了。

可是这种编码办法也存在问题:这样编码出来的方位向量,处在一个离散的空间中,不同方位间的变化是不接连的。假设d_model = 2,咱们有4个方位需求编码,这四个方位向量能够表明成[0,0],[0,1],[1,0],[1,1]。咱们把它的方位向量空间做出来:

图解Transformer系列一:Positional Encoding(位置编码)

假如咱们能把离散空间(黑色的线)转换到接连空间(蓝色的线),那么咱们就能处理方位间隔不接连的问题。一起,咱们不仅能用方位向量表明整型,咱们还能够用方位向量来表明浮点型。

2.4 用周期函数(sin)来表明方位

回想一下,现在咱们需求一个有界又接连的函数,最简单的,正弦函数sin就能够满足这一点。咱们能够考虑把方位向量当中的每一个元素都用一个sin函数来表明,则第t个token的方位向量能够表明为:

PEt=[sin(120t),sin(121t)…,sin(12i−1t),…,sin(12dmodel−1t)]PE_t = [sin(\frac{1}{2^0}t),sin(\frac{1}{2^1}t)…,sin(\frac{1}{2^{i-1}}t), …,sin(\frac{1}{2^{d_{model}-1}}t)]

结合下图,来了解一下这样设计的意义。图中每一行表明一个PEtPE_t,每一列表明PEtPE_t中的第i个元素。旋钮用于调整精度,越往右边的旋钮,需求调整的精度越大,因而指针移动的脚步越小。每一排的旋钮都在上一排的基础上进行调整(函数中t的效果)。经过频率12i−1\frac{1}{2^{i-1}} 来操控sin函数的波长,频率不断减小,则波长不断变大,此时sin函数对t的变化越不敏感,以此来达到越向右的旋钮,指针移动脚步越小的意图。

这也类似于二进制编码,每一位上都是0和1的交互,越往低位走(越往右边走),交互的频率越慢。

图解Transformer系列一:Positional Encoding(位置编码)

图解Transformer系列一:Positional Encoding(位置编码)

因为sin是周期函数,因而从纵向来看,假如函数的频率偏大,引起波长偏短,则不同t下的方位向量或许出现重合的状况。比方在下图中(d_model = 3),图中的点表明每个token的方位向量,色彩越深,token的方位越往后,在频率偏大的状况下,方位响亮点连成了一个闭环,靠前方位(黄色)和靠后方位(棕黑色)竟然靠得十分近:

图解Transformer系列一:Positional Encoding(位置编码)

为了避免这种状况,咱们尽量将函数的波长拉长。一种简单的处理办法是同一把一切的频率都设成一个十分小的值。因而在transformer的论文中,采用了110000i/(dmodel−1)\frac{1}{10000^{i/(d_{model}-1)}}

这个频率(这儿i其实不是表明第i个方位,可是大致意思差不多,下面会细说)

总结一下,到这儿咱们把方位向量表明为:

PEt=[sin(w0t),sin(w1t)…,sin(wi−1t),…,sin(wdmodel−1t)]PE_t = [sin(w_0t),sin(w_1t)…,sin(w_{i-1}t), …,sin(w_{d_{model}-1}t)]

其间,wi=110000i/(dmodel−1)w_{i} = \frac{1}{10000^{i/(d_{model}-1)}}

2.5 用sin和cos替换来表明方位

目前为止,咱们的方位向量完成了如下功能:

(1)每个token的向量仅有(每个sin函数的频率足够小)

(2)方位向量的值是有界的,且坐落接连空间中。模型在处理方位向量时更简单泛化,即更好处理长度和练习数据散布不一致的序列(sin函数本身的性质)

那现在咱们对方位向量再提出一个要求,不同的方位向量是能够经过线性转换得到的。这样,咱们不仅能表明一个token的肯定方位,还能够表明一个token的相对方位,即咱们想要:

PEt+△t=T△t∗PEtPE_{t+\bigtriangleup t} = T_{\bigtriangleup t} * PE_{t}

这儿,T表明一个线性变换矩阵。调查这个目标式子,联想到在向量空间中一种常用的线形变换——旋转。在这儿,咱们将t幻想为一个视点,那么△t\bigtriangleup t便是其旋转的视点,则上面的式子能够进一步写成:

(sin⁡(t+△t)cos⁡((t+△t))=(cos⁡△tsin⁡△t−sin⁡△tcos⁡△t)(sin⁡tcos⁡t)\begin{pmatrix} \sin(t + \bigtriangleup t)\\ \cos((t + \bigtriangleup t) \end{pmatrix}=\begin{pmatrix} \cos\bigtriangleup t&\sin\bigtriangleup t \\ -\sin\bigtriangleup t&\cos\bigtriangleup t \end{pmatrix}\begin{pmatrix} \sin t\\ \cos t \end{pmatrix}

有了这个设想,咱们就能够把原来元素全都是sin函数的PEtPE_t做一个替换,咱们让方位两两一组,分别用sin和cos的函数对来表明它们,则现在咱们有:

PEt=[sin(w0t),cos(w0t),sin(w1t),cos(w1t),…,sin(wdmodel2−1t),cos(wdmodel2−1t)]PE_t = [sin(w_0t),cos(w_0t), sin(w_1t),cos(w_1t),…,sin(w_{\frac{d_{model}}{2}-1}t), cos(w_{\frac{d_{model}}{2}-1}t)]

在这样的表明下,咱们能够很简单用一个线性变换,把PEtPE_t转变为PEt+△tPE_{t + \bigtriangleup t} :

PEt+△t=T△t∗PEt=([cos(w0△t)sin(w0△t)−sin(w0△t)cos(w0△t)]…0………0…[cos(wdmodel2−1△t)sin(wdmodel2−1△t)−sin(wdmodel2−1△t)cos(wdmodel2−1△t)])(sin(w0t)cos(w0t)…sin(wdmodel2−1t)cos(wdmodel2−1t))=(sin(w0(t+△t))cos(w0(t+△t))…sin(wdmodel2−1(t+△t))cos(wdmodel2−1(t+△t)))PE_{t+\bigtriangleup t} = T_{\bigtriangleup t} * PE_{t} =\begin{pmatrix} \begin{bmatrix} cos(w_0\bigtriangleup t)& sin(w_0\bigtriangleup t)\\ -sin(w_0\bigtriangleup t)& cos(w_0\bigtriangleup t) \end{bmatrix}&…&0 \\ …& …& …\\ 0& …& \begin{bmatrix} cos(w_{\frac{d_{model}}{2}-1 }\bigtriangleup t)& sin(w_{\frac{d_{model}}{2}-1}\bigtriangleup t)\\ -sin(w_{\frac{d_{model}}{2}-1}\bigtriangleup t)& cos(w_{\frac{d_{model}}{2}-1}\bigtriangleup t) \end{bmatrix} \end{pmatrix}\begin{pmatrix} sin(w_0t)\\ cos(w_0t)\\ …\\ sin(w_{\frac{d_{model}}{2}-1}t)\\ cos(w_{\frac{d_{model}}{2}-1}t) \end{pmatrix} = \begin{pmatrix} sin(w_0(t+\bigtriangleup t))\\ cos(w_0(t+\bigtriangleup t))\\ …\\ sin(w_{\frac{d_{model}}{2}-1}(t+\bigtriangleup t))\\ cos(w_{\frac{d_{model}}{2}-1}(t+\bigtriangleup t)) \end{pmatrix}

三、Transformer中positional Encoding办法:Sinusoidal functions

3.1 Transformer 方位编码界说:

有了上面的演化过程后,现在咱们就能够正式来看transformer中的方位编码办法了。

界说:

t是这个token在序列中的实际方位(例如第一个token为1,第二个token为2…)

PEt∈RdPE_t\in\mathbb{R}^d是这个token的方位向量,PEt(i)PE_{t}^{(i)}表明这个方位向量里的第i个元素

dmodeld_{model}是这个token的维度(在论文中,是512)

PEt(i)PE_{t}^{(i)}能够表明为:

PEt(i)={sin⁡(wit),ifk=2icos⁡(wit),ifk=2i+1PE_{t}^{(i)} = \left\{\begin{matrix} \sin(w_it),&if\ k=2i \\ \cos(w_it),&if\ k = 2i+1 \end{matrix}\right.

这儿:

wi=1100002i/dmodelw_i = \frac{1}{10000^{2i/d_{model}}}

i=0,1,2,3,…,dmodel2−1i = 0,1,2,3,…,\frac{d_{model}}{2} -1

看得有点懵没关系,这个意思和2.5中的意思是一模相同的,把512维的向量两两一组,每组都是一个sin和一个cos,这两个函数共享同一个频率wiw_i,一共有256组,因为咱们从0开端编号,所以终究一组编号是255。sin/cos函数的波长(由wiw_i决议)则从22\pi增长到2∗100002\pi * 10000

3.2 Transformer方位编码可视化

下图是一串序列长度为50,方位编码维度为128的方位编码可视化成果:

图解Transformer系列一:Positional Encoding(位置编码)

能够发现,因为sin/cos函数的性质,方位向量的每一个值都坐落[-1, 1]之间。一起,纵向来看,图的右半边简直都是蓝色的,这是因为越往后的方位,频率越小,波长越长,所以不同的t对终究的成果影响不大。而越往左边走,色彩替换的频率越频繁。

3.3 Transformer方位编码的重要性质

让咱们再深化探求一下方位编码的性质。

(1) 性质一:两个方位编码的点积(dot product)仅取决于偏移量△t\bigtriangleup t,也即两个方位编码的点积能够反应出两个方位编码间的间隔。

证明:

PEtT∗PEt+△t=∑i=0dmodel2−1[sin(wit)sin(wi(t+△t)+cos(wit)cos(wi(t+△t)]=∑i=0dmodel2−1cos(wi(t−(t+△t)))=∑i=0dmodel2−1cos(wi△t)\begin{aligned} PE_{t}^{T}*PE_{t+\bigtriangleup t} &= \sum_{i = 0}^{\frac{d_{model}}{2}-1} [sin(w_it)sin(w_i(t+\bigtriangleup t) + cos(w_it)cos(w_i(t+\bigtriangleup t)]\\ &= \sum_{i = 0}^{\frac{d_{model}}{2}-1}cos(w_i(t-(t+\bigtriangleup t)))\\ & = \sum_{i = 0}^{\frac{d_{model}}{2}-1}cos(w_i\bigtriangleup t) \end{aligned}

(2) 性质二:方位编码的点积是无向的,即PEtT∗PEt+△t=PEtT∗PEt−△tPE_{t}^{T}*PE_{t+\bigtriangleup t} = PE_{t}^{T}*PE_{t-\bigtriangleup t}

证明:

因为cos函数的对称性,根据性质1,这一点即可证明。

咱们能够分别练习不同维度的方位向量,然后以某个方位向量PEtPE_t为基准,去核算其左右和它相距△t\bigtriangleup t的方位向量的点积,能够得到如下成果:

图解Transformer系列一:Positional Encoding(位置编码)

这儿横轴的k指的便是△t\bigtriangleup t,能够发现,间隔是对成散布的,且整体来说,△t\bigtriangleup t越大或者越小的时候,内积也越小,能够反馈间隔的远近。也便是说,虽然方位向量的点积能够用于表明间隔(distance-aware) ,可是它却不能用来表明方位的方向性(lack-of-directionality)

当方位编码跟着input被喂进attention层时,采用的映射方其实是:

PEtTWQTWKPEt+kPE_t^TW_Q^TW_KPE_{t+k}

这儿WQTW_Q^TWKW_K表明self-attention中的query和key参数矩阵,他们能够被简写成WW(表明attention score的矩阵,到这儿看不懂也没事,在self-attention的笔记里会说明的)。咱们能够随机初始化两组W1W1, W2W2,然后将PEtTW1PEt+kPE_t^TW_1PE_{t+k}, PEtTW2PEt+kPE_t^TW_2PE_{t+k}PEtTPEt+kPE_t^TPE_{t+k}这三个内积进行比较,得到的成果如下:

图解Transformer系列一:Positional Encoding(位置编码)

绿色和黄色即是W1W_1W2W_2的成果。能够发现,进入attention层之后,内积的间隔意识(distance-aware)的模式也遭到了破坏。更详细的细节,能够参见复旦大学这一篇用transformer做NER的论文中。

在transformer的论文中,比较了用positional encoding和learnable position embedding(让模型自己学方位参数)两种办法,得到的结论是两种办法对模型终究的衡量指标差别不大。不过在后边的BERT中,已经改成用learnable position embedding的办法了,或许是因为positional encoding在进attention层后一些优异性质消失的原因(猜想)。Positional encoding有一些幻想+实验+证明的意味,而编码的办法也不只这一种,比方把sin和cos换个方位,仍然能够用来编码。关于positional encoding,我也还在持续探求中。

本文正在参与人工智能创作者签约季

四、参阅

  1. towardsdatascience.com/master-posi…
  2. kazemnejad.com/blog/transf…
  3. arxiv.org/pdf/1911.04…