原文开头,不是搬运 dog。All attention is all you need
Abstract 摘要
这篇文章的内容源于基于编码器-解码器架构的RNN模型,在其他人的工作中,我们可以发现注意力机制对于提升编码器-解码器架构模型的性能很重要。这篇文章提出了一个比较简单的架构–Transformer。但是本文的模型完全没有使用RNN或CNN模型,并且在两个机器翻译任务上表现良好。本文模型在其他工作上表现也良好。
Introduction 导言
在2017年的循环神经网络,LSTM和GRU是机器翻译领域中效果很好的两个模型示例,此后很多工作都在尝试利用编码器-解码器架构。
 RNN通常沿输入和输出序列的位置进行计算。用位置来体现时间的先后信息,由 t-1 时间的隐藏状态向量 
     
      
       
        
        
          h 
         
         
         
           t 
          
         
           − 
          
         
           1 
          
         
        
       
      
        h_{t-1} 
       
      
    ht−1和 t 时的输入生成 t 时的隐藏状态向量 
     
      
       
        
        
          h 
         
        
          t 
         
        
       
      
        h_t 
       
      
    ht。这将导致两个后果,第一点:导致RNN无法并行,计算性能较差。第二点:导致RNN在长文本信息中容易丢失前期信息(可以通过设置更长的隐藏状态向量 
     
      
       
        
        
          h 
         
        
          t 
         
        
       
      
        h_t 
       
      
    ht来获得更好的效果,但是也会带来新的问题,会导致内存开销较大)。最近的工作通过分解技巧和条件计算实现了对上述两个问题的显着改进。然而,上述的两个问题仍然存在。
 注意力机制被应用于翻译模型和序列模型,使得模型不考虑其中的文本距离问题。
 本文提出了 Transformer,一种完全不使用循环神经层的模型架构,而是完全依赖于注意力机制来描述输入和输出之间的全局依赖关系。Transformer 并行化度更高。
Background 相关工作
基于之前同样致力于减少循环神经层的模型,如Extended Neural GPU, ByteNet and ConvS2S,它们都使用卷积神经网络作为基本构建模块,并行计算所有输入和输出位置的隐藏表示。但是卷积神经网络对于比较长的数据难以建模,这是因为对于两个距离较远的向量,需要很多层卷积才能把这两个向量联系起来。与之相比,Transformer的注意力机制能够一次性考虑到所有向量。为了获得与卷积神经网络多输出通道相似的效果,本文提出了多头注意力。
 自注意机制是一种注意机制,它将单个序列的不同位置联系起来,以计算序列的特征。
 端到端记忆网络基于递归注意机制,而非序列对齐递归,在简单语言问题解答和语言建模任务中表现出色。
 据我们所知,Transformer是第一个完全使用自注意力机制的模型。
Model Architecture 模型架构
编码器-解码器架构目前是在序列模型中,表现较好的架构。编码器会把一个输入长度为 
     
      
       
       
         n 
        
       
      
        n 
       
      
    n的符号序列  
     
      
       
       
         X 
        
       
      
        X 
       
      
    X 
     
      
       
       
         ( 
        
        
        
          x 
         
        
          1 
         
        
       
         , 
        
       
         . 
        
       
         . 
        
       
         . 
        
       
         , 
        
        
        
          x 
         
        
          n 
         
        
       
         ) 
        
       
      
        (x_1,...,x_n) 
       
      
    (x1,...,xn)映射到一个长度为 
     
      
       
       
         n 
        
       
      
        n 
       
      
    n的向量序列  
     
      
       
       
         Z 
        
       
      
        Z 
       
      
    Z 
     
      
       
       
         ( 
        
        
        
          z 
         
        
          1 
         
        
       
         , 
        
       
         . 
        
       
         . 
        
       
         . 
        
       
         . 
        
       
         , 
        
        
        
          z 
         
        
          n 
         
        
       
         ) 
        
       
      
        (z_1,....,z_n) 
       
      
    (z1,....,zn)上,若序列 
     
      
       
       
         X 
        
       
      
        X 
       
      
    X表示一个句子,则 
     
      
       
        
        
          x 
         
        
          t 
         
        
       
      
        x_t 
       
      
    xt表示第 t 个词, 
     
      
       
        
        
          z 
         
        
          t 
         
        
       
      
        z_t 
       
      
    zt对应 
     
      
       
        
        
          x 
         
        
          t 
         
        
       
      
        x_t 
       
      
    xt的向量表示。编码器会把输出向量 
     
      
       
       
         Z 
        
       
      
        Z 
       
      
    Z传递给解码器,解码器会生成一个长度为 
     
      
       
       
         m 
        
       
      
        m 
       
      
    m向量序列 
     
      
       
       
         Y 
        
       
      
        Y 
       
      
    Y 
     
      
       
       
         ( 
        
        
        
          y 
         
        
          1 
         
        
       
         , 
        
       
         . 
        
       
         . 
        
       
         . 
        
       
         , 
        
        
        
          y 
         
        
          m 
         
        
       
         ) 
        
       
      
        (y_1,...,y_m) 
       
      
    (y1,...,ym)。解码器是一个自回归模型,会一步一步生成  
     
      
       
        
        
          y 
         
        
          t 
         
        
       
      
        y_t 
       
      
    yt,这是因为上一步的输出 
     
      
       
        
        
          y 
         
         
         
           t 
          
         
           − 
          
         
           1 
          
         
        
       
      
        y_{t-1} 
       
      
    yt−1是当前步的输入。Transformer 使用编码器-解码器架构,使用堆叠的自注意力层和全连接层,完全连接编码器和解码器层。结构如下图所示。
 
Encoder and Decoder Stacks 编解码器
Encoder 编码器
Transformer 的编码器是一个 
     
      
       
       
         N 
        
       
         = 
        
       
         6 
        
       
      
        N = 6 
       
      
    N=6的完全相同的块的堆叠。每一个块有两个子层,第一个子层是多头自注意力层,第二个子层是一个简单的MLP(多层感知机),叫做前向反馈网络 (positionwise fully connected feed-forward network)。每一个子层都是用了残差链接和 层归一化(不是批归一化)。可以用以下公式表示
  
     
      
       
       
         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))
 为了便于这些残差连接,模型中的所有子层以及嵌入层都会产生维度 d 为512的输出。
 LayerNorm 是什么
 以二维输入为例,形状为 (batch_size,features)
 ● batchnorm 是对每一列即每一个 feature 向量(batch_size,1)做归一化。
 ● layernorm 是对每一行即每一个 样本向量(1,features)做归一化。
 对于三维输入,原理如图所示
 
batchnorm 表现效果不佳的原因是:每个样本的 len 不一样,在计算均值和方差时会产生较大的抖动
 layernorm 不需要考虑全局的均值和方差,只考虑当前样本的均值和方差
 总结
 编码器只有两个超参数 :N 个块,输出维度 d
Decoder 解码器
Transformer 的解码器是一个 N = 6 N = 6 N=6的完全相同的块的堆叠。与编码器相比,解码器的一个块多了一个层–掩码多头自注意力。与编码器类似,我们在每个子层周围使用残差连接,然后进行层规范化(layernorm)。掩码层的存在确保了位置 i 的预测只能依赖于小于位置的已知输出。
Attention 注意力层
注意函数可以描述为一个map(dict),将查询和一组键值对映射到输出,其中查询、键、值和输出都是向量。输出是值的加权和,权重是由键和查询的相似度计算得到的。
Scaled Dot-Product Attention 放缩点积注意力函数
放缩点积注意力函数由维度为 
      
       
        
         
         
           d 
          
         
           k 
          
         
        
       
         d_k 
        
       
     dk的查询、键和维度为 
      
       
        
         
         
           d 
          
         
           v 
          
         
        
       
         d_v 
        
       
     dv的值组成。具体计算是对于每一个查询和键做内积再除以 
     
      
       
        
         
         
           d 
          
         
           k 
          
         
        
       
      
        \sqrt{d_k} 
       
      
    dk,最后经过 softmax 来得到相似度即权重,再与值相乘得到输出。
 实际上,我们同时对一组查询进行注意力函数的计算,这些查询可以连接成一个矩阵 
     
      
       
       
         Q 
        
       
      
        Q 
       
      
    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
 流程如下图所示
 
当  
     
      
       
        
        
          d 
         
        
          k 
         
        
       
      
        d_k 
       
      
    dk 值较小时,两种机制的表现相似,当  
     
      
       
        
        
          d 
         
        
          k 
         
        
       
      
        d_k 
       
      
    dk 值较大时,加性注意优于点积注意。这是因为对于较大的 
     
      
       
        
        
          d 
         
        
          k 
         
        
       
      
        d_k 
       
      
    dk值,点积的大小会变大,从而将softmax函数推入具有极小梯度的区域。为了抵消这个影响,我们将点积乘以 
     
      
       
        
        
          1 
         
         
          
          
            d 
           
          
            k 
           
          
         
        
       
      
        \frac{1}{\sqrt{d_k}} 
       
      
    dk1。
 结合下图理解掩码(mask)的作用,点积后对于时间步 t 后的值,都不应该知道,所以替换成一个特别大的负数,从而使得这些值经过softmax后
Mutil-Head Attention
相对于单个注意力函数,把查询,键和值投影 
      
       
        
        
          h 
         
        
       
         h 
        
       
     h次到低维中,再做 
     
      
       
       
         h 
        
       
      
        h 
       
      
    h次注意力函数得到 
     
      
       
       
         h 
        
       
      
        h 
       
      
    h个输出,将这些输出连接起来,效果会更好。
 结合下图理解整个流程
 
输入的矩阵 
     
      
       
       
         V 
        
       
         , 
        
       
         K 
        
       
         , 
        
       
         Q 
        
       
      
        V,K,Q 
       
      
    V,K,Q,经过线性层(Linear)被投影到较低的维度,再做缩放点积注意力得到输出拼接起来,最后结果一个线性层做投影。如公式表示
  
     
      
       
       
         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 
         
        
       
         , 
        
        
        
          W 
         
        
          i 
         
        
          K 
         
        
       
         , 
        
        
        
          W 
         
        
          i 
         
        
          v 
         
        
       
      
        W_i^Q , W_i^K,W_i^v 
       
      
    WiQ,WiK,Wiv是可以学习的矩阵,用来投影到低维。在本文,使用的是  
     
      
       
       
         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。由于每个头部的维数降低,因此总计算成本与全维的单头部关注相似。
Application of Attention in our Model 如何使用注意力机制
在 Transformer 中,多头注意力有三种情况:
 ● 在编码器-解码器沟通层中,查询来自前一个解码器层的输出,而键和值则来自编码器的输出。这使得解码器中的每个位置都能关注输入序列中的所有位置。
 ● 编码器部分包含多头自注意力层。在多头自注意力层中,所有的键、值和查询都来自同一个输入,输出是值的加权和。
 ● 解码器部分的掩码多头自注意力层使得解码器中的每个位置的输出只关注包括该位置在内的之前位置向量。
Position-wise Feed-Forward Networks 位置前馈网络
全连接的位置前馈网络,该网络分别对每个位置进行相同的处理。这包括两个线性变换,中间有一个 ReLU 激活函数,实际上就是一个多层感知机
  
     
      
       
       
         F 
        
       
         F 
        
       
         N 
        
       
         ( 
        
       
         x 
        
       
         ) 
        
       
         = 
        
       
         max 
        
       
          
        
       
         ( 
        
       
         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
 position 指的是输入序列中的每一个词,对每个词都作用同一个 MLP。记过第一个全连接层的输出的向量是 2048 维度的,加过第二个全连接层的输出是 512 维度的。
Embeddings and Softmax
与其他的序列模型相似,本文也是用了 embedding 层来将输入每一个的词元(token)转换为维度为 d m o d e l d_{model} dmodel的向量。编码器,解码器的embedding 和softmax 前的线性层都是用相同的权重矩阵,这样训练会简单点。同时对于权重乘了 d m o d e l \sqrt{d_{model}} dmodel,这是因为在学习embedding时 L2 范数会变小,乘 d m o d e l \sqrt{d_{model}} dmodel可以避免完全受位置编码(position encoding)影响。为什么乘 d m o d e l \sqrt{d_{model}} dmodel,可以参考文章为什么要乘 sqrt d
Position Encoding 位置编码
注意力模型是没有时序信息的,这在处理时序信息时会产生问题,所以引入位置编码。本文中的位置编码采用如下公式
  
     
      
       
       
         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π到10000·2π的几何级数,这意味着不同维度的正弦波的周期(即波长)按照一定的比例递增,从而使得模型能够捕获不同尺度的位置信息。如图所示
 
因为任意两个位置的差值可以被简单地表示为一个线性变换的结果,所以这种正弦波的位置编码方式有助于模型更容易地学会如何处理输入序列中的相对位置关系。与通过神经网路学习添加位置信息的方式相比两者结果是一致的,但是使用正弦波可以使得模型对未遇到过的更长的序列时表现更好。
Why Self-Attention 为什么使用自注意力机制
总结来说,通过上述表格来比较得出自注意力机制的优点。有三个指标:1.计算复杂度 2.顺序计算 3.最长信息距离传输。这三个指标中,计算复杂度越小越好,顺序计算能力越小越好,最长信息距离越小越好。
 从表格中看不同层在这三个指标上的表现 :
- 计算复杂度:自注意力层在计算复杂度上比循环层更优,尤其当序列长度 n n n 小于表示的维度 d d d时,自注意力层的效率更高。
- 并行化能力:自注意力层可以并行化计算,而循环层需要 O ( n ) O(n) O(n) 的顺序操作,因此在计算并行化上,自注意力更具优势。
- 长距离依赖的学习能力:自注意力层在输入和输出位置之间的路径长度是常数,而循环层和卷积层的路径长度较长,使得学习长距离依赖关系更加困难。
 使用自注意力层的模型可能更具解释性,因为注意力头可以学习到与句法和语义结构相关的行为。
Training 训练
训练过程中的细节。
Training Data and Batching
本文在标准的WMT 2014 英语-德语数据集上进行训练,该数据集由大约450万句对组成。句子使用bpe对词进行编码,这样使得语料集更小,该编码具有大约37000个标记的共享源-目标词汇表。对于英语-法语,我们使用了更大的WMT 2014英语-法语数据集,该数据集由36M个句子组成,并将token拆分为32000个词片词汇。句子对按近似序列长度进行批处理。每个训练批包含一组句子对,其中包含大约25000个源标记和25000个目标标记。
Hardware and Schedule
我们在一台配备 8 个英伟达 P100 GPU 的机器上训练模型。对于我们的基础模型,使用本文所述的超参数,每个训练步骤耗时约 0.4 秒。我们总共训练了 100,000 步或 12 个小时的基础模型。对于我们的大型模型(如表 3 底行所述),每步训练时间为 1.0 秒。大型模型的训练步长为 300,000 步。
Optimizer 优化器
使用了Adam优化器(β1 = 0.9,β2 = 0.98,ε = 10^-9)。根据以下公式在训练过程中变化学习率:
  
     
      
       
       
         lrate 
        
       
         = 
        
        
        
          d 
         
        
          model 
         
         
         
           − 
          
         
           0.5 
          
         
        
       
         ⋅ 
        
       
         min 
        
       
          
        
       
         ( 
        
        
        
          step_num 
         
         
         
           − 
          
         
           0.5 
          
         
        
       
         , 
        
       
         step_num 
        
       
         ⋅ 
        
        
        
          warmup_steps 
         
         
         
           − 
          
         
           1.5 
          
         
        
       
         ) 
        
       
      
        \text{lrate} = d_{\text{model}}^{-0.5} \cdot \min(\text{step\_num}^{-0.5}, \text{step\_num} \cdot \text{warmup\_steps}^{-1.5}) 
       
      
    lrate=dmodel−0.5⋅min(step_num−0.5,step_num⋅warmup_steps−1.5)
 这对应于在首次  
     
      
       
       
         warmup_steps 
        
       
      
        \text{warmup\_steps} 
       
      
    warmup_steps 训练步骤中线性增加学习率,之后按步骤编号的平方根的倒数成比例减少。我们使用了  
     
      
       
       
         warmup_steps 
        
       
         = 
        
       
         4000 
        
       
      
        \text{warmup\_steps} = 4000 
       
      
    warmup_steps=4000。
Regularization 正则化
使用了三种正则化方法
 Residual Dropout 对每一个子层的输出进入到 softmax 之前使用 dropout ,并且对embedding 和 position encoding 的和上也使用了 dropout,  
     
      
       
        
        
          P 
         
         
         
           d 
          
         
           r 
          
         
           o 
          
         
           p 
          
         
           o 
          
         
           u 
          
         
           t 
          
         
        
       
         = 
        
       
         0.1 
        
       
      
        P_{dropout} = 0.1 
       
      
    Pdropout=0.1
 Label Smoothing 在训练过程中,我们使用了εls = 0.1 的标签平滑值[ 36 ]。这样做会增加模型的不确定性,从而降低复杂度,但却提高了准确度和 BLEU 分数。
Results 结果
效果还不错,不具体将结果了,大家可以看原文。All attention is all you need
Conclusion 结论
本文提出了用于机器翻译的完全依赖注意力机制的Transformer模型,取代了基于编码器-解码器架构的使用多头自注意力机制的RNN模型。
 对于翻译任务,Transformer比其他架构(RNN和CNN)训练更加简单,时间更短,效果更好。
 本文认为Transformer在其他领域如图片,视频等依然有很好的效果,做出较大的贡献。



















