主要的序列转换模型是基于复杂的递归或卷积神经网络,包括一个编码器和一个解码器。 性能最好的模型还通过注意力机制连接编码器和解码器。 我们提出了一种新的网络结构Transformer,它完全基于注意力机制,完全省去了重复和卷积。 在两个机器翻译任务上的实验表明,这些模型在质量上是优越的,同时具有更高的并行性,需要更少的训练时间。
大多数有竞争力的序列转换模型都有一个encoder-decoder结构。
这里,encoder将输入序列(x1,…,xn)映射到序列z=(z1,…,zn)。 给定z,decoder一次产生一个元素的符号输出序列(y1,…,ym)。注意:这里序列X于Z的个数是一样的,都为n,而输出结果Y的个数是不一样的。
在每一步,模型都是自回归的,在生成下一步时,将先前生成的符号作为附加输入。 转换器遵循这种总体架构,使用堆叠式自关注和逐点、完全连接的编码器和解码器层,分别如图的左半和右半所示。
编码器:编码器由n=6个相同层的Stack组成。 每一层有两个子层。 第一层是多头自注意机制,第二层是简单的、全连接的前馈网络(就是一个MLP)。 我们对两个子层使用残差连接,然后进行层归一化。 也就是说,每个子层的输出是LayerNorm(X+Sublayer(X)),其中Sublayer(X)是由子层本身实现的函数。 为了方便这些剩余连接,模型中的所有子层以及嵌入层都产生维度dModel=512的输出。
解码器:解码器也是由n=6个相同层的堆栈组成的。 除了每个编码器层中的两个子层之外,解码器插入第三个子层,其对编码器堆栈的输出执行多头关注。 与编码器类似,我们对每个子层使用剩余连接,然后进行归一化。 我们还修改了解码器堆栈中的自注意子层,以防止位置关注后续位置。 这种掩蔽,加上输出嵌入偏移一个位置的事实,确保了对位置i的预测只能依赖于小于位置i的已知输出。
注意力函数可以用查询Q、键K、值V来描述,其中查询Q、键K、值V和输出O都是向量。 其中,输出是通过值V的加权和计算出来的,分配给每个值V的权重是由查询Q与相应的键K计算出来的。 如下图所示
上面的方法只是注意力机制最简单的思想。实际上,计算注意力的方法有很多,在这篇文章中作者使用的是一种叫做Scaled Dot-Product Attention的注意力计算方法。
输入是由维度=dk的Q和K以及维度=dv的V组成。所谓点乘注意力机制就是在计算Q与K的相似度这一步使用点积的方法,然后将每个点积除以√dk,并应用一个Softmax函数来获得值的权重。 在实践中,我们同时计算对一组查询的关注函数,并将其打包成矩阵Q,键和值也打包成矩阵K和V。我们计算输出矩阵如下:
对于较小的dk值,除不除都无所谓,但是对于大的dk,点积增长的幅度很大,推动softmax函数到边界区域,导致梯度消失。 为了抵消这种影响,我们除以√dk
与使用K、V和Q执行单一的注意功能不同,我们发现用不同的线性投影分别将Q、K和V线性投影h次到dk、dk和dv维度是有益的。 然后,在每个投影版本上,我们并行执行关注函数,产生dv维的输出值。 它们被串联并再次投影回来,产生最终的值,如下图所示。 (所谓的多头注意力机制,就是对QKV做线性投影,得到结果之后再变回来)多头注意允许模型在不同位置共同关注来自不同表示子空间的信息。 对于一个单一的注意力头,平均抑制了这一点。
在这项工作中,我们使用h=8个平行的注意层或头部。 对于其中的每一个,我们使用dk=dv=dmodel/h=64。 由于降低了每个头的维数,总的计算代价与全维数的单头注意相似。
到此为止,我们已经讲完了Transformer注意力机制相关的内容,细心的同学可能会发现,通过上面的操作并不能处理序列当中的时序信息。换句话说,给定一个序列X=(x1,x2,…,xn),我们并不能确定x1与xn的前后关系。为了使模型利用序列的顺序信息,我们必须注入一些关于序列中的令牌。 为此,我们将“位置编码”添加到编码器和解码器堆栈底部的输入嵌入中。 位置编码具有与嵌入相同的维数Dmodel,以便两者可以求和。 位置编码有许多选择。 在这项工作中,我们使用不同频率的正弦和余弦函数:
其中pos是位置,i是维度。 也就是说,位置编码的每个维对应于一个正弦曲线。 波长从2π到10000·2π呈几何级数。 我们选择这个函数是因为我们假设它将允许模型容易地学习通过相对位置来参与,因为对于任何固定的偏移k,PEpos+k可以表示为PEpos的线性函数。