在今年1月份期间曾简单翻译了一篇关于Attention机制的文章Attention Model注意力机制。虽然,翻译了这篇文章,但由于当时对RNN、Seq2Seq等知识只处于初步了解阶段,对Attention机制总感觉是一知半解。虽然很努力的去看各种资料,但还是感觉不能够理解。经过最近一段时间的学习,对RNN、Seq2Seq有了一定的理解且进行了一定的实践,再阅读Attention相关的论文和博客就感觉不是那么吃力了,现在对最近学习的Attention机制相关的知识进行简单地总结。
Encoder-Decoder简介
Encoder-Decoder框架是深度学习的一种模型框架,是一个解决问题的通用框架,主要解决Seq2Seq类问题。Encoder-Decoder框架的流程可以理解为:先编码,存储,最后解码。用人脑流程来类比,先看到的是源Sequence,人脑根据自己的知识理解这个Sequence,并将理解的记忆下来,形成记忆(对应Context),这个过程叫Encoder。然后,再根据这个Context,针对不同的问题利于Context进行解答,形成答案并输出,这个过程叫Decoder。NLP的许多经典任务都可以抽象为Encode-Decoder,比如:机器翻译、文本摘要、阅读理解及语音识别等。模型的框架如下图所示:
图片来自于[3]
上图所示的框架中,在Encoder阶段,首先将输入的序列$x_1,x_2,…,x_4$进行编码,编码成语义表示$c$:
$$c = f(x_1,x_2,x_3,x_4)$$
$f$一般是非线性函数,称为编码器,一般在文本处理和语音识别任务中通常采用RNN模型,图像处理中一般采用CNN模型。
在Decoder阶段,则是根据语义表示$c$和之前的的生成历史信息$y_1,y_2,…,y_{i-1}$来生成i时刻要生成的$y_i$:
$$
y_i = g(C, y_1,y_2,…,y_{i-1})
$$
每个$y_i$都依次产生。Encoder-Decoder模型结果不限制输入和输出的序列长度,因此应用的范围非常广泛。
引入Attention机制
使用Encode-Decoder时,一般会使用RNN模型对输入的序列进行学习,将输入序列编码成固定长度的向量表示。它存在一个问题:输入序列不论长短都会被编码成一个固定长度的向量表示,而解码器则受限于该固定长度的向量表示。这个问题限制了模型的性能,尤其是当输入序列较长时,模型的学习效果会很差(解码效果很差)。
为什么要引入Attention?
- 当输入序列非常长时,会损失一些信息,模型难以学到合理的向量表示;
- 序列输入时,随着序列的不断增长,原始根据时间步的方式表现越来越差。这是由于原始的这种时间步模型设计的结构有缺陷,即所有的上下文输入信息都被限制到固定的长度,整个模型的能力都同样受到限制;
- 编码器的结构无法解释,也就导致了其无法设计;
Attention机制就是根据当前的某个状态,从已有的大量信息中选择性的关注部分信息的方法。Attention机制打破了传统Encoder-Decoder结构在解码时都依赖于内部一个固定长度向量的限制。基本思想是:通过保留编码器对输入序列编码的中间结果,然后训练一个模型来对这些输入进行选择性的学习并且在输出时将输出序列与之进行关联,不再是使用固定的向量$c$,而是在模型输出时会选择性地专注考虑输入中的对应相关的信息。
Attention机制可以理解成:当我们人在看一样东西的时候,我们当前时刻关注的一定是我们当前正在看的这样东西的某一地方。换句话说,当我们目光移到别处时,注意力随着目光的转移也在转移。这意味着,当人们注意到某个目标或某个场景时,该目标内部以及该场景内每一处空间位置上的注意力分布是不一样的。
个人对Attention的理解是,在Encoder-Decoder过程中,在Decoder阶段不是使用固定的Context向量,而是在解码阶段,动态地根据当前输出,利用特定的方式从众多的输入信息中选择对当前任务目标更关键的信息。不同论文提出的Attention方法一般的区别就是在于从输入信息中选择信息的方式。下面就来看一些论文中提出的Attention机制。
一些Attention
基础seq2seq模型中,Decoder每次的输入是$[y_{i-1},s_{i-1},c]$,这里的前两者是上一个cell的输出和隐藏层状态,$c$是Encoder最后一个cell的隐状态。Attention就是将固定的$c$变为$c^{‘}(h(1),h(2),…,h(t))$。不同的Attention,$c^{‘}(h(1),h(2),…,h(t))$的计算方式是不同的。
Bahdanau Attention
这篇论文中的Attention可以看成是Soft Attention的一种,其上下文向量$c$的计算方式如下:
$$\begin{align}
&e_{ij} = v_a^T tanh(W_as_{i-1}+U_ah_j)\\
&\alpha_{ij} = \frac {exp(e_{ij})}{\sum_j exp(e_{ij})}\\
&c_{i} = \sum_j \alpha_{ij}h_j
\end{align}
$$
相当于构建了一个以所有Encoder隐藏层向量为输入的全连接层,通过BP在训练的时候训练好权重$W_a$、$h_j$和$U_a$。$\alpha_{ij}$表示Encoder隐藏层向量$h_j$的权重。$c_{ij}$为语义向量。$v_a$是一个输入长度的one-hot向量,用来表示输入的词汇。
现在Decoder隐藏层向量与前一时刻状态,输出以及语义向量有关:
$$s_i = f(s_{i-1},y_{i-1}, c_i)$$
计算出$s_i$隐层状态后,解码过程根据$c_i$、上一步的输出$y_{i-1}$、当前的RNN隐向量$s_i$计算得到当前时间步的输出概率分布,g为非线性函数:
$$p(y_i|y_1,…,y_{i-1},x)=g(y_{i-1},s_i,c_i)$$
整个解码的流程如下:
Luong Attention
论文中的$e_{ij}$计算方式如下:
$$
\begin{align}
&e_{ij} = h_j^T W_a s_{i-1}\\
&\alpha_{ij}=\frac {exp(e_{ij})}{\sum_j exp(e_{ij})}\\
&c_{ij} = \sum_j \alpha_{ij}h_j
\end{align}
$$
Decoder的过程如下:
$$
\begin{align}
&p(y_i|y_1,…,y_{i-1},x) = softmax(W_s\hat h_i)\\
&\hat h_i = tanh(W_c[c_i;s_i])\\
&s_i = f(s_{i-1}, y_{i-1},\hat h_{i-1})\\
&c_{ij}=align(s_i, h_j)=\sum_j \alpha_{ij}h_j
\end{align}
$$
Luong中和了Soft Attention和Hard Attention的思想,提出了折中的方法,只考虑附近窗口内的单词贡献度。在选取$e_{ij}$上,尝试了点乘和拼接两种,点乘简化了运算过程,提高了计算效率。
Hard Attention指只考虑Attention分数最高的词,其余词权重归为0。Hard Attention有两种实现方式:(一)选取最相似的输入信息;(二)通过在注意力分布式上随机采样;Hard Attention的优点是节约时间,缺点是丢失了非常多的信息。在图像中表现不错,但在NLP中很少用。基于最大采样或随机采样的方式来选择信息,因此最终的损失函数与注意力分布之间的函数关系不可导,因此无法使用反向传播算法进行训练。
Self Attention
Self Attention也被称为Intra Attention(内部Attention),在一般任务Encoder-Decoder框架中,输出和输出的内容是不一致的,而Self Attention,指的不是输入和输出之间的Attention,而是输入内部元素之间或输出内部元素之间发生Attention。Self Attention其实就是除了$s$和$h$还加入了输出$v$,三者一起进行Attention Score的打分。计算方式如下:
$$
\begin{align}
&u_t = tanh(Wh_t)\\
&\alpha_t = \frac {exp(score(u_t,u))} {\sum_{t^{‘}=1}^Texp(score(u_{t^{‘}},u))}\\
&c_t = \sum_{t=1}^T \alpha_t h_t
\end{align}
$$
公式中的score可以选择任意的公式;$u$是一个可训练的参数,随机初始化初始状态。
引入Self Attention后能够捕获句子中长距离的相互依赖的特征,因为如果是RNN或者是LSTM,需要依次序序列计算,对于远距离的相互依赖的特征,要经过若干时间步步骤的信息累积才能将两者联系起来,而距离越远被捕获的可能性越小。但是Self Attention在计算过程中会直接将句子中任意两个单词的联系通过一个计算步骤直接联系起来,所以远距离依赖特征之间的距离极大缩短,有利于有效地利用这些特征。除此外,Self Attention 对于增加计算的并行性也有直接帮助作用。[3]
除了上面介绍的Attention,对于CNN也可以进行Attention的设计,具体可以参考论文《ABCNN: Attention-Based Convolutional Neural Network for Modeling Sentence Pairs》。
Attention机制的通用理解
Attention机制可以通用的理解为一个查询(query)到一系列(键key-值value)的映射,如下图所示:
图片来自于[3]
可以这样理解Attention机制,将输入中的构成元素想象成由一系列的
$$Attention(Query,input) = \sum_{i=1} Score(Query, Key_i)*Value_i$$
在Encoder-Decoder中,Decode的第t步的Hidden State可以看成Query,Encoder的Hidden states是values。换句话说,Attention机制也是一种根据一些其他向量表达(Query),从向量表达集合(values)中获得特定的向量表达的方法。加权和是已有信息(Values)的选择性摘要信息(selective summary),其中摘要信息是查询(Query)根据自己需要选择确定要关注的信息;在机器翻译的例子中,因为在计算Attention的过程中,输入中的Key和Value合二为一,指向的是同一个东西,也就是输入句子中每个单词对应的语义编码。
Attention机制的计算过程,对目前大多数方法进行抽象,可以归纳为三个过程:第一个阶段是根据Query和每个Key计算两者之间的相似性或者相关性;第二个阶段是对第一个阶段的原始分值进行归一化处理,一般采用Softmax计算出权重系数;第三个阶段是根据权重系数对Value进行加权求和。整体流程如下图所示:
图片来自于[3]
计算Query和每个Key之间的相似性或相关性一般有三种方式:
- $dot: Q^TK_i$
- $General: Q^TW_aK_i$
- $Concat:W_a[Q;K_i]$
- $Preceptron:V_a^Ttanh(W_aQ + U_aK_i)$
第二个阶段和第三个阶段的计算如下面的公式所示:
$$
\begin{align}
&a_i = softmax(f(Q,K_i)) = \frac {exp(f(Q,K_i))}{\sum_j exp(f(Q, K_j))}\\
&Attention(Q,K,V) = \sum_i a_iV_i
\end{align}
$$
总结
- Attention机制其实就是一种加权求和机制;
- Attention的权重由当前的Hidden state和需要计算的Hidden state通过一定的方式计算出Score,然后在通过Softmax得到;
- Attention可以用来做什么:主要是关注长序列中的关键信息;
参考文献
- 注意力机制(Attention Mechanism)在自然语言处理中的应用
- 自然语言处理中的自注意力机制(Self-attention Mechanism)
- 深度学习中的注意力机制
- Attention Model(mechanism)的套路
- Bahdanau, D., Cho, K. & Bengio, Y. Neural Machine Translation by Jointly Learning to Align and Translate. Iclr 2015 1–15 (2014).
- Luong, M. & Manning, C. D. Effective Approaches to Attention-based Neural Machine Translation. 1412–1421 (2015).
- Zhouhan Lin, Minwei Feng, Cicero Nogueira dos Santos, Mo Yu, Bing Xiang, Bowen Zhou, and Yoshua Bengio. A structured self-attentive sentence embedding. arXiv preprint arXiv:1703.03130, 2017.