目录
1.简介
Attention机制最早在视觉领域提出,2014年Google Mind发表了《Recurrent Models of Visual Attention》,使Attention机制流行起来,这篇论文采用了RNN模型,并加入了Attention机制来进行图像的分类。
2005年,Bahdanau等人在论文《Neural Machine Translation by Jointly Learning to Align and Translate》中,将attention机制首次应用在nlp领域,其采用Seq2Seq+Attention模型来进行机器翻译,并且得到了效果的提升,Seq2Seq With Attention中进行了介绍。
2017 年,Google 机器翻译团队发表的《Attention is All You Need》中,完全抛弃了RNN和CNN等网络结构,而仅仅采用Attention机制来进行机器翻译任务,并且取得了很好的效果,注意力机制也成为了大家近期的研究热点。
本文首先介绍常见的Attention机制,然后对论文《Attention is All You Need》进行介绍,该论文发表在NIPS 2017上。
2.attention机制
关于这部分的内容,可以具体参考我的另外一篇博客:self-attention理解
3.Transformer结构
绝大部分的序列处理模型都采用encoder-decoder结构,其中encoder将输入序列 {x1,x2, … ,xn } 映射到连续表示 {z1,z2, … ,zn } ,然后decoder生成一个输出序列 [公式] ,每个时刻输出一个结果。Transformer模型延续了这个模型,整体架构如下图所示
3.1 Encoder
Encoder有N=6层,每层包括两个sub-layers:
- 第一个sub-layer是multi-head self-attention mechanism,用来计算输入的self-attention
- 第二个sub-layer是简单的全连接网络(feed-forward sublayer)
在每个sub-layer都模拟了残差网络,每个sub-layer的输出都是
其中Sublayer(x) 表示Sub-layer对输入 x 做的映射,在两个子层的每一层后采用残差连接,接着进行layer normalization,为了确保连接,所有的sub-layers和embedding layer输出的维数都相同 ,即 dmodel = 512
3.2 Decoder
Decoder也是N=6层,每层包括3个sub-layers:
- 第一个是Masked multi-head self-attention,也是计算输入的self-attention,但是因为是生成过程,因此在时刻 i 的时候,大于 i 的时刻都没有结果,只有小于 i 的时刻有结果,因此需要做Mask
- 第二个sub-layer是对encoder的输入进行attention计算
- 第三个sub-layer是全连接网络,与Encoder相同
同时Decoder中的self-attention层需要进行修改,因为只能获取到当前时刻之前的输入,因此只对时刻 t之前的时刻输入进行attention计算,这也称为Mask操作。
3.3 Attention机制
在Transformer中使用的Attention是Scaled Dot-Product Attention, 是归一化的点乘Attention,假设输入的query q 、key维度为 dk ,value维度为 dv , 那么就计算query和每个key的点乘操作,并除以 √dk
,然后应用Softmax函数计算权重
在实践中,将query和keys、values分别处理为矩阵 Q,K,V , 那么计算输出矩阵为
其中Q,K,V如下图所示
那么Scaled Dot-Product Attention的示意图如下所示,Mask是可选的(opt.),如果是能够获取到所有时刻的输入(K, V), 那么就不使用Mask;如果是不能获取到,那么就需要使用Mask。使用了Mask的Transformer模型也被称为Transformer Decoder,不使用Mask的Transformer模型也被称为Transformer Encoder。
如果只对Q、K、V做一次这样的权重操作是不够的,这里提出了Multi-Head Attention,操作包括:
- 首先对Q、K、V做一次线性映射,将输入维度均为 dmodel 的 Q,K,V 矩阵映射到 Rm*dk ,
Rm*dk ,Rm*dv - 在采用Scaled Dot-Product Attention计算出结果
- 多次进行上述两步操作,然后将得到的结果进行合并
- 将合并的结果进行线性变换
这样输出的矩阵 Rm*512 ,每行的向量都是对 V 向量中每一行 vi 的加权,示意图如下所示
在Encoder-Decoder架构中,有三处Multi-head Attention模块,分别是:
- Encoder模块的Self-Attention,在Encoder中,每层的Self-Attention的输入Q =K =V, 都是上一层的输出。Encoder中的每个position都能够获取到前一层的所有位置的输出。
- Decoder模块的Mask Self-Attention,在Decoder中,每个position只能获取到之前position的信息,因此需要做mask
- Encoder-Decoder之间的Attention,其中 Q 来自于之前的Decoder层输出, K,V 来自于encoder的输出,这样decoder的每个位置都能够获取到输入序列的所有位置信息。
3.4 Position-wise Feed-forward Networks
在进行了Attention操作之后,encoder和decoder中的每一层都包含了一个全连接前向网络,对每个position的向量分别进行相同的操作,包括两个线性变换和一个ReLU激活输出
其中每一层的参数都相互独立
3.5 Position Embedding
因为模型不包括recurrence/convolution,因此是无法捕捉到序列顺序信息的,例如将K、V按行进行打乱,那么Attention之后的结果是一样的。但是序列信息非常重要,代表着全局的结构,因此必须将序列的token相对或者绝对position信息利用起来。
这里每个token的position embedding 向量维度也是 dmodel = 512 然后将原本的input embedding和position embedding加起来组成最终的embedding作为encoder/decoder的输入。其中position embedding计算公式如下
其中 pos 表示位置index, i 表示dimension index
Position Embedding本身是一个绝对位置的信息,但在语言中,相对位置也很重要,Google选择前述的位置向量公式的一个重要原因是:
这表明位置p+k的向量可以表示成位置p的向量的线性变换,这提供了表达相对位置信息的可能性。
position embedding,通常是一个训练的向量,但是position embedding只是extra features,有该信息会更好,但是没有性能也不会产生极大下降,因为RNN、CNN本身就能够捕捉到位置信息,但是在Transformer模型中,Position Embedding是位置信息的唯一来源,因此是该模型的核心成分,并非是辅助性质的特征。也可以采用训练的position embedding,但是试验结果表明相差不大,因此论文选择了sin position embedding,因为
- 这样可以直接计算embedding而不需要训练,减少了训练参数
- 这样允许模型将position embedding扩展到超过了training set中最长position的position,例如测试集中出现了更大的position,sin position embedding依然可以给出结果,但不存在训练到的embedding
4.Why Self-Attention
将Self-Attention layers和recurrent/convolutional layers来进行比较,来说明Self-Attention的好处。假设将一个输入序列 {x1,x2, … ,xn } 分别用
- Self-Attention Layer
- Recurrent Layer
- Convolutional Layer
来映射到一个相同长度的序列 {z1,z2, … ,zn }
分析三个方面,得到结果
- 每一层的计算复杂度
- 能够被并行的计算,用需要的最少的顺序操作的数量来衡量
- 网络中long-range dependencies的path length,在处理序列信息的任务中很重要的在于学习long-range dependencies。影响学习长距离依赖的关键点在于前向/后向信息需要传播的步长,输入和输出序列中路径越短,那么就越容易学习long-range dependencies。因此我们比较三种网络中任何输入和输出之间的最长path length
5.
更为形象的解释,可以参照github上面的文章 The Illustrated Transformer