今天来看一下Transformer模型,由Google团队提出,论文名为《Attention Is All You Need》。论文地址。
正如标题所说的,注意力是你所需要的一切,该模型摒弃了传统的RNN和CNN结构,网络结构几乎由Attention机制构成,该论文的亮点在于提出了Multi-head attention机制,其又包含了self-attention,接下来我们将慢慢介绍该模型的原理。
正如文中提到大多数的序列传导模型都含有encoder-decoder结构,Transformer的encoder是将一段表征序列 ( x 1 , ⋯ , x n ) (x_1,\cdots,x_n) (x1,⋯,xn)映射为另一种连续表示的序列 ( z 1 , ⋯ , z n ) (z_1,\cdots,z_n) (z1,⋯,zn),即encoder的输出信息;而decoder是将encoder输出和decoder前一步的输出自回归的共同生成序列 ( y 1 , ⋯ , y m ) (y_1,\cdots,y_m) (y1,⋯,ym)。举个例子,现在有一个机器翻译任务,首先将句子embedding为高维向量,输入encoder中,其输出随后输入decoder进行解码得到最终翻译结果,如下图所示。
需要注意的是,Transformer的输出 y i y_i yi是一次一次自回归的生成的,也就是每一次输出都需要调用最后一层encoder的输出序列。这里不像多层RNN隐层的并行传递,Transformer是串行的。如下图所示。
好了,接下来该介绍encoder和decoder的神秘面纱了,如下图所示。
在读论文时第一眼看这个架构图,一开始是比较懵的,这到底做了些啥操作。后来看了李沐老师讲解的Transformer才有了一定的理解。
这里说到作者实验用到了6层的encoder,这里是为了学到更多的语义信息。并且每层encoder都包含两个子层,分别是多头注意力机制Multi-head attention和前馈神经网络FFN。当然了,作者对两个子层的输出都做了residual连接和Layer normalization(LN),加了残差连接是为了网络能搭的更深,并且容易训练,防止梯度消失;而LN完全是针对每一个样本自身的特征缩放,能将每个词都归一为相同空间的语义信息。BN也是一种常见的特征缩放方法,常用于CNN,不适用于NLP任务,因为其对所有batch的同一个特征做缩放,在图像中是非常友好的,而NLP中每一个sequence的长度是不一样的,所以在同一个batch中越长的语句得不到充分的缩放表示。
同样的,作者实验用到了6层decoder,不同于encoder,这里作者还设置了mask的multi-head attention,其原因在于在解码时,模型是看不到整条句子的,因此,必须在当前时刻掩码掉后面的词,才能做到正确训练和有效预测。
谈到注意力机制,像我们人一样,看到一幅图片,我们会关注其强烈的表征现象,能让我们快速了解新事物的信息,如下图所示。特别在处理NLP任务中,长距离的记忆能力是一个难题,引入注意力机制,关注更重要的词,可以缓解这一现象。
在Transformer中,每个单词embedding为三个不同的向量,分别是 Q u e r y Query Query向量 Q Q Q、 K e y Key Key向量 K K K和 V a l u e Value Value向量 V V V。具体来说,对于一个句子,只需要将其输入到三个linear层,通过学习三个 W W W参数就能得到不一样的 Q 、 K 、 V Q、K、V Q、K、V。至于为什么说 Q 、 K 、 V Q、K、V Q、K、V要不一样,其实一样也可以,但是这里为了增强数据的表达能力,保证在 Q K T QK^T QKT矩阵内积时可以得到不同的空间投影,提高模型泛化能力。
生成的 Q 、 K 、 V Q、K、V Q、K、V矩阵后便可以进行attention计算了,如下图所示
假设有三个矩阵 Q 、 K 、 V Q、K、V Q、K、V,维度分别为 ( d q , d m o d e l ) 、 ( d k , d m o d e l ) 、 ( d v , d m o d e l ) (d_q, d_{model})、(d_k, d_{model})、(d_v, d_{model}) (dq,dmodel)、(dk,dmodel)、(dv,dmodel),其中 q = k = v q=k=v q=k=v。
多头
,类似cv中的channel数量,能学习更多维度信息。多头注意力机制中包含了Scaled Dot-product Attention,也是self-attention。余弦相似度
,如果两者相似度较高,则赋予较大的值来反应两者的关系,反之如果是正交的,内积为0,则它们就没有相似性,这里输出的attention score矩阵维度是shape: ( d q , d k ) (d_q, d_k) (dq,dk)。Scale缩放公式:
Attention ( Q 、 K 、 V ) = softmax ( Q K T ( d k ) ) V \begin{aligned} \text{Attention}(Q、K、V)=\text{softmax}(\frac{QK^T}{\sqrt(d_k)})V \end{aligned} Attention(Q、K、V)=softmax((dk)QKT)V
Multi-head公式:
Multihead ( Q 、 K 、 V ) = Concat ( head i , ⋯ , head h ) W O where head i = Attention ( Q W i Q , Q W i K , Q W i V ) \begin{aligned} \text{Multihead}(Q、K、V)=\text{Concat}(\text{head}_i,\cdots,\text{head}_h)W^O\\ \text{where} \text{ } \text{head}_i=\text{Attention}(QW_{i}^{Q},QW_{i}^{K},QW_{i}^{V}) \end{aligned} Multihead(Q、K、V)=Concat(headi,⋯,headh)WOwhere headi=Attention(QWiQ,QWiK,QWiV)
上述的操作执行完后,便可以通过多个头的concat将矩阵拼接,随后通过linear层降维,完成Multi-head attention的过程。
值得注意的是多头数量必须可被 d m o d e l d_{model} dmodel整除。这个很好理解,在CNN中,我们经常将feature map的width和height升维后,会把channel数降低,学到更深的信息一个道理。
除了注意子层外,encoder和decoder中的每个层都包含一个完全连接的前馈网络,它分别和相同地应用于每个位置。这由两个线性变换组成,中间有一个ReLU激活。换句话说就是MLP模型。公式如下所示:
FFN ( x ) = max ( 0 , x W 1 + b 1 ) W 2 + b 2 \begin{aligned} \text{FFN}(x) = \text{max}(0, xW_1 + b_1)W_2 + b_2 \end{aligned} FFN(x)=max(0,xW1+b1)W2+b2
论文作者给定了MLP的中间状态输出维度为2048,而最后输出维度为512,当然就是512->2048->512这样变换。
在Transformer中,在嵌入层中,这些权重乘以 d m o d e l \sqrt{d_{model}} dmodel。其原因是在嵌入层学emdedding的时候,在L2norm后,不管维度多大最终权重都会比较小,但后续要和positional encoding相加(不会经过norm),需要保持差不多的scale。
self-attention对输入sequence中各单词的位置或者说顺序不敏感,因为通过Query向量和Key向量的内积,本质上就是一些词由其他词的线性表出,并没有说有位置的信息存在。比如“我吃牛肉”这句话,在Transformer看来和“牛吃我肉”是没什么区别的。
为了缓解该问题,作者提出了位置编码。简而言之,就是在词向量输入到注意力模块之前,与该词向量等长的位置向量进行了按位相加,进而赋予了词向量相应的位置信息。
作者给出了位置编码的定义公式,具体如下:
P E p o s , 2 i = s i n ( p o s / 1000 0 2 i / d m o d e l ) 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}=sin(pos/10000^{2i/d_{model}}) \\ PE_{pos, 2i+1}=cos(pos/10000^{2i/d_{model}}) PEpos,2i=sin(pos/100002i/dmodel)PEpos,2i+1=cos(pos/100002i/dmodel)
这样通过 s i n ( α + β ) = s i n ( α ) c o s ( β ) + c o s ( α ) s i n ( β ) sin(\alpha+\beta)=sin(\alpha)cos(\beta)+cos(\alpha)sin(\beta) sin(α+β)=sin(α)cos(β)+cos(α)sin(β)。可以将牛(pos=3)可以由pos=2和pos=4表达,使得Transformer可以更容易掌握单词间的相对位置。
关于Transformer比较重要的点基本上就这些,当然还有很多细节的地方需要去探索,接下来我将会写更多的论文分享,总结一些经典的模型。