神经网络在机器学习中属于连接主义,attention机制就是通过添加注意力连接实现的,对传统的神经网络添加新的连接,让神经网络自动学习,对输入的各个部分应该分配多少注意力。这篇blog涉及的attention机制只是几个典型的attention,其中,sequence attention在NLP领域用的较多,channel attention和spatial attention在CV领域用的较多。
针对序列的attention,一般用于输入数据有先后时序性要求的任务中,通过添加注意力机制,让神经网络自动学习应该注意到哪一个时间步的输入,所以在介绍这一部分时利用的NLP的应用场景。
在著名的《attention is all you need》论文中,作者认为使用较为广泛的注意力机制可以分成点积注意力(dot-product attention)和额外注意力(additive attention),点积注意力机制,需要我们知道查询向量(query),键向量(key)和值向量(value),简单来说,我们在想要获取attention信息的位置会放出一个query,这个query去查询所有的候选位置,每个候选位置会有一对key和value,查询的过程就是query和所有候选位置的key做点积的过程,点积结果经过softmax后加权到各自的value上,求和就得到了最终的attention结果,具体过程可以看下面。
attention 与 self-attention的区别可以从查询向量(query),键向量(key)和值向量(value)三个向量的来源来区分,以传统的sequence to sequence为例,我们认为模型的输入是一个sequence,记为 s e q 1 = < i 1 , i 2 , … , i n > seq_1=
对于一般的attention,我们一般会在 s e q 2 seq_2 seq2中触发求attention的过程,例如在 o 2 o_2 o2位置放出query,这个query回到 s e q 1 seq_1 seq1中查找 i 1 , i 2 , … , i n i_1,i_2, \dots, i_n i1,i2,…,in各个位置的key-value对,因此query在 s e q 2 seq_2 seq2产生,key-value在 s e q 1 seq_1 seq1产生。
self-attention,一般会在同一个 s e q seq seq内触发求attention的过程,产生query,这个query在同一 s e q seq seq中查找各个位置的key-value对,因此query,key-value的产生都是在一个sequence中的,不存在跨sequence的情况,所以叫做self-attention。
Self-attention, sometimes called intra-attention is an attention mechanism relating different positions of a single sequence in order to compute a representation of the sequence.
在讲解具体的点积注意力过程时,我们以self-attention为例。
首先对输入的sequence的每一个token进行词嵌入,同时每一个token又会有一个查询向量 q q q,键向量 k k k和值向量 v v v,上图假设输入的sequence有两个token,分别是Thinking和Machines,我们想知道Thinking这个单词和这个sequence的所有token的相似度,我们就用Thinking的查询向量 q 1 q_1 q1,点乘每个token的键向量 k i , i = 1 , 2 k_i, i=1,2 ki,i=1,2。
点乘过后,传统的点积注意力机制会直接进入softmax,但是上图会除以 d k \sqrt{d_k} dk, d k d_k dk是查询向量和键向量的维度( d k = 64 d_k=64 dk=64是《attention is all you need》论文中的超参数,如果具体到上图,应该是 d k = 3 d_k=3 dk=3),这是因为,《attention is all you need》的作者认为,当 d k d_k dk变大,查询向量和键向量的点积也会往大了变,会进入softmax函数的小梯度区域,
We suspect that for large values of d k d_k dk, the dot products grow large in magnitude, pushing the softmax function into regions where it has extremely small gradients. To counteract this effect, we scale the dot products by 1 d k \frac{1}{\sqrt{d_k}} dk1 .
这样修改后的点积attention叫Scaled Dot-Product Attention。
认为经过softmax之后的结果就是Thinking对这一sequence的所有token的相似度,这一相似度乘以值向量的结果求和就得到了注意力机制的结果,当然上述过程可以直接用矩阵相乘表示,这也是点积注意力的一大优势:
Q Q Q, K K K, V V 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
其中 Q Q Q的size是 ( w , d k ) (w, d_k) (w,dk), K K K的size是 ( w , d k ) (w, d_k) (w,dk), V V V的size是 ( w , d v ) (w, d_v) (w,dv), w w w是Token数, d v d_v dv可以等于 d k d_k dk
现在我们知道了点积attention的计算过程,我们来看 Q Q Q, K K K, V V V是怎么来的,到目前为止我们没有用到向量就是绿色的词嵌入表示,因此查询矩阵,键矩阵和值矩阵是依靠输入得到的,具体看下面过程
上图中, W Q , W K , W V W^Q,W^K,W^V WQ,WK,WV矩阵就是神经网络需要学习的参数,X就是输入向量拼接后,形成的矩阵。
额外注意力(additive attention)就没有查询向量,键向量和值向量,点积相似度的计算过程被一个额外的神经网络所替代,所以叫做额外注意力机制,所以点积注意力和额外注意力的 compatibility function不同,compatibility function可以理解为计算相似度的抽象函数。在《attention is all you need》论文中以点积注意力为主,所以其提出的大名鼎鼎的transformer也是基于点积注意力。
看名字,应该觉得这俩attention机制应该用于CNN,介绍这channel attention和spatial attention用一个轻量级的CBAM(Convolutional Block Attention Module, Sanghyun Woo et al., 2018),CBAM原理图如下:
CBAM包含Channel Attention和Spatial Attention。对于输入 F F F,其尺寸为 ( B a t c h , C h a n n e l , H e i g h t , W i d t h ) (Batch, Channel, Height, Width) (Batch,Channel,Height,Width)的输入 ,不考虑Batch维度,Channel Attention会计算一个通道权重 M c ( F ) M_{c}(F) Mc(F) ,其尺寸为 ( C h a n n e l , 1 , 1 ) (Channel, 1, 1) (Channel,1,1),也就是对一个通道里面 H e i g t h × W i d t h Heigth\times Width Heigth×Width个像素点的值乘上相同的权重,主要关注于输入的不同通道信息;Spatial Attention会计算一个空间权重 M s ( F ′ ) M_{s}(F') Ms(F′),其尺寸为 ( 1 , H e i g h t , W i d t h ) (1, Height, Width) (1,Height,Width),也就是对不同通道在同一像素位置的值乘上相同的权重,主要关注于输入的不同位置信息。具体运算过程如下
F ′ = M c ( F ) ⊗ F F ′ ′ = M s ( F ′ ) ⊗ F ′ F' = M_{c}(F)\otimes F\\ F''= M_{s}(F')\otimes F' F′=Mc(F)⊗FF′′=Ms(F′)⊗F′
其中 F F F为经过Channel Attention和Spatial Attention之前的输入, F ′ ′ F'' F′′为经过Channel Attention和Spatial Attention之后的结果, M c ( ⋅ ) M_{c}(·) Mc(⋅)与 M s ( ⋅ ) M_{s}(·) Ms(⋅)分别表示Channel Attention和Spatial Attention。
Channel Attention对于输入 F F F,其size为 < B , C , H , W > <B,C,H,W>,分别经过最大池化层和平均池化层,得到两个 < B , C , 1 , 1 > <B,C,1,1>,在经过同一个MLP网络后输出两个 < B , C , 1 , 1 > <B,C,1,1>,在相加经过激活函数得到最终的输出 < B , C , 1 , 1 > <B,C,1,1>。
Spatial Attention对于输入 F ′ F' F′,其size为 < B , C , H , W > <B,C,H,W>,首先在Channel维度上使用最大池化和平均池化,得到两个 < B , 1 , H , W > <B,1,H,W>,经过concatenation得到 < B , 2 , H , W > <B,2,H,W>,使用卷积操作经过激活函数得到最终的输出 < B , 1 , H , W > <B,1,H,W>。
以sequence attention为例,多头attention在实现上就是并列好几个attention,最后合并,有点大力出奇迹的感觉,并列的每一个attention机制,就被称为一个头。
Multi-Head Attention consists of several attention layers running in parallel.
多头attention示意图如下图所示:
多个self-attention并行执行,最后的结果concatenation在一起,如果并列了8个头,concat之后,尺寸会变为原来的8倍,经过神经网络进行缩小回原来的尺寸。
transformer也是火的很,强大的Bert模型也是基于transformer的。transformer是一个完全基于attention的结构,完全没有CNN和RNN的影子,这也侧面说明了attention机制并不依赖于RNN或者CNN,可以独立的拿出来单独形成结构。pytorch在1.2版本已经加入了transformer层。
transformer在《attention is all you need》中继续沿用encode-decode结构,如上图,encode就是左边部分,decode就是右边部分,在encode中又包含很多层编码器,每一层编码器由一个多头attenion子层和一个前向神经网络子层构成,每一子层有一个残差结构;在decode中也包含很多层解码器,每一层解码器由一个masked多头attention子层、一个多头attention子层和一个前向神经网络子层构成,每一子层也是一个残差结构。所以上图的encode和decode都只画了一个层,每一层包含2,3个子层。多画几层就是下面的结构
为了保证数据能够沿着上图的结构前向传播,transformer会维持一个全局的维度 d m o d e l d_{model} dmodel,也就是说不管是embedding层、encode中的每个编码器的每个子层、以及decode中每个解码器的每个子层,其输入输出维度都是 d m o d e l d_{model} dmodel。
附带一提,BERT只用了encode结构。
参考文献:
Attention Is All You Need
CBAM: Convolutional Block Attention Module
BERT大火却不懂Transformer?读这一篇就够了:https://baijiahao.baidu.com/s?id=1622064575970777188&wfr=spider&for=pc