Attention
Attention机制的引入
注意力是人类不可或缺的复杂认知功能,指人可以在关注一些信息的同时忽略另一些信息的能力。注意力可以作用在外部的刺激(听觉,味觉),也可以作用在内部的意识(思考,回忆)。
在计算能力有限的情况下,注意力机制(Attention Mechanism)作为一种资源分配方案,将有限的计算资源用来处理更重要的信息,是解决信息超载问题的主要手段.
Attention分类
按照认知神经学中的注意力,可以总体上分为两类:
- 自上而下的有意识的注意力,称为聚焦式注意力(Focus Attention) 聚焦式注意力也常称为选择性注意力(Selective Attention)。聚焦式注意力是指有预定目的、依赖任务的,主动有意识地聚焦于某一对象的注
意力. - 自下而上的无意识的注意力,称为基于显著性的注意力(Saliency Based Attention).基于显著性的注意力是由外界刺激驱动的注意,不需要主动干预,也和任务无关.如果一个对象的刺激信息不同于其周围信息,一种无意识的“赢者通吃”(Winner-Take-All)或者门控(Gating)机制就可以把注意力转向这个对象.
Attention计算
用 X = [ x 1 , ⋯ , x N ] ∈ R D × N X=[x_1,\cdots,x_N]\in \mathbb{R}^{D\times N} X=[x1,⋯,xN]∈RD×N表示 N N N组输入信息,其中 D D D维向量 x n ∈ R D , n ∈ [ 1 , N ] x_n \in \mathbb{R}^D,n\in [1,N] xn∈RD,n∈[1,N]表示一组输入信息.为了节省计算资源,不需要将所有信息都输入神经网络,只需要从 X X X中选择一些和任务相关的信息.注意力机制的计算可以分为两步:一是在所有输入信息上计算注意力分布,二是根据注意力分布来计算输入信息的加权平均.
注意力分布
为了从 N N N个输入向量 [ x 1 , ⋯ , x N ] [x_1,\cdots,x_N] [x1,⋯,xN]中选择出和某个特定任务相关的信息,我们需要引入一个和任务相关的表示,称为查询向量(Query Vector),并通过一个打分函数来计算每个输入向量和查询向量之间的相关性。
给定一个和任务相关的查询向量 q q q,我们用注意力变量 z ∈ [ 1 , N ] z \in[1,N] z∈[1,N]来表示被选择信息的索引位置,即 z = n z=n z=n表示选择了第 n n n个输入向量.为了方便计算,我们采用一种“软性”的信息选择机制.首先计算在给定 q q q和 X X X下,选择第 n n n个输入向量的概率 α n \alpha_n αn,
α n = p ( z = n ∣ X , q ) = s o f t m a x ( s ( x n , q ) ) = e x p ( s ( x n , q ) ) ∑ j = 1 N e x p ( s ( x j , q ) ) \alpha_n=p(z=n\vert X,q)={\rm softmax}\left(s(x_n,q)\right)=\frac{{\rm exp}\left(s(x_n,q)\right)}{\sum_{j=1}^N{\rm exp}\left(s(x_j,q)\right)} αn=p(z=n∣X,q)=softmax(s(xn,q))=∑j=1Nexp(s(xj,q))exp(s(xn,q))
其中
α
n
\alpha_n
αn称为注意力分布(Attention Distribution),
s
(
x
,
q
)
s(x,q)
s(x,q) 为注意力打分函数,
可以使用以下几种方式来计算:
- 加性模型
s ( x , q ) = v ⊤ tanh ( W x + U q ) s(x,q)=v^\top\tanh(Wx+Uq) s(x,q)=v⊤tanh(Wx+Uq)
- 点积模型
s ( x , q ) = x ⊤ q s(x,q)=x^\top q s(x,q)=x⊤q
- 缩放点积模型
s ( x , q ) = x ⊤ q D s(x,q)=\frac{x^\top q}{\sqrt{D}} s(x,q)=Dx⊤q
- 双线性模型
s ( x , q ) = x ⊤ W q s(x,q)=x^\top Wq s(x,q)=x⊤Wq
其中 W , U , v W,U,v W,U,v为可学习的参数, D D D为输入向量的维度.
当输入向量的维度 D D D比较高时,点积模型的值通常有比较大的方差,从而导致 S o f t m a x {\rm Softmax} Softmax函数的梯度会比较小.因此,缩放点积模型可以较好地解决这个问题. 双线性模型是一种泛化的点积模型.假设 W = U ⊤ V W=U^\top V W=U⊤V,双线性模型可以写为 s ( x , q ) = x ⊤ U ⊤ V q = ( U x ) ⊤ ( V q ) s(x,q)=x^\top U^\top Vq=(Ux)^\top (Vq) s(x,q)=x⊤U⊤Vq=(Ux)⊤(Vq),即分别对 x x x和 q q q进行线性变换后计算点积.相比点积模型,双线性模型在计算相似度时引入了非对称性.
加权平均
注意力分布 α n \alpha_n αn可以解释为在给定任务相关的查询 q q q时,第 n n n个输入向量受关注的程度.我们采用一种“软性”的信息选择机制对输入信息进行汇总,即
a t t ( X , q ) = ∑ n = 1 N α n x n {\rm att}(X,q)=\sum_{n=1}^N\alpha_nx_n att(X,q)=n=1∑Nαnxn
Attention机制的变体
硬性注意力
之前提到的注意力是软性注意力,其选择的信息是所有输入信息在注意力分布下的期望。
此外,还有一种注意力是只关注到某一个位置上的信息,叫做硬性注意力(hard attention)。硬性注意力有两种实现方式:
(1)一种是选取最高概率的输入信息;
(2)另一种硬性注意力可以通过在注意力分布式上随机采样的方式实现。
硬性注意力的一个缺点是基于最大采样或随机采样的方式来选择信息,使得最终的损失函数与注意力分布之间的函数关系不可导,无法使用反向传播算法进行训练.因此,硬性注意力通常需要使用强化学习来进行训练.为了使用反向传播算法,一般使用软性注意力来代替硬性注意力.
键值对注意力
更一般地,我们可以用键值对(key-value pair)格式来表示输入信息,其中“键”用来计算注意力分布 α n \alpha_n αn,“值”用来计算聚合信息
用 ( K , V ) = [ ( k 1 , v 1 ) , ⋯ , ( k N , v N ) ] (K,V)=[(k_1,v_1),\cdots,(k_N,v_N)] (K,V)=[(k1,v1),⋯,(kN,vN)]表示𝑁 组输入信息,给定任务相关的查询向量 q q q时,注意力函数为
α n = exp ( s ( k i , q ) ) ∑ j exp ( s ( k j , q ) ) \alpha_n = \frac{\exp \left(s(k_i,q)\right)}{\sum_{j}\exp\left(s(k_j,q)\right)} αn=∑jexp(s(kj,q))exp(s(ki,q))
a t t ( ( K , V ) , q ) = ∑ n = 1 N α n v n {\rm att}\left((K,V),q\right)=\sum_{n=1}^N\alpha_n v_n att((K,V),q)=n=1∑Nαnvn
其中
s
(
k
n
,
q
)
s(k_n,q)
s(kn,q)为打分函数,当
K
=
V
K=V
K=V时,键值对模式等价于普通的注意力机制。
多头注意力
多头注意力(Multi-Head Attention)是利用多个查询
Q
=
[
q
1
,
⋯
,
q
M
]
Q=[q_1,\cdots,q_M]
Q=[q1,⋯,qM],来
并行地从输入信息中选取多组信息.每个注意力关注输入信息的不同部分.
a t t ( ( K , V ) , Q ) = a t t ( ( K , V ) , q 1 ) ⊕ ⋯ ⊕ a t t ( ( K , V ) , q M ) {\rm att}\left((K,V),Q\right) = {\rm att}\left((K,V),q_1\right)\oplus\cdots\oplus{\rm att}\left((K,V),q_M\right) att((K,V),Q)=att((K,V),q1)⊕⋯⊕att((K,V),qM)
Attention机制处理长距离序列的优势
卷积网络与循环网络处理长距离序列
当使用神经网络来处理一个变长的向量序列时,我们通常可以使用卷积网络或循环网络进行编码来得到一个相同长度的输出向量序列,如图所示:
基于卷积或循环网络的序列编码都是一种局部的编码方式,只建模了输入信息的局部依赖关系.虽然循环网络理论上可以建立长距离依赖关系,但是由于信息传递的容量以及梯度消失问题,实际上也只能建立短距离依赖关系.
寻找有效处理长距离序列的方法
如果要建立输入序列之间的长距离依赖关系,可以使用以下两种方法:
- 一种方法是增加网络的层数,通过一个深层网络来获取远距离的信息交互;
- 另一种方法是使用全连接网络.全连接网络是一种非常直接的建模远距离依赖的模型,但是无法处理变长的输入序列.不同的输入长度,其连接权重的大小也是不同的.这时我们就可以利用注意力机制来“动态”地生成不同连接的权重,这就是自注意力模型(Self-Attention Model).
Self-Attention Model
为了提高模型能力,自注意力模型经常采用查询-键-值(Query-Key-Value,QKV)模式
假设输入序列为 X = [ x 1 , ⋯ , x N ] ∈ R D x × N X=[x_1,\cdots,x_N]\in\mathbb{R}^{D_x\times N} X=[x1,⋯,xN]∈RDx×N输出序列为 H = [ h 1 , ⋯ , h N ] ∈ R D v × N H=[h_1,\cdots,h_N]\in \mathbb{R}^{D_v \times N} H=[h1,⋯,hN]∈RDv×N,自注意力模型的具体计算过程如下:
对于每个输入 x i x_i xi,我们首先将其线性映射到三个不同的空间,得到查询向量 q i ∈ R D k q_i \in \mathbb{R}^{D_k} qi∈RDk,键向量 k i ∈ R D k k_i \in \mathbb{R}^{D_k} ki∈RDk和值向量 v i ∈ R D v v_i \in \mathbb{R}^{D_v} vi∈RDv。
对于整个输入序列 X X X,线性映射过程可以缩写为
Q = W q X K = W k X V = W v X Q = W_q X\\ K = W_k X\\ V = W_v X Q=WqXK=WkXV=WvX
对于每一个查询向量 q n ∈ Q q_n\in Q qn∈Q,利用注意力机制,可以得到输出向量 h n h_n hn.
h n = a t t ( ( K , V ) , q n ) = ∑ j = 1 N α n j v j = ∑ j = 1 N s o f t m a x ( s ( k j , q n ) ) v j \begin{align} h_n &= {\rm att}\left((K,V),q_n\right)\\ &=\sum_{j=1}^N \alpha_{nj}v_j\\ &=\sum_{j=1}^N {\rm softmax}\left(s(k_j,q_n)\right)v_j \end{align} hn=att((K,V),qn)=j=1∑Nαnjvj=j=1∑Nsoftmax(s(kj,qn))vj
其中 n , j ∈ [ 1 , ⋯ , N ] n,j\in[1,\cdots,N] n,j∈[1,⋯,N]为输出和输入向量序列的位置, α n j \alpha_{nj} αnj表示第 n n n个输出关注到第 j j j个输入的权重
如果使用缩放点积(Scaled Dot-Product)来作为注意力打分函数,输出向量序列可以简写为
H = V s o f t m a x ( K ⊤ Q D k ) H=V{\rm softmax}\left(\frac{K^\top Q}{\sqrt{D_k}}\right) H=Vsoftmax(DkK⊤Q)
可以看到 Scaled Dot-Product Attention 有个缩放因子 D k \sqrt{D_k} Dk,为什么要加这个缩放因子呢?
如果 D k D_k Dk很小, additive attention 和 dot-product attention 相差不大。
但是如果 D k D_k Dk很大,点乘的值很大,如果不做 scaling,结果就没有 additive attention 好。
另外,点乘结果过大,使得经过 softmax 之后的梯度很小,不利于反向传播,所以对结果进行 scaling。
下图给出全连接模型和自注意力模型的对比,其中实线表示可学习的权重,虚线表示动态生成的权重.由于自注意力模型的权重是动态生成的,因此可以处理变长的信息序列.
自注意力模型可以扩展为多头自注意力(Multi-Head Self-Attention)模型,在多个不同的投影空间中捕捉不同的交互信息。
Multi-Head Self-Attention
自注意力模型可以看作在一个线性投影空间中建立 H H H中不同向量之间的交互关系.为了提取更多的交互信息,我们可以使用多头自注意力(Multi-Head Self-Attention),在多个不同的投影空间中捕捉不同的交互信息
假设在 M M M个投影空间中分别应用自注意力模型,有
∀ m ∈ [ 1 , ⋯ , M ] , Q m = W q m H , K m = W k m H , V m = W v m H h e a d i = s e l f - a t t ( Q m , K m , V m ) M u l t i H e a d ( H ) = W o C o n c a t ( h e a d 1 , ⋯ , h e a d m ) \forall m \in [1,\cdots,M],\, Q_m = W_{q}^m H ,K_m = W_k^m H , V_m = W_v^m H\\ {\rm head}_i = {\rm self\text{-}att}(Q_m,K_m,V_m)\\ {\rm MultiHead}(H)=W_{o}{\rm Concat}({\rm head}_1,\cdots,{\rm head}_m) ∀m∈[1,⋯,M],Qm=WqmH,Km=WkmH,Vm=WvmHheadi=self-att(Qm,Km,Vm)MultiHead(H)=WoConcat(head1,⋯,headm)
Transformer
Transformer的本质上是一个Encoder-Decoder的结构
Encoder
Positional Encoding
对于一个序列 x 1 : T x_{1:T} x1:T,我们可以构建一个含有多层多头自注意力模块的模型来对其进行编码.由于自注意力模型忽略了序列 x 1 : T x_{1:T} x1:T 中每个 x t x_t xt 的位置信息,因此需要在初始的输入序列中加入位置编码(Positional Encoding)来进行修正.对于一个输入序列 x 1 : T ∈ R D × T x_{1:T} \in \mathbb{R}^{D\times T} x1:T∈RD×T,令
H ( 0 ) = [ e x 1 + p 1 , ⋯ , e x T + p T ] H^{(0)}=[e_{x_1}+p_1,\cdots ,e_{x_T} + p_T] H(0)=[ex1+p1,⋯,exT+pT]
其中 e x t ∈ R D e_{x_t}\in \mathbb{R}^D ext∈RD为词 x t x_t xt的嵌入向量表示, p t ∈ R D p_t \in \mathbb{R}^D pt∈RD为位置 t t t的向量表示,即位置编码. p t p_t pt可以作为可学习的参数,也可以通过下面方式进行预定义:
p t , 2 i = sin ( t / 1000 0 2 i / D ) p t , 2 i + 1 = cos ( t / 1000 0 2 i / D ) \begin{align} p_{t,2i}&=\sin{\left(t/10000^{2i/D}\right)}\\ p_{t,2i+1}&=\cos{\left(t/10000^{2i/D}\right)} \end{align} pt,2ipt,2i+1=sin(t/100002i/D)=cos(t/100002i/D)
其中 p t , 2 i p_{t,2i} pt,2i表示第 t t t个位置的编码向量的第 2 i 2i 2i维, D D D是编码向量的维度.
位置编码拓展阅读
Transformer学习笔记一:Positional Encoding(位置编码) - 知乎 (zhihu.com)
一文读懂Transformer模型的位置编码 - 知乎 (zhihu.com)
Encoder block
给定第 l − 1 l-1 l−1层的隐状态 H ( l − 1 ) H^{(l-1)} H(l−1),第 l l l层的隐状态 H ( l ) H^{(l)} H(l)可以通过一个多头自注意力模块和一个非线性的前馈网络得到.每次计算都需要残差连接以及层归一化操作.具体计算为
Z ( l ) = n o r m ( H ( l − 1 ) + M u l t i H e a d ( H ( l − 1 ) ) ) H ( l ) = n o r m ( Z ( l ) + F N N ( Z ( l ) ) ) \begin{align} Z^{(l)}&={\rm norm}\left(H^{(l-1)}+{\rm MultiHead}\left(H^{(l-1)}\right)\right)\\ H^{(l)} &= {\rm norm}\left(Z^{(l)}+{\rm FNN}\left(Z^{(l)}\right)\right) \end{align} Z(l)H(l)=norm(H(l−1)+MultiHead(H(l−1)))=norm(Z(l)+FNN(Z(l)))
其中 n o r m ( ⋅ ) {\rm norm}(⋅) norm(⋅)表示层归一化, F N N ( ⋅ ) {\rm FNN}(⋅) FNN(⋅)表示逐位置的前馈神经网络(Position-wise Feed-Forward Network),是一个简单的两层网络.对于输入序列中每个位置上向量 z ∈ Z ( l ) z\in Z^{(l)} z∈Z(l),
F N N ( z ) = W 2 R e L u ( W 1 z + b 1 ) + b 2 {\rm FNN}(z)=W_2{\rm ReLu}\left(W_1z+b_1\right)+b_2 FNN(z)=W2ReLu(W1z+b1)+b2
其中 W 1 , W 2 , b 1 , b 2 W_1,W_2,b_1,b_2 W1,W2,b1,b2为网络参数.
编码器的输入为序列
x
1
:
S
x_{1:S}
x1:S,输出为一个向量序列
H
e
n
c
=
[
h
1
e
n
c
,
⋯
,
h
S
e
n
c
]
H^{enc}=[h_1^{enc},\cdots,h_{S}^{enc}]
Henc=[h1enc,⋯,hSenc].然后,用两个矩阵将
H
e
n
c
H^{enc}
Henc映射到
K
e
n
c
K^{enc}
Kenc和
V
e
n
c
V^{enc}
Venc作为键值对供解码器使用,即
K e n c = W k ′ H e n c V e n c = W v ′ H e n c \begin{align} K^{enc}&=W_k'H^{enc}\\ V^{enc}&=W_v'H^{enc} \end{align} KencVenc=Wk′Henc=Wv′Henc
其中 W k ′ , W v ′ W_k',W_v' Wk′,Wv′为线性映射的参数矩阵。
Decoder
- 包含两个 Multi-Head Attention 层。
- 第一个 Multi-Head Attention 层采用了 Masked 操作。
- 第二个 Multi-Head Attention 层的K, V矩阵使用 Encoder 的编码信息矩阵H进行计算,而Q使用上一个 Decoder block 的输出计算。
- 最后有一个 Softmax 层计算下一个翻译单词的概率。
Masked Multi-Head Attention
Decoder block 的第一个 Multi-Head Attention 采用了 Masked 操作,因为在翻译的过程中是顺序翻译的,即翻译完第 i i i个单词,才可以翻译第 i + 1 i+1 i+1个单词。通过 Masked 操作可以防止第 i i i个单词知道 i + 1 i+1 i+1个单词之后的信息。Mask 操作是在 Self-Attention 的 Softmax 之前使用的.
Padding Mask
对于不定长输入序列,我们要对输入序列进行对齐。具体来说,就是给在较短的序列后面填充0。但是如果输入的序列太长,则是截取左边的内容,把多余的直接舍弃。因为这些填充的位置没什么意义,所以我们的Attention机制不应该把注意力放在这些位置上,对此我们需要进行一些处理。
具体的做法是,把这些位置的值加上一个非常大的负数(负无穷),这样的话,经过softmax,这些位置的概率就会接近0。而我们的padding mask 实际上是一个张量,每个值都是一个Boolean,值为false的地方就是我们要进行处理的地方。
Sequence Mask
sequence mask是为了使得Decoder不能看见未来的信息。也就是对于一个序列,在time_step为t的时刻,我们的解码输出应该只能依赖于t时刻之前的输出,而不能依赖t之后的输出。因此我们需要想一个办法,把t之后的信息给隐藏起来。 那么具体怎么做呢?也很简单:产生一个上三角矩阵,上三角的值全为0。把这个矩阵作用在每一个序列上,就可以达到我们的目的。
sequence mask的目的是防止Decoder “seeing the future”,就像防止考生偷看考试答案一样。这里mask是一个下三角矩阵,对角线以及对角线左下都是1,其余都是0。下面是个10维度的下三角矩阵
输出为 H d e c = [ h 1 d e c , ⋯ , h t d e c ] H^{dec}=[h_1^{dec},\cdots,h_t^{dec}] Hdec=[h1dec,⋯,htdec]
Mask方式阅读
https://luweikxy.gitbook.io/machine-learning-notes/self-attention-and-transformer
Multi-Head Attention
将 h t d e c h_t^{dec} htdec进行线性映射后得到 q t d e c q_t^{dec} qtdec,将 q t d e c q_t^{dec} qtdec作为查询向量,通过键值对注意力机制从输入 ( K e n c , V e n c ) (K^{enc},V^{enc}) (Kenc,Venc)中选取有用的信息。
面试题
Transformer为何使用多头注意力机制
类似于cnn中多个卷积核的作用,使用多头注意力,能够从不同角度提取信息,提高信息提取的全面性。
Encoder端和Decoder端是如何进行交互的?
Cross Self-attention,Decoder提供Q,Encoder提供K,V。
Transformer优缺点
优点
- 效果好
- 其次它不是类似RNN的顺序结构,因此具有更好的并行性,符合现有的GPU框架。
- 从计算一个序列长度为n的信息要经过的路径长度来看, CNN需要增加卷积层数来扩大视野,RNN需要从1到n逐个进行计算,而Self-attention只需要一步矩阵计算就可以。Self-Attention可以比RNN更好地解决长时依赖问题。
- Self-Attention模型更可解释,Attention结果的分布表明了该模型学习到了一些语法和语义信息。
缺点
- 完全基于self-attention,对于词语位置之间的信息有一定的丢失,虽然加入了positional encoding来解决这个问题,但也还存在着可以优化的地方。
- 局部信息的获取不如RNN和CNN强:
- 只能处理固定长度数据
Transformer Encoder 有什么子层?
Encoder由六个相同层构成,每层都有两个子层:多头自注意力层和全连接的前馈神经网络(Linear+relu+dropout+Linear)。使用残差连接和层归一化连接两个子层。
Transformer与LSTM对比
Transformer和LSTM的最大区别,就是LSTM的训练是迭代的,是一个接一个字的来,当前这个字过完LSTM单元,才可以进下一个字,而Transformer的训练是并行的,就是所有字是全部同时训练的,这样就大大加快了计算效率
Transformer的残差结构及意义
解决梯度消失,防止过拟合
Decoder阶段的多头自注意力和Encoder的多头自注意力有什么区别?
decoder为Masked Multi-Head Attention
为什么decoder自注意力需要进行sequence mask
为了使得Decoder不能看见未来的信息。
Transformer attention计算为什么要在softmax这一步之前除以 d k \sqrt{d_k} dk
- 取决于Softmax的性质,如果softmax内计算的数过大或者过小,可能导致Softmax后的结果为0,导致梯度消失
- 为什么是 d k d_k dk。假设Q、K中元素的值分布在[0,1],softmax的计算中,分母涉及了一次对所有位置的求和,整体的分布就会扩大到 [ 0 , d k ] [0,d_k] [0,dk]
Transformer attention计算注意力矩阵的时候如何对padding做mask操作的?
把这些位置的值加上一个非常大的负数(一般来说-1000就可以),这样的话,经过softmax,这些位置的概率就会接近0。
Transformer attention的注意力矩阵的计算为什么用乘法而不是加法?
在计算复杂度上,乘法和加法理论上的复杂度相似,但是在实践中,乘法可以利用高度优化的矩阵乘法代码(一般的深度学习框架底层都有对矩阵运算的一些优化,有很多的并行算法和硬件加速)使得点乘速度更快,空间利用率更高。
Transformer、LSTM和单纯的前馈神经网络比,有哪些提升?
LSTM相比于单纯的前馈神经网络,首先具有理解文本的语序关系的能力(RNN)。除此之外,又解决了RNN在处理长序列时发生的梯度消失和梯度爆炸的问题。
Transformer进一步解决了RNN、LSTM等模型的长距离依赖问题,能够理解更长的上下文语义。可以并行化,所要的训练时间更短。
简单介绍一下Transformer的位置编码?有什么意义和优缺点?
因为self-attention是位置无关的,无论句子的顺序是什么样的,通过self-attention计算的token的hidden embedding都是一样的,这显然不符合人类的思维。因此要有一个办法能够在模型中表达出一个token的位置信息,transformer使用了固定的positional encoding来表示token在句子中的绝对位置信息。