作为和rnn、cnn一样甚至地位更高的模型架构,Transformer可谓是创造了一个全新的时代,为什么要使用attention,cnn和rnn究竟有哪些不足,为什么attention能够在语言任务上有如此优良的表现,本篇文章会给出非常细节的回答,相信会给查缺补漏的朋友一些新的思想和启发~
Paper: https://proceedings.neurips.cc/paper/2017/file/3f5ee243547dee91fbd053c1c4a845aa-Paper.pdf
Code: https://github.com/tensorflow/tensor2tensor
本文提出了一个新颖简单的网络架构——Transformer,完全基于注意力机制,不需要递归和卷积。在机器翻译任务上进行实验,该模型性能好,并行性高,所需训练时长小。
循环神经网络如LSTM、GRU是序列模型中最先进的方法,但是这种模型通常沿着输入和输出位置进行计算,将位置进行对齐,这种固有的顺序性阻碍了训练的并行化。
attention机制已经成为很多序列模型、转录模型中重要组成,用于解决远程依赖问题(编码器的知识如何有效传给解码器),但是除了少数情况,attention机制还是和循环神经网络结合使用。
本文提出了Transformer架构,完全依赖attention机制,并且显著提高了并行度。
为了减少序列计算,一些方法使用卷积神经网络对作为基本构造块,计算输入输出的隐向量表示,但是将两个任意的输入或输出的token关联起来所需要的时间会随着距离的增大而增加,这会导致学习远距离位置关系变得困难。Transformer通过attention机制固定了操作次数,并采用多头注意力机制抵消有效分辨率的问题。
在卷积中,两个位置很远的token需要卷积很多层才能够联系到一起,但是自注意力机制可以直接联系到一起。这里的有效分辨率可以理解为模式,卷积有多通道的概念,可以学习到图片的多种模式,多头注意力机制有异曲同工之妙。
自注意力机制将单个序列的不同位置联系到一起,以计算序列的表示,并且已经在阅读理解、摘要等任务上成功应用。
当时还有一个端到端的记忆网络,基于循环注意力机制,在简单语言问答和语言建模任务上表现良好。
Transformer架构是目前所知第一个完全依赖自注意力机制的转录模型。
当前有竞争力的模型大多都是encoder-decoder架构,encoder输入长度为n的序列 ( x 1 , . . . , x n ) (x_1,...,x_n) (x1,...,xn),输出长度为n的表征 z = ( z 1 , . . . , z n ) \mathbf{z}=(z_1,...,z_n) z=(z1,...,zn),其中 z i z_i zi是具有固定长度的隐向量,接着将encoder的输出输入到decoder中,生成最终长度为m的序列 ( y 1 , . . . , y m ) (y_1,...,y_m) (y1,...,ym),decoder中模型是自回归的,即之前的输出作为下一时刻的输入。Transformer的架构如下图所示:
编码器由6个相同的块堆叠而成,每个块有两个子层,第一个是多头自注意力机制,第二个是MLP,两个子层的输出都连接残差,并进行层归一化,即 L a y e r N o r m ( x + S u b l a y e r ( x ) ) \mathrm{LayerNorm}(x+\mathrm{Sublayer}(x)) LayerNorm(x+Sublayer(x)),向量维度都设置为512。
解码器层同样由6个相同的块堆叠而成,除了编码器中的两个子层,解码器还插入了第三个子层,该层对编码器的输出执行多头注意力机制。和编码器相同,每个子层的输出都连接残差,并进行层归一化。此外,作者还修改了解码器最底层的自注意力层,防止后面的输出信息被泄露。
这里有必要解释一下为什么使用LayerNorm而不是BatchNorm,在时序样本中,每个样本的长度是不一样的,因此会设定一个最大样本长度,不足的部分填充为0。二者主要区别在于均值和方差,如果样本长度变化比较大,每次BatchNorm的均值和方差抖动会很厉害,对于新到来的很长的或者很短的序列不适用,但是LayerNorm是每个样本自己的均值和方差,更稳定。详细可以看下面的图片进行理解。
注意力函数是将一个query和一些key-value对映射成一个输出的函数。输出可以看做是values的加权和,权重可以理解为由query和value之间的相似度计算得到。
本文的attention称作缩放点积注意力(Scaled Dot-Product Attention),输入包括queries、keys和values,维度分别为 d k d_k dk、 d k d_k dk和 d v d_v dv。计算完queries和keys的点积后除以 d k \sqrt{d_k} dk,再输入到softmax函数中获取权重,计算公式如下:
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 \mathrm{Attention}(Q,K,V)=\mathrm{softmax}(\frac{QK^T}{\sqrt{d_k}})V Attention(Q,K,V)=softmax(dkQKT)V
常见的两种注意力机制分别为加性注意力和点积注意力。本文的注意力是在点积注意力基础上加上放缩。点积注意力实践中更快、更省空间,因为使用了高度优化的矩阵乘法代码。但是加性注意力在较大的 d k d_k dk下表现优于点积注意力,因此本文用了放缩,防止softmax结果两极化严重,导致梯度下降变慢。注意力计算过程如下图所示:
作者发现将单独的 d m o d e l d_{\mathrm{model}} dmodel维度的keys、values和queries进行h次投影会更有效,对投影的各个值并行执行注意力函数,产生 d v d_v dv维输出,将这h个输出连接到一起再投影可以得到 d m o d e l d_{\mathrm{model}} dmodel维的输出,如上图所示。多头注意力机制的优势在于可以让模型同时关注不同位置不同表示的子空间信息。过程如下所示:
MultiHead ( Q , K , V ) = Concat ( head 1 , … , head h ) W O where head = Attention ( Q W i Q , K W i K , V W i V ) \begin{aligned} \operatorname{MultiHead}(Q, K, V) & =\operatorname{Concat}\left(\operatorname{head}_{1}, \ldots, \text { head }_{\mathrm{h}}\right) W^{O} \\ \text { where head } & =\operatorname{Attention}\left(Q W_{i}^{Q}, K W_{i}^{K}, V W_{i}^{V}\right) \end{aligned} MultiHead(Q,K,V) where head =Concat(head1,…, head h)WO=Attention(QWiQ,KWiK,VWiV)
其中投影矩阵 W i Q ∈ R d m o d e l × d k W^Q_i \in \mathbb{R}^{d_{\mathrm{model}} \times d_k} WiQ∈Rdmodel×dk, W i K ∈ R d m o d e l × d k W^K_i \in \mathbb{R}^{d_{\mathrm{model}} \times d_k} WiK∈Rdmodel×dk, W i V ∈ R d m o d e l × d v W^V_i \in \mathbb{R}^{d_{\mathrm{model}} \times d_v} WiV∈Rdmodel×dv, W O ∈ R h d v × d m o d e l W^O \in \mathbb{R}^{hd_v \times d_{\mathrm{model}}} WO∈Rhdv×dmodel。本文中作者设置h为8,因此 d k = d v = d m o d e l / h = 64 d_k=d_v=d_{\mathrm{model}}/h=64 dk=dv=dmodel/h=64。
本文在三个地方应用了多头注意力机制:
编码器和解码器每一个层中都包含一个全连接层,独立作用在每个token上,它包括两个线性变换和一个relu,如下:
F F N ( x ) = m a x ( 0 , x W 1 + b 1 ) W 2 + b 2 \mathrm{FFN}(x)=\mathrm{max}(0,xW_1+b_1)W_2+b2 FFN(x)=max(0,xW1+b1)W2+b2
也可以理解为kernel大小为1的卷积层。
MLP的理解可以如上图上面部分所示,就是对每个token的输出,映射到高维再映射回去,下面部分是对attention和RNN整体的一个对比,二者其实都是先处理序列信息再进行下一步的映射,只不过Transformer可以将整个序列的信息并行进行计算,而RNN只能对前面的序列信息串行计算,效率和效果上都大打折扣。
输入序列中的token通过可学习的embedding转换为维度 d m o d e l d_{\mathrm{model}} dmodel的向量,此外还通过线性变换(映射到词表)和softmax函数将解码器的输出转换为预测下一个token的概率。需要注意的是,embedding层中需要乘以 d m o d e l \sqrt{d_{\mathrm{model}}} dmodel,以保证之后的位置信息不会造成太大波动。
attention中只是通过相似度计算加权的values,其中不包含时序信息,即打乱序列token顺序,计算结果也保持不变,因此需要注入位置信息。作者采用不同频率的正弦和余弦函数:
P E ( p o s , 2 i ) = sin ( p o s / 1000 0 2 i / d model ) P E ( p o s , 2 i + 1 ) = cos ( p o s / 1000 0 2 i / d model ) \begin{aligned} P E_{(p o s, 2 i)} & =\sin \left(p o s / 10000^{2 i / d_{\text {model }}}\right) \\ P E_{(p o s, 2 i+1)} & =\cos \left(p o s / 10000^{2 i / d_{\text {model }}}\right) \end{aligned} PE(pos,2i)PE(pos,2i+1)=sin(pos/100002i/dmodel )=cos(pos/100002i/dmodel )
pos是位置,i是维度。位置编码和embedding有相同的维度,可以将二者相加。选择正弦函数是因为其可以允许模型推断出比训练期间遇到的序列长度更长的序列长度。
传统的循环层和卷积层通常将一个可变序列映射到等长的序列,而使用self-attention,有三点优势:
如上表所示,自注意力层可以同时执行序列操作,而循环层需要 O ( n ) O(n) O(n)顺序操作。从计算复杂度角度,当n比维度d小时,自注意力层比循环层更快,为了提高长序列任务的计算性能,受限的自注意力可以让输入仅考虑中心大小为r的邻域,将最大路径长度增加到 O ( n / r ) O(n/r) O(n/r)。
对于卷积层,如果内核宽度 k < n k
最后,attention机制还附带额外的好处,可以产生更多可解释的模型,并且可以表现出与句子的句法和语义结构相关的行为。
在实际中,n和d的大小其实是差不多的,因此三个算法的计算复杂度可以认为是相同或者在一个量级的,但是attention在计算并行度上和远距离依赖上优势明显。
作者在450万条数据对的英文-德文和3600万条数据对的英文-法文数据集上进行实验。
实验部分在8卡P100上进行。
优化器部分采用Adam,学习率采用动态学习率。
作者采用了三种正则化方法。
实验在英德翻译任务和英法翻译任务上都表现优越,并且训练成本大大降低。下表总结了实验结果。
为了评估Transformer中不同组件的重要性,作者通过修改超参数来测试模型性能的变化,结果如下表所示。
根据上表的B可以观察到,减少注意力key的维度 d k d_k dk会损害模型的质量,在C和D中进一步观察,发现模型越大越好,并且dropout对避免过拟合有很大帮助。在E中用学习的位置embedding代替正弦位置编码,得到几乎相同的结果。
本文提出Transformer模型,是一个只使用注意力机制的转录模型,将以往的encoder-decoder架构中的循环层换为了多头注意力机制。在机器翻译任务上,Transformer训练速度快,效果好。因此作者希望将Transformer应用到其他任务上,通过研究局部的、受限的自注意机制,来有效处理图像、音频、视频等输入输出任务。
再次回顾NLP领域的经典,LLM的基石,新时代的缔造者——Transformer,收获良多。本篇文章受制于篇幅,因此很多细节的地方并没有给出解释,甚至于模型设计的灵感与思路也没能以一个完整的故事形式呈现,但是这并不妨碍它对于NLP乃至整个AI领域做出的杰出贡献。这一次阅读是结合了沐神的讲解视频,使我对Transformer架构有了更深的理解。沐神把文章中很多没能解释的点或者解释不清的地方都做了清晰的讲解,包括为什么使用LayerNorm,Q、K、V的用法和含义,attention层的作用,这些内容都在我脑海中留下了很深的影响,过去的一年我都在试图掌握Transformer这块积木的搭建方法,而忽略了这个积木本身的奥秘,相信通过这次的精读,能够为我后序的科研提供崭新的理解和思路。