深入理解注意力机制

这篇文章主要是为了监督自己系统学习一下注意力机制的知识(模糊地看过好多次,但什么都没学会…看论文才发现需要补一下知识)。
主要分为以下几点内容:

PART1----注意力机制是为了解决什么问题?

PART2----软性注意力机制(soft attention)的数学原理

PART3----软性注意力机制、Encoder-Decoder框架、Seq2Seq

PART4----自注意力模型的原理

PART5----Multi-head Attention

PART6----Attention机制的应用(计算机视觉领域)

PART7----Cross Attention


PART1 注意力机制是为了解决什么问题?

在神经网络的学习中,一般而言模型的参数越多则模型的表达能力越强,模型所存储的信息量也越大,但这会带来信息过载的问题。那么通过引入注意力机制,在众多的输入信息中聚焦于对当前任务更为关键的信息,降低对其他信息的关注度,甚至过滤掉无关信息,就可以解决信息过载问题,并提高任务处理的效率和准确性。
这类似于我们人类的视觉注意力机制,通过快速扫描全局图像,找到需要重点关注的目标区域,也就是一般所说的注意力焦点,然后在这个区域投入更多的注意力,以获取更多所需要关注目标的细节信息,而忽视其他的不重要的无关信息。
深度学习中的注意力机制从本质上讲和人类的选择性视觉注意力机制类似,核心目标也是从众多信息中选择出对当前任务目标更关键的信息


PART2 软性注意力机制的数学原理

(一)最原本的模式

X = [ x 1 , x 2 , . . . , x N ] X=[x_1,x_2,...,x_N] X=[x1,x2,...,xN]表示N个输入信息,为了提高神经网络的效率,不需要让神经网络处理所有的N个输入信息,而只需要从 X X X中选择一些与任务相关的信息输入进行计算。(这里讲一下软性注意力和硬性注意力的区别)软性注意力(soft attention)机制是指在选择信息的时候,不是从N个信息中选择一个,而是计算N个输入信息的加权平均,再输入到神经网络中计算。硬性注意力(hard attention)机制是指选择输入序列某一个位置上的信息,比如随机选择一个信息或者选择概率最高的信息。一般是用软性注意力机制来处理神经网络的问题
这里先单独介绍一下注意力值的计算。完整的带注意力机制的神经网络的工作流程在PART3。

注意力值的计算可以分为两步:

(1)在所有的输入信息上计算注意力分布

给定这样一个场景:把输入信息向量 X X X看作是一个信息存储器,现在给定一个查询向量 q q q,用来查找并选择 X X X中的某些信息,那么就需要知道被选择信息的索引位置。采取软性选择机制,不是从存储的多个信息中只挑出一个信息而是从所有的信息中都抽取一些,最相关的信息就抽取的更多。
定义一个注意力变量 z ∈ [ 1 , N ] z∈[1,N] z[1,N]来表示被选择信息的索引位置,也就是 z = i z=i z=i表示选择了第 i i i个输入信息,然后计算在给定了 q q q X X X的情况下,选择第 i i i个输入信息的概率 α i α_i αi
在这里插入图片描述
(这里补充一下softmax函数:Softmax的含义就在于不再唯一的确定某一个最大值,而是为每个输出分类的结果都赋予一个概率值,表示属于每个类别的可能性。单个输出节点的二分类问题一般在输出节点上使用Sigmoid函数,拥有两个及其以上的输出节点的二分类或者多分类问题一般在输出节点上使用Softmax函数。)
其中, α i α_i αi构成的概率分布向量就称为注意力分布(Attention Distribution)。 s ( x i , q ) s(x_i,q) s(xi,q)是注意力打分函数,有以下几种形式:

在这里插入图片描述
其中, W W W U U U v v v是可学习的网络参数, d d d是输入信息的维度。

(2)根据注意力分布来计算输入信息的加权平均

注意力分布 α i α_i αi表示在给定查询 q q q时,输入信息向量 X X X中第 i i i个信息与查询 q q q的相关程度。采用软性信息选择机制给出查询所得的结果,就是用加权平均的方式对输入信息进行汇总,得到Attention值:
在这里插入图片描述
下面是计算Attention值的整体过程图:
在这里插入图片描述

(二)键值对注意力模式

更一般地,可以用键值对(key-value pair)来表示输入信息,那么 N N N个输入信息就可以表示为:
( K , V ) = [ ( k 1 , v 1 ) , ( k 2 , v 2 ) , . . . , ( k N , v N ) ] (K,V)=[(k_1,v_1),(k_2,v_2),...,(k_N,v_N)] (K,V)=[(k1,v1),(k2,v2),...,(kN,vN)],其中,Key用来计算注意力分布 α i α_i αi,Value用来基于注意力分布计算聚合后的信息
那么,就可以把注意力机制看作是一种软寻址操作:把输入信息 X X X看作是存储器中存储的内容,元素由地址Key(键)和值Value(值)组成,当前有个Key=Query(目标任务的表示)的查询,目标是取出存储器中对应的Value值,即Attention值。而在软寻址中,并不是需要硬性满足Key=Query的条件来取出存储信息。而是通过计算Query与存储器中元素的地址Key的相似度 来决定 从对应的元素Value中取出多少的内容。每个地址Key对应的Value值都会被抽取内容出来,然后求和,这就相当于由Query和Key的相似性来计算每个Value值的权重,然后对Value值进行加权求和,得到最终的Value值即Attention值。

可以归纳为三个过程:
step1:根据Query和Key计算二者的相似度。可以用上面所列的加性模型、点积模型或余弦相似度来计算,得到注意力得分 s i = F ( Q , k i ) s_i=F(Q,k_i) si=F(Q,ki)
step2:用softmax函数对注意力得分进行数值转换。一方面可以进行归一化,得到所有权重系数之和为1的概率分布,另一方面可以用softmax函数的特性突出重要元素的权重(这是因为经过使用指数形式的Softmax函数能够将差距大的数值距离拉的更大):
α i = s o f t m a x ( s i ) = e x p ( s i ) ∑ j = 1 N e x p ( s j ) α_i=softmax(s_i)=\frac{exp(s_i)}{\sum_{j=1}^Nexp(s_j)} αi=softmax(si)=j=1Nexp(sj)exp(si)

step3:根据权重系数对Value进行加权求和 A t e n t i o n ( ( K , V ) , Q ) = ∑ i = 1 N α i v i Atention((K,V),Q)=\sum_{i=1}^Nα_iv_i Atention((K,V),Q)=i=1Nαivi

图示如下:
在这里插入图片描述
将这三个过程用公式表示为: a t t e n t i o n ( ( K , V ) , q ) = ∑ i = 1 N α i v i = ∑ i = 1 N e x p ( s ( k i , q ) ) ∑ j = 1 N e x p ( s ( k j , q ) ) v i attention((K,V),q)=\sum_{i=1}^Nα_iv_i=\sum_{i=1}^N\frac{exp(s(k_i,q))}{\sum_{j=1}^Nexp(s(k_j,q))}v_i attention((K,V),q)=i=1Nαivi=i=1Nj=1Nexp(s(kj,q))exp(s(ki,q))vi


PART3 软性注意力机制与Encoder-Decoder框架

注意力机制是一种通用的思想,本身不依赖与特定的框架,但是目前大多数注意力模型和Encoder-Decoder框架结合使用。它可以简单地总结为两个步骤:

  • 在给定的信息上计算注意力分布(也就是判断什么信息重要,什么信息不重要,分别赋予不同的权重)
  • 根据注意力分布来计算所有输入信息的加权平均

下图是在文本处理领域里二者相结合的结构(未引入注意力和引入了注意力模型):
在这里插入图片描述

在这里插入图片描述
文本处理领域的Encoder-Decoder框架可以这么直观地去理解:可以把它看作适合处理由一个句子(或篇章)生成另外一个句子(或篇章)的通用处理模型。对于句子对<Source,Target>,我们的目标是给定输入句子Source,期待通过Encoder-Decoder框架来生成目标句子Target。Source和Target可以是同一种语言,也可以是两种不同的语言。而Source和Target分别由各自的单词序列构成。Encoder就是对输入句子Source进行编码,将输入句子通过非线性变换转化为中间语义表示 c c c。对于解码器Decoder来说,其任务是根据句子Source的中间语义表示 c c c和之前已经生成的历史信息来生成未来时刻要生成的单词。

Encoder-Decoder框架是一种深度学习领域的常用框架模式,在文本处理、语音识别和图像处理等领域被广泛使用。其编码器和解码器并非是特定的某种神经网络模型,在不同的任务中会套用不同的模型,比如在文本处理中常用RNN模型,图像处理中一般采用CNN模型。

以RNN作为编码器和解码器的Encoder-Decoder框架也叫做异步的序列到序列模型,也就是Seq2Seq模型

以下是没有引入注意力机制的RNN Encoder-Decoder框架:
在这里插入图片描述
下面以Seq2Seq模型为例,来对比未加入注意力机制的模型和加入了注意力机制的模型。

(一)未加入注意力机制的RNN Encoder-Decoder

未加入注意力机制的RNN Encoder-Decoder框架在处理序列数据时,可以做到先用编码器把长度不固定的序列 X X X编码成长度固定的向量表示 C C C,再用解码器把这个向量表示解码成另一个长度不固定的序列 y y y,输入序列 X X X和输出序列 y y y的长度可能是不同的。
《Learning phrase representations using RNN encoder-decoder for statiscal machine translation》这篇论文提出了一种RNN Encoder-Decoder结构,如下图所示。除此之外,这篇文章首次提出了GRU这个常用的LSTM变体结构。

在这里插入图片描述
把这个结构用在文本处理中,给定输入序列 X = [ x 1 , x 2 , . . . , x N ] X=[x_1,x_2,...,x_N] X=[x1,x2,...,xN],也就是由单词序列构成的句子,这样的一个编码-解码过程相当于是求另一个长度可变的序列 y = [ y 1 , y 2 , . . . , y T ] y=[y_1,y_2,...,y_T] y=[y1,y2,...,yT]的条件概率分布: p ( y ) = p ( y 1 , y 2 , . . . , y T ∣ x 1 , x 2 , . . . , x N ) p(y)=p(y_1,y_2,...,y_T|x_1,x_2,...,x_N) p(y)=p(y1,y2,...,yTx1,x2,...,xN)。经过解码后,这个条件概率分布可以转化为累乘形式: p ( y ) = ∏ t = 1 T p ( y t ∣ { y 1 , . . . , y t − 1 } , c ) p(y)=\prod_{t=1}^Tp(y_t|\lbrace{y_1,...,y_{t-1}}\rbrace,c) p(y)=t=1Tp(yt{ y1,...,yt1},c)
So在得到了表示向量 c c c和之前预测的所有词 ( y 1 , y 2 , . . . , y t − 1 ) (y_1,y_2,...,y_{t-1}) (y1,y2,...,yt1)后,此模型可以用来预测第 t t t个词 y t y_t yt,也就是求条件概率 p ( y t ∣ { y 1 , . . . , y t − 1 } , c ) p(y_t|\lbrace{y_1,...,y_{t-1}}\rbrace,c) p(yt{ y1,...,yt1},c)

对照上面的Figure1,我们分三步来计算这个条件概率
step1:把输入序列 X X X中的元素一步步输入到Encoder的RNN网络中,计算每个输入数据的隐藏状态 h t h_t ht,然后把所有的隐藏状态 [ h 1 , h 2 , . . . , h T ] [h_1,h_2,...,h_T] [h1,h2,...,hT]整合为一个语义表示向量 c c c
h t = f 1 ( x t , h t − 1 ) c = q ( { h 1 , h 2 , . . . h T } ) h_t=f_1(x_t,h_{t-1})\quad\quad\quad c=q(\lbrace h_1,h_2,...h_T\rbrace) ht=f1(xt,ht1)c=q({ h1,h2,...hT})

step2:Decoder的RNN网络每一个时刻 t t t都会输出一个预测的 y t y_t yt。根据语义表示向量 c c c、上一时刻预测的 y t − 1 y_{t-1} yt1和Decoder的隐藏状态 s t − 1 s_{t-1} st1,计算当前时刻 t t t的隐藏状态 s t = f 2 ( y t − 1 , s t − 1 , c ) s_t=f_2(y_{t-1},s_{t-1},c) st=f2(yt1,st1,c)
step3:由语义表示向量 c c c、上一时刻预测的词 y t − 1 y_{t-1} yt1和Decoder中的隐藏状态 s t s_t st,预测第 t t t个词 y t y_t yt,也就是求下面的条件概率:
p ( y t ∣ { y 1 , . . . , y t − 1 } , c ) = g ( y t − 1 , s t , c ) p(y_t|\lbrace{y_1,...,y_{t-1}}\rbrace,c)=g(y_{t-1},s_t,c) p(yt{ y1,...,yt1},c)=g(yt1,st,c)

可以看到,在生成目标句子的每一个单词时,使用的语义向量 c c c都是同一个,也就意味着在预测某一个词 y t y_t yt时,任何输入单词对于它的重要性都是一样的,注意力是分散的。也就是说在生成每一个单词时,并没有产生 [ c 1 , c 2 , . . . c T ] [c_1,c_2,...c_T] [c1,c2,...cT]这样与每个输出的单词相对应的多个不同的语义表示。

(二)加入注意力机制的RNN Encoder-Decoder

《Neural Machine Translation by Jointly Learning to Align and Translate》这篇论文在上面那篇论文的基础上,提出了一种新的神经网络翻译模型结构,也就是在RNN Encoder-Decoder框架中加入了注意力机制,这篇论文中的编码器是一个双向GRU,解码器也是用RNN网络来生成句子。
用这个模型来做机器翻译,那么给定一个句子 X = [ x 1 , x 2 , . . . , x N ] X=[x_1,x_2,...,x_N] X=[x1,x2,...,xN],经过编码-解码操作后,生成另一种语言的目标句子 y = [ y 1 , y 2 , . . . , y T ] y=[y_1,y_2,...,y_T] y=[y1,y2,...,yT],也就是要计算每个可能单词的条件概率,用于搜索最可能的单词,公式如下:
p ( y i ∣ y 1 , . . . y i − 1 , x ) = g ( y i − 1 , s i , c i ) p(y_i| y_1,...y_{i-1},x)=g(y_{i-1},s_i,c_i) p(yiy1,...yi1,x)=g(yi1,si,ci)

生成第 t t t个单词的过程图示如下:
在这里插入图片描述
和未加入注意力机制的RNN Encoder-Decoder框架相比,一方面从 y i y_i yi的条件概率计算公式来看, g ( ⋅ ) g(·) g()这个非线性函数中的语义表示向量是随着输出 y i y_i yi的变化而变化的 c i c_i ci,而不是一直不变的 c c c;另一方面从上图来看,每生成一个单词 y t y_t yt,就要用原句子序列 X X X和其他信息重新计算一个语义表示向量 c i c_i ci。所以增加了注意力机制的RNN Encoder-Decoder框架的关键就在于,固定不变的语义表示向量 c c c被替换成了根据当前生成的单词而不断变化的语义表示 c i c_i ci

对照上图,我们分四步来计算生成的单词 y i y_i yi的条件概率
step1:给定原输入序列(就是一个句子) X = [ x 1 , x 2 , . . . , x N ] X=[x_1,x_2,...,x_N] X=[x1,x2,...,xN],把单词一个个输入到Encoder的RNN网络中,计算每个输入数据的隐藏状态 h t h_t ht,这里采用的编码器是双向RNN,所以要分别计算出顺时间循环层和逆时间循环层的隐藏状态,然后把所有的隐藏状态拼接起来
h t ( 1 ) = f ( U ( 1 ) h t − 1 ( 1 ) + W ( 1 ) x t + b ( 1 ) ) h t ( 2 ) = f ( U ( 2 ) h t + 1 ( 2 ) + W ( 2 ) x t + b ( 2 ) ) h t = h t ( 1 ) ⊕ h t ( 2 ) h_t^{(1)}=f(U^{(1)}h_{t-1}^{(1)}+W^{(1)}x_t+b^{(1)})\quad\quad\quad\quad h_t^{(2)}=f(U^{(2)}h_{t+1}^{(2)}+W^{(2)}x_t+b^{(2)})\quad\quad\quad\quad h_t=h_t^{(1)}⊕h_t^{(2)} ht(1)=f(U(1)ht1(1)+W(1)xt+b(1))ht(2)=f(U(2)ht+1(2)+W(2)xt+b(2))ht=ht(1)ht(2)

step2在解码器的RNN网络中,在第 t t t时刻,根据已知的语义表示向量 c t c_t ct、上一时刻预测的 y t − 1 y_{t-1} yt1、编码器中的隐藏状态 s t − 1 s_{t-1} st1,计算当前时刻的隐藏状态 s t = f 2 ( y t − 1 , s t − 1 , c t ) s_t=f_2(y_{t-1},s_{t-1},c_t) st=f2(yt1,st1,ct) ( c t c_t ct的值是多少?)
step3:求 c t c_t ct,需要先知道 s t − 1 s_{t-1} st1
e i j = a ( s i − 1 , h j ) α i j = e x p ( e i j ) ∑ k = 1 K e x p ( e i k ) c i = ∑ j = 1 T x α i j h j e_{ij}=a(s_{i-1},h_j)\quad\quad\quad\quad α_{ij}=\frac{exp(e_{ij})}{\sum_{k=1}^Kexp(e_{ik})}\quad\quad\quad\quad c_i=\sum_{j=1}^{T_x}α_{ij}h_j eij=a(si1,hj)αij=k=1Kexp(eik)exp(eij)ci=j=1Txαijhj
这里的 e i j e_{ij} eij就是还没有归一化的注意力得分 a ( ⋅ ) a(·) a()这个非线性函数叫做对齐模型,它的作用是把编码器中的每个单词 x j x_j xj对应的隐藏状态 h j h_j hj和解码器中生成单词 y i y_i yi的前一个单词的隐藏状态 s i − 1 s_{i-1} si1进行对比,从而计算出每个输入单词 x j x_j xj和生成单词 y i y_i yi之间的匹配程度。匹配程度越高,注意力得分就越高,那么在生成单词 y i y_i yi时,就需要给予这个输入单词更多的关注
得到注意力得分 e i j e_{ij} eij后,用softmax函数进行归一化,得到注意力概率分布 σ i j σ_{ij} σij。这个注意力分布作为每个输入单词 x j x_j xj受关注程度的权重,对每个输入单词对应的隐藏状态 h j h_j hj进行加权求和,就得到了每个生成的单词 y i y_i yi所对应的语义表示向量 c i c_i ci,也就是attention值
step4:我们的目的不是求出attention值,而是求出生成的单词 y i y_i yi的条件概率 p ( y t ∣ { y 1 , . . . , y t − 1 } , c ) = g ( y t − 1 , s t , c ) p(y_t|\lbrace{y_1,...,y_{t-1}}\rbrace,c)=g(y_{t-1},s_t,c) p(yt{ y1,...,yt1},c)=g(yt1,st,c)


PART4 自注意力模型

(一)通俗的解释

我们与软注意力Encoder-Decoder模型进行对比,来认识一下自注意力模型(Self-Attention Model)。

在软注意力Encoder-Decoder模型中,更具体地说,在机器翻译模型中,输入序列和输出序列的内容甚至长度都是不一样的,注意力机制是发生在编码器和解码器之间,也就是说是发生在输入的原句子序列和输出的生成序列之间,此时Query来自Target,Key和Value来自Source。而自注意力模型中的自注意力机制是发生在输入序列内部或者输出序列内部的,也可以理解为Target=Source这种特殊情况下的注意力计算机制,此时Query、Key和Value来自Source或Target,可以抽取到同一个句子内间隔较远的单词之间的联系,比如句法特征(有一定距离的短语结构)

如果是单纯的RNN网络,对于输入序列就按步骤计算隐藏状态和输出的,对于距离比较远但却相互依赖的特征,网络捕获到二者之间的联系的可能性比较小,而在序列内部引入自注意力机制后,可以将句子中的任意两个单词通过计算直接联系起来,就更容易捕获相互依赖的特征。

(二)理论分析

在对自注意力有了大概的认识后,我们用公式来定义一下自注意力模型。
自注意力模型是在同一层网络的输入和输出(不是模型最终的输出)之间,利用注意力机制动态地生成不同连接的权重,来得到该层网络输出的模型。
前面说了自注意力模型可以建立序列内部的长距离依赖关系,其实通过全连接神经网络也可以做到,但是问题在于全连接网络的连接边数是固定不变的,因而无法处理长度可变的序列。而自注意力模型可以动态生成不同连接的权重,生成多少个权重,权重的大小是多少,都是可变的,当输入更长的序列时,只需要生成更多连接边即可。如下图,虚线连接边是动态变化的。

在这里插入图片描述
用数学公式来表达自注意力机制:假设一个神经层中的输入序列为 X = [ x 1 , x 2 , . . . , x N ] X=[x_1,x_2,...,x_N] X=[x1,x2,...,xN],输出序列为同等长度的 H = [ h 1 , h 2 , . . . , h N ] H=[h_1, h_2, ..., h_N] H=[h1,h2,...,hN],首先将输入的 X X X通过线性变换投影到三个不同的空间(这里的线性投影的含义就是学习到三个不同的矩阵),得到三组向量序列:
Q = W Q X ∈ R d 3 × N K = W K X ∈ R d 3 × N V = W V X ∈ R d 3 × N Q=W_QX∈R^{d_3×N}\quad\quad\quad\quad K=W_KX∈R^{d_3×N}\quad\quad\quad\quad V=W_VX∈R^{d_3×N} Q=WQXRd3×NK=WKXRd3×NV=WVXRd3×N

其中, Q Q Q K K K V V V分别为查询向量序列 [ q 1 , . . . , q N ] [q_1,...,q_N] [q1,...,qN]、键向量序列 [ k 1 , . . . , k N ] [k_1,...,k_N] [k1,...,kN]、值向量序列 [ v 1 , . . . , v N ] [v_1,...,v_N] [v1,...,vN] W Q W_Q WQ W K W_K WK W V W_V WV分别是可学习的参数矩阵。
输出向量 h i h_i hi表示为:
h i = a t t e n t i o n ( ( K , V ) , q i ) = ∑ j = 1 N α i j v j = ∑ j = 1 N s o f t m a x ( s ( k j , q i ) v j ) h_i=attention((K,V),q_i)=\sum_{j=1}^Nα_{ij}v_j=\sum_{j=1}^Nsoftmax(s(k_j,q_i)v_j) hi=attention((K,V),qi)=j=1Nαijvj=j=1Nsoftmax(s(kj,qi)vj)

其中, i , j ∈ [ 1 , N ] i,j∈[1,N] i,j[1,N]为输出向量和输入向量序列的位置,连接权重 α i j αij αij由注意力机制动态生成。
整体图解为:
在这里插入图片描述
这张图中,假设输入三个 X X X序列(N=3),每一个的长度为 D x D_x Dx,则此时得到三个查询向量,每一个查询向量得到一个对应的结果拼在一起,不改变输入的 X X X的对应N这部分的维度,但是将长度 D x D_x Dx改变为了 D v D_v Dv(这里的 D v D_v Dv是可以任意设置的,只要通过操作此时从 X X X到值 V V V的投影操作对应的矩阵 W v W_v Wv就可以了)。也就是说通过上述操作,可以将不定长的序列 D x D_x Dx动态地生成适合的权重并转化为某一个定长 D v D_v Dv

自注意力机制可以作为神经网络的一层来使用,也可以用来替换卷积层或循环层,也可以与卷积层或循环层交叉堆叠使用。

在下图中,输入序列和输出序列都是同一个句子,通过由自注意力机制动态生成的权重,可以发现making与more-difficult的权重比较大(颜色深),于是捕获了这三个词之间存在的联系(构成了一个短语)。 很明显,引入Self Attention后会更容易捕获句子中长距离的相互依赖的特征,因为如果是RNN或者LSTM,需要依次序序列计算,对于远距离的相互依赖的特征,要经过若干时间步步骤的信息累积才能将两者联系起来,而距离越远,有效捕获的可能性越小。

但是Self Attention在计算过程中会直接将句子中任意两个单词的联系通过一个计算步骤直接联系起来,所以远距离依赖特征之间的距离被极大缩短,有利于有效地利用这些特征。而且,Self Attention对于增加计算的并行性也有直接帮助作用,这主要体现在self attention的矩阵计算过程中。这是为何Self Attention逐渐被广泛使用的主要原因。

在这里插入图片描述


PART5 Multi-head Attention

Multi-head Attention注意力的思想比较直接,就是存在多个查询向量 Q = [ q 1 , . . . , q M ] Q=[q_1,...,q_M] Q=[q1,...,qM],来通过一种并行的方式从输入中搜索需要的信息。直观点儿的理解是解决问题需要很多不同的方面的信息,每一个查询向量 q i q_i qi考察的都是不同的方面,此时利用不同的 q i q_i qi从不同的角度给输入信息的重要性进行打分,再进行某种程度的聚合。
也就是把计算attention的过程重复h次,然后将结果拼接起来,以常见的Scaled Dot-Product Attention计算为例,大致分成两步:
step1:把 Q、K、V 通过参数矩阵映射,然后再做attention,把这个过程重复h次
step2:把多个头的输出拼接起来
M u l t i H e a d ( ( K , V ) , q ) = C o n c a t ( ( ( K , V ) , q 1 ) , . . . , ( ( K , V ) , q M ) ) MultiHead((K,V),q)=Concat(((K,V),q_1),...,((K,V),q_M)) MultiHead((K,V),q)=Concat(((K,V),q1),...,((K,V),qM))

所谓Multi-head,就是多做几次同样的事情(参数不共享),然后把结果拼接起来。再回顾一下上一节的自注意力:比如说此时对应的 X X X的维度是 D x D_x Dx,共 N 个,每一次通过一个矩阵 W Q W_Q WQ将其投影为一个查询矩阵的时候都可以一次性得到 N 个查询向量,这 N 个查询向量可以保证后续输出的结果还是共 N 个(只是另一个维度由值向量的维度 D v D_v Dv决定)。考虑多头注意力,也就是说此时我们考虑能不能得到多个查询矩阵,以从不同的角度来捕捉 X X X的重要情况,也就是说采用多个矩阵 W Q i W_{Q_i} WQi将它投影到 m 个不同的空间分别得到 m 个查询矩阵,共 m ∗ N m*N mN个向量,再分别计算输出,最后采用向量拼接的方式把它拼起来得到最后的结果。

Single-Head Attention VS Multi-Head Attention对比了多头注意力机制的计算过程和多头注意力机制的计算过程。
在这里插入图片描述


PART6 Attention机制的应用(计算机视觉领域)

Attention机制对于计算机视觉能不能起到帮助作用呢?attention本身是一个加权,加权也就意味着可以融合不同的信息。CNN本身有一个缺陷,每次操作只能关注到卷积核附近的信息(local information),不能融合远处的信息(non-local information)。而attention可以把远处的信息也帮忙加权融合进来,起一个辅助作用。
在这里插入图片描述
如上图所示,每个例子上方左侧是输入的原图,下方句子是人工智能系统自动产生的描述语句,上方右侧图展示了当AI系统产生语句中划横线单词的时候,对应图片中聚焦的位置区域。比如当输出单词dog的时候,AI系统会将注意力更多地分配给图片中小狗对应的位置。

在计算机视觉的相关应用中大概可以分为两种
(1)学习权重分布:输入数据或特征图上的不同部分对应的专注度不同

  • 这个加权可以是保留所有分量均做加权(也就是soft attention);也可以是在分布中以某种采样策略选取部分分量(也就是hard attention),此时常用RL来做。
  • 这个加权可以作用在原图上,也就是《Recurrent Model of Visual Attention》(RAM)和《Multiple Object Recognition with Visual Attention》(DRAM);也可以作用在特征图上,如后续的好多文章(例如image caption中的《 Show, Attend and Tell: Neural Image Caption Generation with Visual Attention》)。
  • 这个加权可以作用在空间尺度上,给不同空间区域加权;也可以作用在channel尺度上,给不同通道特征加权;甚至特征图上每个元素加权。
  • 这个加权还可以作用在不同时刻历史特征上,如Machine Translation。

(2)任务聚焦:通过将任务分解,设计不同的网络结构(或分支)专注于不同的子任务,重新分配网络的学习能力,从而降低原始任务的难度,使网络更加容易训练。


PART7 Cross Attention

Cross Attention只对Self Attention的输入做了改动,Cross-attention的输入来自不同的序列,Self-attention的输入来自同序列,也就是所谓的输入不同。具体来说,self-attention输入是一个单一的嵌入序列Cross-attention将两个相同维度的嵌入序列不对称地组合在一起,而其中一个序列用作查询Q输入,而另一个序列用作键K和值V输入。当然也存在个别情况,在SelfDoc的cross-attention,使用一个序列的查询和值,另一个序列的键。总而言之,QKV是由两序列拼凑的,不单一。

它最终使用于Transformer的decoder。Transformer的decoder模块如下图右侧,它有三个输入分别为input1、input2、input3。Decoder先递归地输入 input1:过去时刻decoder的output表示位置信息的input2:position encoding 相加,经过masked multi-head attention后 与 input3:encoder的output做cross attention。因此cross attention通常作为decoder模块,与Self Attention作为encoder共同使用。

在这里插入图片描述
Cross Attention输入的Query来自Encoder(Self Attention)的输出,而Key和Value来自初始的input,即Encoder的输入。也就是说将encoder输出作为预测句子的一种表示,然后其来查询与原始输入句子中每个单词的相似性。Cross Attention做的事情是用key/value的信息表示query的信息,或者说将key/value信息引入到query信息中(因为有residual层会与原query信息相加),求得的是query对于key的相关性(query attending to key, e.g., vehicle attending to lanes, vice versa)。

Cross Attention在decoder中应用非常多,一般在encoder使用了Self Attention后,在decoder中先用Cross Attention网络层获取attention value,然后接一个MLP层或LSTM层预测目标,比直接用MLP或LSTM作为decoder的效果会好很多。Cross Attention还可以将先前任意一层网络层的信息再次引入,类似于residual的功能,但更加灵活。

除此之外,Cross Attention的Query和Key也可以来自两个不同模态的输入,例如一个是图像,一个是对应的文本,用来求两者的相关性,即图像-文本任务,这也是该模块设计出来的初衷之一。


参考资料:

深度学习中的注意力机制
一文读懂注意力机制
GAT, Self Attention, Cross Attention对比以及在自动驾驶轨迹预测任务中的pytorch应用
Illustrated: Self-Attention
详解Self-Attention和Multi-Head Attention

猜你喜欢

转载自blog.csdn.net/weixin_44022810/article/details/127477454
今日推荐