注意力机制模仿了生物观察行为的内部过程,即一种将内部经验和外部感受对齐从而增长部分区域的观察精细度的机制。例如人的视觉在处理一张图片时,会经过快速扫描全局图像,得到须要重点关注的目标区域,也就是注意力焦点。而后对这一区域投入更多的注意力资源,以得到更多所须要关注的目标的细节信息,并抑制其它无用信息。数组
图片来源:深度学习中的注意力机制,其中红色区域表示更关注的区域。网络
目前大多数的注意力模型都是依附在 Encoder-Decoder 框架下,但并非只能运用在该模型中,注意力机制做为一种思想能够和多种模型进行结合,其自己不依赖于任何一种框架。Encoder-Decoder 框架是深度学习中很是常见的一个模型框架,例如在 Image Caption 的应用中 Encoder-Decoder 就是 CNN-RNN 的编码 - 解码框架;在神经网络机器翻译中 Encoder-Decoder 每每就是 LSTM-LSTM 的编码 - 解码框架,在机器翻译中也被叫作 Sequence to Sequence learning 。框架
所谓编码,就是将输入的序列编码成一个固定长度的向量;解码,就是将以前生成的固定向量再解码成输出序列。这里的输入序列和输出序列正是机器翻译的结果和输出。函数
为了说明 Attention 机制的做用,以 Encoder-Decoder 框架下的机器翻译的应用为例,该框架的抽象表示以下图:学习
为了方便阐述,在选取 Encoder 和 Decoder 时都假设其为 RNN。在 RNN 中,当前时刻隐藏状态 \(h_t\) 是由上一时刻的隐藏状态 \(h_{t-1}\) 和当前时刻的输入 \(x_t\) 决定的,如公式(1)所示:大数据
\[h_t = f(h_{t-1},x_t)\tag{1}\]ui
在 编码阶段,得到各个时刻的隐藏层状态后,经过把这些隐藏层的状态进行汇总,能够生成最后的语义编码向量 \(C\) ,如公式(2)所示,其中 \(q\) 表示某种非线性神经网络,此处表示多层 RNN 。编码
\[C=q(h_1,h_2,\cdots,h_{T_x})\tag{2}\]spa
在一些应用中,也能够直接将最后的隐藏层编码状态做为最终的语义编码 \(C\),即知足:.net
\[C=q(h_1,h_2,\cdots,h_{T_x})=h_{T_x}\tag{3}\]
在 解码阶段,须要根据给定的语义向量 \(C\) 和以前已经生成的输出序列 \(y_1,y_2,\cdots,y_{t-1}\) 来预测下一个输出的单词 \(y_t\),即知足公式(4):
\[y_t=\arg \max P(y_t)=\prod_{t=1}^{T}p(y_t|y_1,y_2,\cdots,y_{t-1},C)\tag{4}\]
因为咱们此处使用的 Decoder 是 RNN ,因此当前状态的输出只与上一状态和当前的输入相关,因此能够将公式(4)简写成以下形式:
\[y_t=g(y_{t-1},s_{t-1},C)\tag{5}\]
在公式(5)中,\(s_{t-1}\) 表示 Decoder 中 RNN 神经元的隐藏层状态,\(y_{t-1}\) 表示前一时刻的输出,\(C\) 表明的是编码后的语义向量,而 \(g(\cdot)\) 则是一个非线性的多层神经网络,能够输出 \(y_t\) 的几率,通常状况下是由多层 RNN 和 softmax 层组成。
Encoder-Decoder 框架虽然应用普遍,可是其存在的局限性也比较大。其最大的局限性就是 Encoder 和 Decoder 之间只经过一个固定长度的语义向量 \(C\) 来惟一联系。也就是说,Encoder 必需要将输入的整个序列的信息都压缩进一个固定长度的向量中,存在两个弊端:一是语义向量 C 可能没法彻底表示整个序列的信息;二是先输入到网络的内容携带的信息会被后输入的信息覆盖掉,输入的序列越长,该现象就越严重。这两个弊端使得 Decoder 在解码时一开始就没法得到输入序列最够多的信息,所以致使解码的精确度不够准确。
在上述的模型中,Encoder-Decoder 框架将输入 \(X\) 都编码转化为语义表示 \(C\),这就致使翻译出来的序列的每个字都是同权地考虑了输入中的全部的词。例如输入的英文句子是:Tom chase Jerry
,目标的翻译结果是:汤姆追逐杰瑞
。在未考虑注意力机制的模型当中,模型认为 汤姆
这个词的翻译受到 Tom
,chase
和 Jerry
这三个词的同权重的影响。可是实际上显然不该该是这样处理的,汤姆
这个词应该受到输入的 Tom
这个词的影响最大,而其它输入的词的影响则应该是很是小的。显然,在未考虑注意力机制的 Encoder-Decoder 模型中,这种不一样输入的重要程度并无体现处理,通常称这样的模型为 ** 分心模型 **。
而带有 Attention 机制的 Encoder-Decoder 模型则是要从序列中学习到每个元素的重要程度,而后按重要程度将元素合并。这就代表,在 Encoder 将输入的序列元素进行编码时,获得的不在是一个固定的语义编码 C ,而是存在多个语义编码,且不一样的语义编码由不一样的序列元素以不一样的权重参数组合而成。一个简单地体现 Attention 机制运行的示意图以下:
在 Attention 机制下,语义编码 C 就不在是输入序列 \(X\) 的直接编码了,而是各个元素按其重要程度加权求和获得的,即:
\[C_i=\sum_{j=0}^{T_x}{a_{ij}f(x_j)}\tag{6}\]
在公式(6)中,参数 \(i\) 表示时刻, \(j\) 表示序列中的第 \(j\) 个元素, \(T_x\) 表示序列的长度, \(f(\cdot)\) 表示对元素 \(x_j\) 的编码。
到目前为止,相信各位客官对 Attention 机制的思想和做用都有了必定的了解。接下来,咱们将对 Attention 机制的具体实现原理进行剖析。
Attention 机制的一个重点就是得到 attention value,即机器翻译中的语义编码 \(C_i\)。在上一节中咱们知道该值是经过输入元素按照不一样的权重参数组合而成的,因此咱们能够将其定义为一个 attention 函数,比较主流的 attention 函数的机制是采用键值对查询的方式,其工做实质以下图所示:
经过工做示意图咱们能够知道,一个 attention value 的得到须要通过三个阶段:
SoftMax()
进行归一化;在天然语言任务中,每每 Key 和 Value 是相同的。须要注意的是,计算出来的 attention value 是一个向量,表明序列元素 \(x_j\) 的编码向量,包含了元素 \(x_j\) 的上下文关系,即同时包含全局联系和局部联系。全局联系很好理解,由于在计算时考虑了该元素与其余全部元素的类似度计算;而局部联系则是由于在对元素 \(x_j\) 进行编码时,重点考虑与其类似度较高的局部元素,尤为是其自己。
相比于传统的 RNN 和 CNN,attention 机制具备以下优势:
一步到位的全局联系捕捉,且关注了元素的局部联系;attention 函数在计算 attention value 时,是进行序列的每个元素和其它元素的对比,在这个过程当中每个元素间的距离都是一;而在时间序列 RNNs 中,元素的值是经过一步步递推获得的长期依赖关系获取的,而越长的序列捕捉长期依赖关系的能力就会越弱。
并行计算减小模型训练时间;Attention 机制每一步的计算都不依赖于上一步的计算结果,所以能够并行处理。
模型复杂度小,参数少
但 attention 机制的缺点也比较明显,由于是对序列的全部元素并行处理的,因此没法考虑输入序列的元素顺序,这在天然语言处理任务中比较糟糕。由于在天然语言中,语言的顺序是包含了十分多的信息的,若是缺失了该部分的信息,则获得的结果每每会大大折扣。
简而言之,Attention 机制就是对输入的每一个元素考虑不一样的权重参数,从而更加关注与输入的元素类似的部分,而抑制其它无用的信息。其最大的优点就是能一步到位的考虑全局联系和局部联系,且能并行化计算,这在大数据的环境下尤其重要。同时,咱们须要注意的是 Attention 机制做为一种思想,并非只能依附在 Encoder-Decoder 框架下的,而是能够根据实际状况和多种模型进行结合。
该文仅是对 Attention 机制的思想和原理进行了分析,在具体的实现上还有许多的细节信息,包括和框架的结合方式,具体的数学计算,并行计算的过程以及具体的代码实现等,后续会持续更新 Attention 机制这些部分的内容。