Abstract
序列转换任务(如机器翻译)通常使用基于卷积或循环神经网络组成的encoder-decoder模型,当时最好的模型采用attention机制连接encoder和decoder。
提出一个简单的Transformer架构,完全依赖于attention机制。实验证明该模型取得良好的性能,并且还有容易并行化(parallelizable)、训练时间短等优点。
Introduction
在序列建模及转换问题中,通常使用RNN,LSTM等模型。RNN的一个突出问题是由于它的时序特性,训练时无法并行化,这在处理长序列时尤为严重。有一些工作试图通过factorization tricks 或 conditional computation改善它的运算效率,但这并没有触及它的顺序计算本质。
Attention机制在序列建模中已经广泛应用,但大多数时候还是与RNN共同使用。
本文提出Transformer,一种只依赖于attention机制从而避免使用循环网络的模型,用于学习输入和输出之间的全局依赖关系。
Model Architecture
encoder-decoder结构:encoder将输入序列 ( x 1 , . . . , x n ) (x_1,...,x_n) (x1,...,xn)映射为连续的表示序列 z = ( z 1 , . . . , z n ) z=(z_1,...,z_n) z=(z1,...,zn),decoder接收 z z z,每次生成一个symbol,组成输出序列 ( y 1 , . . . , y m ) (y_1,...,y_m) (y1,...,ym)。这个模型是自回归的,即生成每一步的symbol时需要上一步的输出作为新的输入。
Transformer遵循这个结构,其encoder和decoder都是使用多层self-attention,point-wise,fully connected layers进行构建。
Encoder and Decoder Stacks
Encoder
由 N = 6 N=6 N=6个相同的层组成,每层包括两个子层:第一层是multi-head self-attention机制,第二层是一个简单的position-wise fully connected feed-forward网络。两个子层均添加残差连接,并后跟一个layer normalization层,即每个子层的输出是: 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))。为了使用残差连接,每个子层(包括embedding层)的输出都具有相同的维度 d m o d e l = 512 d_{model}=512 dmodel=512。
Decoder
同样由 N = 6 N=6 N=6个相同的层组成。每层中除了encoder中相同的连个子层外,还添加了一个作用于encoder输出的multi-head attention层。每个子层同样带有残差连接和layer normalization。decoder的self-attention改为masked self-attention,防止计算时加入后面还没出现的位置,确保位置i的预测只依赖于i之前已知位置的输出。
Attention
Attention函数将一个query和一组key-value对映射到一个输出,其中query key value都是向量。输出是对value求加权和,权值(attention weight)是将query与每个value对应的key通过匹配性函数(compatibility function)计算得到。
Scaled Dot-Product Attention
输入querys、keys的维度为 d k d_k dk,values的维度为 d v d_v dv。将query与每个key计算dot product attention,再除以 d k \sqrt{d_k} dk,最后使用softmax函数获取每个value的权重。
可以通过矩阵运算在多个query和key-value对上同时计算attntion。其中,query的个数与key(value)的个数不一定相同。将所有queries、keys、values向量分别拼在一起,用矩阵Q、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
上述过程包括两次矩阵乘法,示意图如下:
上图中有n个query,m个key和value,每个query和key向量的维度为 d k d_k dk,每个value的维度为 d v d_v dv。第三个 n × m n\times m n×m矩阵即 Q K T QK^T QKT,其中每一行表示一个query(Q中的一行)对所有m个key求内积的结果。
有两种常见的attention(dot-product attention和additive attention),理论上复杂度差不多,但实际应用时由于可以使用矩阵乘法加速,所以采用dot-product attention。
作者还注意到,当 d k d_k dk比较小时,两种attention表现差不多,但 d k d_k dk比较大时additive attention表现更好。作者认为原因是当维度 d k d_k dk太大时,点积运算的结果太大,再经过softmax运算后导致梯度特别小。因此使用 1 d k \frac{1}{\sqrt{d_k}} dk1进行缩放。
Multi-Head Attention
上面的dot-product attention计算直接使用Q、K、V一次性计算出结果,不包含任何可学习的参数。假设self-attention中,每个query、key、value向量均为 d m o d e l d_{model} dmodel(即Q、K、V矩阵的维度分别为 n × d m o d e l , m × d m o d e l , m × d m o d e l n\times d_{model}, m\times d_{model}, m\times d_{model} n×dmodel,m×dmodel,m×dmodel)。
Multi-head attention的过程是:首先将原始的Q、K、V矩阵通过分别不同的线性层(可学习)投影到更低维度 d k 、 d k 、 和 d v d_k、d_k、和d_v dk、dk、和dv(投影h次),再用h组投影后的结果分别计算attention,每组得到一个结果矩阵,然后这h个矩阵concat在一起,再经过一次线性投影,得到本层attention最终的输出。
Multi-head attention使模型可以学习h个不同的投影函数,从而同时在不同的表示空间中进行attention计算。这类似于卷积网络中的多卷积核。
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,...,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_i^Q,KW_i^K,VW_i^V) where:headi=Attention(QWiQ,KWiK,VWiV)
其中,参数矩阵 W i Q ∈ R d m o d e l × d k , W i K ∈ R d m o d e l × d k , W i V ∈ R d m o d e l × d v , W O ∈ R h d v × d m o d e l W_i^Q\in \mathbb{R}^{d_{model}\times d_k},W_i^K\in \mathbb{R}^{d_{model}\times d_k},W_i^V\in \mathbb{R}^{d_{model}\times d_v}, W^O\in \mathbb{R}^{hd_v\times d_{model}} WiQ∈Rdmodel×dk,WiK∈Rdmodel×dk,WiV∈Rdmodel×dv,WO∈Rhdv×dmodel原文中作者使用 h = 8 h=8 h=8,每个head中 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。由于每个head计算dot-product前对QKV进行了降维,总的运算量与不进行降维的单头注意力差不多。
Applications of Attention in Transformer
在Transformer中multi-head attention有三种用途:
- encoder-decoder attention中,query来自上一个decoder层,key和value来自encoder层输出。这使得decoder中的每个位置可以关注输入序列中的所有位置,类似于seq2seq中的attention。
- encoder的self-attention中,所有query、key、value都来自同一个地方,即上一个encoder层的输出。这使得encoder中的每个位置可以关注上一个encoder层的所有位置。
- decoder的self-attention中,应该允许decoder中的每个位置可以关注decoder中这个位置及之前的所有位置,这是为了保持自回归性质,即下一个输入依赖于上一个输出。这一点通过将softmax的输入中不应该计算的位置mask掉(设置为 − ∞ -\infin −∞ ,则softmax后为0)实现(masked self-attention)。
Position-wise Feed-Forward Networks
每个attention子层后的FFN层是分别作用在每个位置上的,并且同一个子层中的FFN权重共享。FFN层具体包括两个线性变换和一个ReLU激活函数。
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的卷积层实现。FFN层的输入、输出维度为 d m o d e l = 512 d_{model}=512 dmodel=512,隐藏层 d f f = 2048 d_{ff}=2048 dff=2048。
Embeddings and Softmax
使用预学习的embedding将输入和输出token转换为 d m o d e l d_{model} dmodel维向量。
Positional Encoding
由于没有使用卷积和循环网络,必须通过某种方式向模型中添加序列中每个token的位置信息。
在encoder和decoder的input embedding中添加位置编码(positional encoding)来实现这一点。位置编码的维度与input embedding相同,为 d m o d e l d_{model} dmodel,直接加在embedding上。
位置编码的选择:通过计算不同频率的sin和cos函数:
P E p o s , 2 i = s i n ( p o s / 100 0 2 i / d m o d e l ) PE_{pos,2i}=sin(pos/1000^{2i/d_{model}}) PEpos,2i=sin(pos/10002i/dmodel)
P E p o s , 2 i + 1 = c o s ( p o s / 100 0 2 i / d m o d e l ) PE_{pos,2i+1}=cos(pos/1000^{2i/d_{model}}) PEpos,2i+1=cos(pos/10002i/dmodel)
其中 p o s pos pos表示位置, i i i表示维度。位置编码的每个维度对应一条正弦曲线,波长从 2 π 2\pi 2π到 1000 1000 1000几何增长。这种正弦位置编码让模型可以学习位置的相对关系,因为对于固定的
还可以使用可学习的位置编码,作者通过实验发现二者性能相近,作者使用正弦位置编码是因为它允许模型遇到比训练时更长的序列时依然能进行推断。