概述
主流的序列转换模型(dominant sequence transduction models)都是基于复杂的递归神经网络或者卷积神经网络,包括一个编码器(encoder)和一个解码器(decoder)
表现最好的模型是利用注意力机制将编码器和解码器连接起来
我们提出了一个简单的网络架构Transformer,简单地基于注意力机制,并且不用递归和卷积操作
在实验中,在两个机器翻译任务上,我们的模型表现出更强的并行性,同时训练时间也较短
我们的模型在WMT2014英转德翻译任务上实现了28.4的BLEU,比当前最高的要多出2 BLEU
在WMT2014英转法翻译任务上,我们的模型利用8个GPU,在训练3.5天之后达到单个模型最优的分数41.0 BELU,这要比最好的模型的训练消耗低得多
背景
以减少序列化的计算为目标的工作已有许多,比如扩展的神经GPU(Extended Neural GPU),ByteNet以及ConvS2S
以上的工作都是利用CNN作为基础的块来进一步搭建,从而并行化计算所有输入和输出的隐藏表征(hidden representation)
在这些模型之中,关联两个任意的输入和输出位置的信号所需操作的数量随着位置间的距离而增加
ConvS2S是线性的,ByteNet是对数的,这使得学习距离远的依赖变得困难
在Transformer之中,这被降低至一个常数的操作数,尽管产生了一定的代价,原因是平均了加权注意力的位置导致了有效的解析力(effective resolution)下降
我们使用多头部的注意力(Multi-Head Attention)对该现象进行抵消
Self-Attention,自注意力,有时也称之为内部注意力(intra-attention),是一种注意力机制,关联一个序列中的不同位置,进而计算该序列的一个表征
该种技术在阅读理解,抽象总结,文字蕴含(texual entailment)以及学习任务独立的句子表征等任务中表现出色
端到端的记忆网络(End-to-End Memory Network)是基于递归注意力机制,而不是序列对齐的递归,在单语言问答以及语言建模任务中表现出色
Transformer是第一个语言转导模型,完全依赖自注意力来计算输入和输出的表征,并且不使用序列对齐的RNN或者卷积
模型架构
大部分神经序列转导模型都是编码器-解码器结构,在这个结构中呢,编码器首先会将符号表示的输入序列 映射到连续表示的序列 对于给定的z,解码器会生成一个输出序列,在每一步模型是自回归的(auto-regressive),即当生成文本的时候利用先前生成的符号作为额外的输入
Transformer仿照上述的结构,编码器和解码器都使用堆叠的自注意力(stacked self-attention)以及点对点(point-wise),全连接的层
编码器和解码器的堆叠(Encoder and Decoder Stack)
编码器:编码器是6个相同的层的堆叠(N=6),每一层都有两个子层,第一个子层是多头部自注意力机制,第二个子层是一个简单的逐位置的全连接前馈网络。这里在两个子层中引入了残差连接(residual connection),同时进行层的标准化(layer normalization),即每一个子层的输出是LayerNorm(x+Sublayer(x))。为了促进这些残差连接,模型中所有的子层,和嵌入层(embedding layer)一样,产生512维的输出
解码器:解码器也是6个相同的层的堆叠,在编码器的层的结构中加入了第三个子层,其作用是在编码器Stack的输出上使用应用多头部注意力(Multi-Head Attention)
同样的,应用残差连接加上层的标准化
我们修改了解码器堆叠中的自注意力子层,来防止位置出现在后续位置上(prevent positions from attending to subsequent positions)
这种遮罩(masking),结合输出embedding进行一个位置的偏移,保证位置i的预测仅仅依赖于小于i的位置的已知输出
注意力(Attention)
一个注意力函数能够被描述成一个映射,将一个请求(query)和一个键值对(key-value pairs)集合映射到一个输出
其中query,key,value以及输出都是向量,输出即value的加权求和,其中每个value的权值通过query的compatibility function以及相应的key进行计算
这里我们需要解释一下这其中的query,key,value以及output
以 Neural Machine Translation by Learning to Jointly Align and Translate 一文所阐述的注意力为例子
如上图所示,输入为x(1), ..., x(n),得到隐藏状态h(1), ..., h(n), 将h(n+1)输入到解码器中得到第一个解码器的隐藏状态z(1)
这时候需要将z(1)分别和h(1), ..., h(n)进行点积,得到每一个输入位置的分数score(1), ..., score(n) (分数的计算方法有多种,这里简单使用点积的形式)
将score整体归一化之后令h(i)*score(i), 对i进行求和之后直接得到上下文向量
将上下文向量和z(1)作为下一个单元的输入
这里面我们注意到,注意力机制实质就是上下文向量context vector的生成
回到文章中来,query可以看作是z(1),key-value类似<x(i), h(i)> [目前NLP工作中一般都是key=value,都看成隐藏状态h(i)], 输出就是context vector,因为上下文向量刚好也就是h(i)的加权求和
伸缩的点积注意力(Scaled Dot-Product Attention)
不妨记query和key的维度都是,value的维度为
将query,key和value堆叠成矩阵的形式,可得
其中的scale操作即是除以,过softmax层则是之前提到的归一化,最后进行加权求和得到上下文向量
针对注意力的计算,或者说是score的计算,还有一种称之为加性注意力,通过含有单层隐藏层的前馈网络来计算分数
与之相比点积注意力更快,而且对于空间能更好利用,毕竟矩阵乘法有许多高效的实现
这里文中提到当比较小的时候,加性的注意力表现要更加出色
多头部注意力(Multi-Head Attention)
如上图所示,先对V,K,Q进行线性变换,然后进行多次的缩放点积注意力计算,再将结果连接在一起,经过最后的线性变换得到结果
Attention函数即之前提到的缩放点积注意力,在这篇工作中头部的数量
注意力在文中模型的应用
在encoder-decoder注意力层中,请求query来自于先前的decoder层,key和value来自于encoder的输出,这使得对于decoder的每一个位置都能够参与输入句子的所有位置
编码器有自注意力层,在自注意力层中,所有的query,key和value来自于相同的地方,即编码器先前层的输出,编码器每个位置都能够参与先前的所有位置
相同地,解码器中的自注意力层,每个位置都能参与先前的所有位置,最大到该位置
逐点的前馈网络
前馈网络的设计比较简单
位置编码(positional encoding)
由于我们模型中没有卷积和递归的成分,需要加入token的位置信息,并且位置编码需要是和embedding维度相同的,保证可以相加起来
本工作中使用正弦和余弦函数进行位置编码
其中pos是位置,i是维度位置,即对应某个确定的位置,通过改变i获得相应编码的不同维度的值