以往的循环神经网络如LSTM和GRU,在序列建模和翻译问题中已经成为最先进的方法,但由于其循环结构,导致无法并行化计算,且难以对长序列的全局关系建模。故本文提出Transformer,一种非递归式的模型架构,完全依靠注意力机制来获取序列输入和输出之间的全局依赖关系,且Transformer允许并行化计算。具体为:
提出自注意力机制,是一种为了方便计算序列表示而关联单个序列的不同位置的注意力机制
基于循环注意力机制的端到端网络,已被证明在简单语言问答和语言建模任务上表现良好
第一个完全使用自注意力来计算序列输入输出的表示转换关系的模型
Transformer采用编码器-解码器结构,编码器将输入序列 ( x 1 , … , x n ) (x_1,\dots,x_n) (x1,…,xn)映射为表示 z = ( z 1 , … , z n ) z = (z_1,\dots,z_n) z=(z1,…,zn),解码器再将 z z z生成为输出序列 ( y 1 , … , y m ) (y_1, \dots, y_m) (y1,…,ym)。解码器生成下一个元素时,会将之前生成的元素作为额外的输入,且每次只生成一个元素,该过程称为自回归。编码器和解码器使用堆叠的自注意力和全连接层,如上图。
编码器由 N = 6 N = 6 N=6个相同结构层的堆栈组成,每一层都有两个子层,分别为多头自注意力机制(MSA)和全连接前馈神经网络(FFN)。其中,每个子层都采用残差连接进行层归一化,即,每个子层的输出为:
L a y e r N o r m ( x + S u b l a y e r ( x ) ) LayerNorm(x + Sublayer(x)) LayerNorm(x+Sublayer(x))
其中 S u b l a y e r ( x ) Sublayer(x) Sublayer(x)为子层自身实现的功能。为了促进这些残差连接,模型的所有子层及嵌入层输出维度都为 d m o d e l = 512 d_{model} = 512 dmodel=512。
解码器也由 N = 6 N = 6 N=6个相同结构层的堆栈组成。每个解码器层除了有MSA、FFN两个子层外,还在中间插入第三个子层,该子层会对编码器的输出执行多头交叉注意力。与编码器类似,解码器层的每个子层也采用残差连接进行层归一化。其次,会对解码器中的所有自注意力子 层添加掩码屏蔽,防止当前位置的自注意力关注后续位置的输入,确保对位置 i i i的预测只能依赖于位置小于 i i i的已知输出。
注意力函数会将query和一组key-value对映射到输出,query、key、value和输出都是向量。其中,输出定义为以value为值、以query和对应的key经过兼容性函数计算的结果为权重的加权和。
缩放点积注意力的输入有维度为 d k d_k dk的query、key以及维度 d v d_v dv的value。首先计算单个query与所有key的点积,并分别除以 d k \sqrt d_k dk,随后应用softmax获得 value的权重并与value做点积计算得到加权和。
在实践中,会同时计算一组query的注意力函数。将给定的一组query打包成矩阵Q,key和value分别打包成矩阵K和V ,则输出矩阵的计算公式为:
A t t e n t i o n ( Q , K , V ) = s o f t m a x ( Q K T d k ) V Attention(Q,K,V)=softmax(\frac {QK^T} {\sqrt{d_k}})V Attention(Q,K,V)=softmax(dkQKT)V
两个常用的注意力函数是加性注意力和点积注意力。点积注意力使用点积操作为兼容性函数(如上式,除了缩放因子 1 d k \frac 1 {\sqrt {d_k}} dk1),加性注意力使用单层前馈神经网络作为兼容性函数。两者的理论复杂度相似,但点积注意力在实践中要更快,且空间效率更高,因为其可以使用高度优化的矩阵乘法代码来实现。
对于 d k d_k dk较小的value,两种注意力机制在实验中的表现类似,但对于 d k d_k dk较大的value,加性注意力的表现优于点积注意力。故怀疑对于 d k d_k dk较大的value,点积的输出量级会增大,这会将softmax函数的梯度缩放到极小的区域,从而导致梯度消失。为了避免该问题,故将点积使用 1 d k \frac 1 {\sqrt {d_k}} dk1 进行缩放,整体流程如上图左。
与使用输出维度为 d m o d e l d_{model} dmodel的key、value和query执行单个注意力函数不同,本文发现对query、key和value使用h次(注意力头数)不同的线性投影(缩放点积注意力)对模型的最终表现有益,其中每个头都会分别学习到 d k d_k dk、 d k d_k dk和 d v d_v dv维度的线性投影。实践中,会对query、key和value在多个头上并行执行注意力函数,其中每个头都会产生 d v d_v dv维度的输出值,并将这些输出值concat起来再次投影,从而得到最终的输出值,如上图右。
多头注意允许模型关注来自不同位置的不同表示子空间的信息。如果只有一个注意力头,理论上就只能关注到这些子空间的平均信息。多头自注意力的公式如下:
M u l t i H e a d ( Q , K , V ) = C o n c a t ( h e a d 1 , … , h e a d h ) W O MultiHead(Q,K,V)=Concat(head_1,\dots,head_h)W^O MultiHead(Q,K,V)=Concat(head1,…,headh)WO
w h e r e h e a d i = A t t e n t i o n ( Q W i Q , K W i K , V W i V ) where \ head_i=Attention(QW^Q_i,KW^K_i,VW^V_i) where headi=Attention(QWiQ,KWiK,VWiV)
其中,投影参数矩阵 W i Q ∈ R d m o d e l × d k W^Q_i\in\R^{d_{model}\times d_k} WiQ∈Rdmodel×dk, W i K ∈ R d m o d e l × d k W^K_i\in\R^{d_{model}\times d_k} WiK∈Rdmodel×dk, W i V ∈ R d m o d e l × d v W^V_i\in\R^{d_{model}\times d_v} WiV∈Rdmodel×dv, W i O ∈ R h d v × d m o d e l W^O_i\in\R^{hd_v\times d_{model} } WiO∈Rhdv×dmodel。本工作采用了 h = 8 h = 8 h=8的多头注意力机制,其中每一个头的输出维度为 d k = d v = d m o d e l / h = 64 d_k = d_v = d_{model}/h = 64 dk=dv=dmodel/h=64,由于每个头的投影维度降低,总计算成本与单头注意力相同。
Transformer以三种不同的方式使用多头自注意力机制:
在交叉注意力层中,query为前一个解码器子层的输出,key和value为编码器的输出。解码器中的每个位置都可以关注输入序列中的所有位置
编码器的自注意力子层中,key、value和query都为编码器中前一子层的输出。编码器中的每个位置都可以关注输入序列的所有位置。
解码器的自注意力子层中,允许解码器中的每个位置关注包括该位置本身的解码器中的所有位置。但需要防止解码器中的左向信息流,以保持自回归特性,在缩放点积注意力中通过掩码屏蔽(将左向连接的softmax的输入设为 − ∞ -\infty −∞)来实现这一点。
编码器和解码器中的每一层都包含一个全连接前馈网络,其由两个ReLU激活的线性变换组成,并独立地应用于每一个位置的输出,同一层FFN的每个位置输入都使用相同参数的线性变换,不同层使用不同参数的线性变换。公式如下:
F F N ( x ) = m a x ( 0 , x W 1 + b 1 ) W 2 + b 2 FFN(x)=max(0,xW_1+b_1)W_2+b_2 FFN(x)=max(0,xW1+b1)W2+b2
另一种FFN方法是采用两个卷积核大小为1的卷积神经网络,输入和输出的维度是 d m o d e l = 512 d_{model} = 512 dmodel=512,两个卷积中间层的维为 d f f = 2048 d_{ff} = 2048 dff=2048。
与其他序列模型类似,本文使用可学习嵌入层将输入token和输出token转换为维度 d m o d e l d_{model} dmodel的向量,并使用可学习的线性变换和softmax函数将解码器输出转换为要预测的下一个token概率。编解码器的两个嵌入层和输出softmax层之前的线性变换层之间共享相同的权重矩阵。在嵌入层中,权重会乘以 d m o d e l \sqrt {d_{model}} dmodel。
由于transformer中不包含递归和卷积层,模型无从得知输入序列的位置信息。为了让模型利用序列的位置信息,会在编码器和解码器堆栈的底部向输入嵌入添加位置编码(Positional Encoding)。位置编码与嵌入具有相同的维度 d m o d e l d_{model} dmodel,因此可以将两者相加。
本工作中,使用不同频率的正弦函数和余弦函数做位置编码信息,公式如下:
P E ( p o s , 2 i ) = s i n ( p o s / 1000 0 2 i / d m o d e l ) PE_{(pos,2i)}=sin(pos/10000^{2i/d_{model}}) PE(pos,2i)=sin(pos/100002i/dmodel)
P E ( p o s , 2 i + 1 ) = c o s ( p o s / 1000 0 2 i / d m o d e l ) PE_{(pos,2i+1)}=cos(pos/10000^{2i/d_{model}}) PE(pos,2i+1)=cos(pos/100002i/dmodel)
其中pos是序列位置,i是维度,位置编码的每个维度对应一个波长呈 2 π 2π 2π到 10000 ⋅ 2 π 10000 · 2π 10000⋅2π几何级数的正弦信号。对于任何固定偏移 k k k, P E p o s + k PE_{pos+k} PEpos+k可以表示为 P E p o s PE_{pos} PEpos的线性变换,故该函数可以让模型轻松学习相对位置的注意,且可以让模型在训练期间使用的序列长度之外推广。
本节将自注意力层与递归层和卷积层进行比较,递归层和卷积层通常用于将一个变长序列 ( x 1 , … , x n ) (x_1, \dots, x_n) (x1,…,xn)映射到另一个等长序列 ( z 1 , … , z n ) (z_1, \dots, z_n) (z1,…,zn), x i , z i ∈ R d x_i , z_i \in \R^d xi,zi∈Rd。故考虑三个层面的对比:
每层的总计算复杂度
可并行化的计算量,由所需的最小并行操作数进行度量
网络中长程依赖性的最大路径长度
结果如上表,自注意层以常数数量的操作连接所有位置,而循环层需要 O ( n ) O(n) O(n)顺序操作,故自注意力层的并行化能力更强。在计算复杂度方面,当序列长度 n n n小于表示维度 d d d时,自注意力层比循环层更快。为了提高处理非常长序列的任务的计算性能,可以将自注意计算范围限制在输入序列中以相应输出位置为中心的大小为 r r r的邻域,这将增加最大路径长度到 O ( n / r ) O(n/r) O(n/r)。
具有核宽度 k < n k < n k<n的单个卷积层无法连接所有输入和输出位置对,需要 O ( n / k ) O(n/k) O(n/k)个卷积层或 O ( l o g k ( n ) ) O(log_k(n)) O(logk(n))个扩张卷积的堆栈,才能增加网络中任意两个位置之间最长路径的长度。卷积层的计算复杂度是循环层的 k k k倍,但是可分离卷积可以将复杂度降低到 O ( k ⋅ n ⋅ d + n ⋅ d 2 ) O(k · n · d + n · d^ 2 ) O(k⋅n⋅d+n⋅d2),然而,即使是 k = n k = n k=n,可分离卷积的复杂性也等于自注意力层和前馈层的组合。
本工作在标准的WMT 2014英德数据集上进行训练,该数据集包含大约450万个句子对,使用BPE对句子进行编码,该编码词汇表大约包含37000个token。对于英法翻译,使用了更大的WMT 2014英法数据集,包含3600万个句子对,使用32000个token的word-piece词汇表。句子对按近似序列长度进行批处理,每个训练批次包含一组句子对,其中包含大约25000个源token和25000个目标token的句子对。
本工作在一台拥有8个NVIDIA P100 gpu的机器上训练模型。对于transformer基本模型,每个训练步骤大约需要0.4秒,基础模型总共进行了10万步即12小时的训练。对于大型模型,每个训练步骤大约需要1.0秒,模型训练了30万步(3.5天)。
本工作使用超参数为 β 1 = 0.9 , β 2 = 0.98 和 ϵ = 1 0 − 9 β_1 = 0.9, β_2 = 0.98和ϵ = 10^{−9} β1=0.9,β2=0.98和ϵ=10−9的Adam优化器,在训练过程中根据下面的公式改变学习率:
l r a t e = d m o d e l − 0.5 ⋅ min ( s t e p _ n u m − 0.5 , s t e p _ n u m ⋅ w a r m u p _ s t e p s − 1.5 ) lrate=d^{-0.5}_{model}\cdot \min(step\_num^{-0.5},step\_num\cdot warmup\_steps^{-1.5}) lrate=dmodel−0.5⋅min(step_num−0.5,step_num⋅warmup_steps−1.5)
相当于在前warmup_steps个训练步骤中线性增加学习率,之后根据步数的倒数平方根成比例地减小学习率。warmup_steps = 4000。
在训练过程中使用了三种正则化方法。
Residual Dropout:在每个子层的输出归一化之前,对该子层输出上应用Dropout;此外,还在编码器和解码器堆栈中的嵌入和位置编码的和上应用Dropout。基础模型的 P d r o p = 0.1 P_{drop} = 0.1 Pdrop=0.1。
Label Smoothing:在训练过程中,使用了值为 ϵ l s = 0.1 ϵ_{ls} = 0.1 ϵls=0.1的标签平滑。这会增加模型的困惑度,因为模型的学习目标变得更不确定,但提高了准确性和BLEU分数。
结果如上表,在WMT 2014英德翻译任务中,big transformer模型比之前报告的最好模型高出2.0BLEU,建立了一个新的最先进的BLEU分数28.4。在WMT 2014英法翻译任务中,big transformer达到了41.0的BLEU分数,超过了 之前发表的所有单个模型。另外,为英法翻译任务训练的Transformer(big)模型使用的Dropout丢弃率为 P d r o p = 0.1 P_{drop} = 0.1 Pdrop=0.1。 两个任务上的训练成本都是最低的。
对于base transformer,使用一个通过平均最后5个checkpoint参数得到的单一模型,big transformer平均了最后20个checkpoint。翻译任务使用beam search,beam大小为4,长度惩罚 α = 0.6 α = 0.6 α=0.6。在推理期间将最大输出长度设置为输入长度+50,但在可能的情况下尽早终止。
为了评估Transformer不同组件的重要性,本工作以不同的方式改变了基础模型,并测量了在开发集newstest2013上英德翻译性能的变化。本实验使用了上一节中描述的beam search,但没有使用checkpoint平均。
结果如上表。在行(A)中,改变attention头的数量以及attention key和value维度,并保持计算量不变,观察到,虽然单头注意力比最佳设置差0.9BLEU,但过多的头也会导致质量下降。
在行(B)中,观察到减少key的维度会损害模型质量。这表明确定兼容性函数并不容易,比点积更复杂的兼容性函数可能是有益的。在(C)和(D)行中进一步观察到,模型越大越好,dropout在避免过拟合方面非常有用。在行(E)中,将正弦位置编码替换为可学习位置嵌入,并观察到几乎相同的结果。
为了评估Transformer是否可以泛化到其他任务,在英语短语句法分析上进行了实验。 这项任务的输出会受到强结构约束,并且输出会比输入长得多。
实验用Penn Treebank的Wall Street Journal(WSJ)部分训练了一个 d m o d e l = 1024 d_{model} = 1024 dmodel=1024的4层transformer,大约40K训练句子。还使用更高的置信度和大约有17M数据的BerkleyParser语料库进行了半监督训练。为WSJ使用了16K个token的词汇表,为半监督设置使用了32K个token的词汇表。
本实验只进行了少量实验来选择dropout、注意力和残差、学习率和beam大小,所有其他参数都与英德基础翻译模型保持不变。在推理过程中,将最大输出长度增加到输入长度+300;对于WSJ和半监督,beam大小为21、长度惩罚 α = 0.3 α = 0.3 α=0.3。
结果如上表,尽管缺乏特定任务的调优,但除了循环神经网络,产生了 比所有之前的模型更好的结果。 与RNN序列到序列模型相比,即使只在WSJ的40K句子训练集上训练,Transformer的表现也优于BerkeleyParser。
自注意力可以产生更可解释的模型,本实验检查模型的注意力分布。如下图,观察到单个注意力头不仅清楚地学会了执行不同的任务,而且许多注意力头似乎表现出与句子的句法和语义结构相关的行为。
Vaswani, A. , Shazeer, N. , Parmar, N. , Uszkoreit, J. , Jones, L. , & Gomez, A. N. , et al. (2017). Attention is all you need. arXiv.