Attention Model(注意力模型)学习大全

深度学习里的Attention model其实模拟的是人脑的注意力模型,举个例子来说,当我们观赏一幅画时,虽然我们可以看到整幅画的全貌,但是在我们深入仔细地观察时,其实眼睛聚焦的就只有很小的一块,这个时候人的大脑主要关注在这一小块图案上,也就是说这个时候人脑对整幅图的关注并不是均衡的,是有一定的权重区分的。这就是深度学习里的Attention Model的核心思想。

AM刚开始也确实是应用在图像领域里的,AM在图像处理领域取得了非常好的效果!于是,就有人开始研究怎么将AM模型引入到NLP领域。最有名的当属“Neural machine translation by jointly learning to align and translate”这篇论文了,这篇论文最早提出了Soft Attention Model,并将其应用到了机器翻译领域。后续NLP领域使用AM模型的文章一般都会引用这篇文章(目前引用量已经上千了!!!)

如下图所示,机器翻译主要使用的是Encoder-Decoder模型,在Encoder-Decoder模型的基础上引入了AM,取得了不错的效果:

Soft Attention Model:

这里其实是上面图的拆解,我们前面说过,“Neural machine translation by jointly learning to align and translate”这篇论文提出了soft Attention Model,并将其应用到了机器翻译上面。其实,所谓Soft,意思是在求注意力分配概率分布的时候,对于输入句子X中任意一个单词都给出个概率,是个概率分布。

即上图中的ci是对Encoder中每一个单词都要计算一个注意力概率分布,然后加权得到的。如下图所示:

其实有Soft AM,对应也有一个Hard AM。既然Soft是给每个单词都赋予一个单词对齐概率,那么如果不这样做,直接从输入句子里面找到某个特定的单词,然后把目标句子单词和这个单词对齐,而其它输入句子中的单词硬性地认为对齐概率为0,这就是Hard Attention Model的思想。Hard AM在图像里证明有用,但是在文本里面用处不大,因为这种单词一一对齐明显要求太高,如果对不齐对后续处理负面影响很大。

但是,斯坦福大学的一篇paper“Effective Approaches to Attention-based Neural Machine Translation”提出了一个混合Soft AM 和Hard AM的模型,论文中,他们提出了两种模型:Global Attention Model和Local Attention Model,Global Attention Model其实就是Soft Attention Model,Local Attention Model本质上是Soft AM和 Hard AM的一个混合。一般首先预估一个对齐位置Pt,然后在Pt左右大小为D的窗口范围来取类似于Soft AM的概率分布。

Global Attention Model和Local Attention Model

Global AM其实就是soft AM,Decoder的过程中,每一个时间步的Context vector需要计算Encoder中每一个单词的注意力权重,然后加权得到。

Local AM则是首先找到一个对其位置,然后在对其位置左右一个窗口内来计算注意力权重,最终加权得到Context vector。这其实是Soft AM和Hard AM的一个混合折中。

静态AM

其实还有一种AM叫做静态AM。所谓静态AM,其实是指对于一个文档或者句子,计算每个词的注意力概率分布,然后加权得到一个向量来代表这个文档或者句子的向量表示。跟soft AM的区别是,soft AM在Decoder的过程中每一次都需要重新对所有词计算一遍注意力概率分布,然后加权得到context vector,但是静态AM只计算一次得到句子的向量表示即可。(这其实是针对于不同的任务而做出的改变)

强制前向AM

Soft AM在逐步生成目标句子单词的时候,是由前向后逐步生成的,但是每个单词在求输入句子单词对齐模型时,并没有什么特殊要求。强制前向AM则增加了约束条件:要求在生成目标句子单词时,如果某个输入句子单词已经和输出单词对齐了,那么后面基本不太考虑再用它了,因为输入和输出都是逐步往前走的,所以看上去类似于强制对齐规则在往前走。

看了这么多AM模型以及变种,那么我们来看一看AM模型具体怎么实现,涉及的公式都是怎样的。

我们知道,注意力机制是在序列到序列模型中用于注意编码器状态的最常用方法,它同时还可用于回顾序列模型的过去状态。使用注意力机制,系统能基于隐藏状态 s_1,...,s_m 而获得环境向量(context vector)c_i,这些环境向量可以和当前的隐藏状态 h_i 一起实现预测。环境向量 c_i 可以由前面状态的加权平均数得出,其中状态所加的权就是注意力权重 a_i:

注意力函数 f_att(h_i,s_j) 计算的是目前的隐藏状态 h_i 和前面的隐藏状态 s_j 之间的非归一化分配值。

而实际上,注意力函数也有很多种变体。接下来我们将讨论四种注意力变体:加性注意力(additive attention)、乘法(点积)注意力(multiplicative attention)、自注意力(self-attention)和关键值注意力(key-value attention)。

加性注意力(additive attention)

加性注意力是最经典的注意力机制 (Bahdanau et al., 2015) [15],它使用了有一个隐藏层的前馈网络(全连接)来计算注意力的分配:

也就是:

乘法(点积)注意力(multiplicative attention)

乘法注意力(Multiplicative attention)(Luong et al., 2015) [16] 通过计算以下函数而简化了注意力操作:

加性注意力和乘法注意力在复杂度上是相似的,但是乘法注意力在实践中往往要更快速、具有更高效的存储,因为它可以使用矩阵操作更高效地实现。两个变体在低维度 d_h 解码器状态中性能相似,但加性注意力机制在更高的维度上性能更优。

自注意力(self-attention)

注意力机制不仅能用来处理编码器或前面的隐藏层,它同样还能用来获得其他特征的分布,例如阅读理解任务中作为文本的词嵌入 (Kadlec et al., 2017) [37]。然而,注意力机制并不直接适用于分类任务,因为这些任务并不需要情感分析(sentiment analysis)等额外的信息。在这些模型中,通常我们使用 LSTM 的最终隐藏状态或像最大池化和平均池化那样的聚合函数来表征句子。

自注意力机制(Self-attention)通常也不会使用其他额外的信息,但是它能使用自注意力关注本身进而从句子中抽取相关信息 (Lin et al., 2017) [18]。自注意力又称作内部注意力,它在很多任务上都有十分出色的表现,比如阅读理解 (Cheng et al., 2016) [38]、文本继承 (textual entailment/Parikh et al., 2016) [39]、自动文本摘要 (Paulus et al., 2017) [40]。

关键值注意力(key-value attention)

关键值注意力 (Daniluk et al., 2017) [19] 是最近出现的注意力变体机制,它将形式和函数分开,从而为注意力计算保持分离的向量。它同样在多种文本建模任务 (Liu & Lapata, 2017) [41] 中发挥了很大的作用。具体来说,关键值注意力将每一个隐藏向量 h_i 分离为一个键值 k_i 和一个向量 v_i:[k_i;v_i]=h_i。键值使用加性注意力来计算注意力分布 a_i:

其中 L 为注意力窗体的长度,I 为所有单元为 1 的向量。然后使用注意力分布值可以求得环境表征 c_i:

其中环境向量 c_i 将联合现阶段的状态值 v_i 进行预测。

最后的最后,再加一个自己用keras实现的简单的静态AM(自注意力)层的代码吧:

 
  1. from keras import backend as K

  2. from keras.engine.topology import Layer

  3. from keras import initializers, regularizers, constraints

  4.  
  5. class Attention_layer(Layer):

  6. """

  7. Attention operation, with a context/query vector, for temporal data.

  8. Supports Masking.

  9. Follows the work of Yang et al. [https://www.cs.cmu.edu/~diyiy/docs/naacl16.pdf]

  10. "Hierarchical Attention Networks for Document Classification"

  11. by using a context vector to assist the attention

  12. # Input shape

  13. 3D tensor with shape: `(samples, steps, features)`.

  14. # Output shape

  15. 2D tensor with shape: `(samples, features)`.

  16. :param kwargs:

  17. Just put it on top of an RNN Layer (GRU/LSTM/SimpleRNN) with return_sequences=True.

  18. The dimensions are inferred based on the output shape of the RNN.

  19. Example:

  20. model.add(LSTM(64, return_sequences=True))

  21. model.add(AttentionWithContext())

  22. """

  23.  
  24. def __init__(self,

  25. W_regularizer=None, b_regularizer=None,

  26. W_constraint=None, b_constraint=None,

  27. bias=True, **kwargs):

  28.  
  29. self.supports_masking = True

  30. self.init = initializers.get('glorot_uniform')

  31.  
  32. self.W_regularizer = regularizers.get(W_regularizer)

  33. self.b_regularizer = regularizers.get(b_regularizer)

  34.  
  35. self.W_constraint = constraints.get(W_constraint)

  36. self.b_constraint = constraints.get(b_constraint)

  37.  
  38. self.bias = bias

  39. super(Attention_layer, self).__init__(**kwargs)

  40.  
  41. def build(self, input_shape):

  42. assert len(input_shape) == 3

  43.  
  44. self.W = self.add_weight((input_shape[-1], input_shape[-1],),

  45. initializer=self.init,

  46. name='{}_W'.format(self.name),

  47. regularizer=self.W_regularizer,

  48. constraint=self.W_constraint)

  49. if self.bias:

  50. self.b = self.add_weight((input_shape[-1],),

  51. initializer='zero',

  52. name='{}_b'.format(self.name),

  53. regularizer=self.b_regularizer,

  54. constraint=self.b_constraint)

  55.  
  56. super(Attention_layer, self).build(input_shape)

  57.  
  58. def compute_mask(self, input, input_mask=None):

  59. # do not pass the mask to the next layers

  60. return None

  61.  
  62. def call(self, x, mask=None):

  63. uit = K.dot(x, self.W)

  64.  
  65. if self.bias:

  66. uit += self.b

  67.  
  68. uit = K.tanh(uit)

  69.  
  70. a = K.exp(uit)

  71.  
  72. # apply mask after the exp. will be re-normalized next

  73. if mask is not None:

  74. # Cast the mask to floatX to avoid float64 upcasting in theano

  75. a *= K.cast(mask, K.floatx())

  76.  
  77. # in some cases especially in the early stages of training the sum may be almost zero

  78. # and this results in NaN's. A workaround is to add a very small positive number to the sum.

  79. # a /= K.cast(K.sum(a, axis=1, keepdims=True), K.floatx())

  80. a /= K.cast(K.sum(a, axis=1, keepdims=True) + K.epsilon(), K.floatx())

  81. print a

  82. # a = K.expand_dims(a)

  83. print x

  84. weighted_input = x * a

  85. print weighted_input

  86. return K.sum(weighted_input, axis=1)

  87.  
  88. def compute_output_shape(self, input_shape):

  89. return (input_shape[0], input_shape[-1])

QQ截图20161015223332.jpg-20.6kB

3.实验结果

为了检验性能,作者分别使用传统模型和attention模型在英语-法语的翻译数据集上进行了测验。

传统模型的编码器和解码器各有1000个隐藏单元。编码器中还有一个多层神经网络用于实现从隐藏状态到单词的映射。在优化方面,使用了SGD(minibatch stochastic gradient descent)以及Adadelta,前者负责采样,后者负责优化下降方向。

得到的结果如下:
QQ截图20161015224833.jpg-36.7kB

图中RNNenc表示传统的结构,而RNNsearch表示attention模型。后面的数字表示序列的长度。可以看到,不论序列长度,attention模型的性能均优于传统的编码-解码模型。而RNNsearch-50甚至在长文本上的性能也非常的优异

除了准确度之外,还有一个很值得关注的东西:注意力矩阵。之前已经提过,每个输出都有一个长为TxTx的注意力向量,那么将这些向量合起来看,就是一个矩阵。对其进行可视化,得到如下结果

QQ截图20161015225911.jpg-63.7kB

其中x轴表示待翻译的句子中的单词(英语),y轴表示翻译以后的句子中的单词(法语)。可以看到尽管从英语到法语的过程中,有些单词的顺序发生了变化,但是attention模型仍然很好的找到了合适的位置。换句话说,就是两种语言下的单词“对齐”了。因此,也有人把注意力模型叫做对齐(alignment)模型。而且像比于用语言学实现的硬对齐,这种基于概率的软对齐更加优雅,因为能够更全面的考虑到上下文的语境。

2. Attention模型的主要应用

  Attention模型主要应用于深度学习,目前深度学习最热门的应用就是自然语言理解、图像识别和语音识别三大领域。本文针对三个领域分别列举几个Attention模型的应用。

2.1 自然语言理解

  第一节的机器翻译就是一个非常重要的应用,谷歌在最新发布的机器翻译模型中就采用了Attention模型,[4]一文中将Attention模型应用到文本摘要,从长句子或段落中提取关键词,如下图:


图片名称


华为诺亚方舟实验室的李航博士将Attention模型应用于短文本对话[5]

2.2 图像识别

  Attention模型在图像识别里的应用既有图像分类,如[6][7],又有图像生成,如[8][9],个人最感兴趣的是图像标题生成[10],如下图:

该研究中将Attention模型的权值可视化,显示在原图中,即图中白色的区域,可以看出,图中的飞盘和狗分别与句子中的frisbee和dog形成了对应关系。

2.3 语音识别

  语音识别的经典模型要数CTC,基于Attention模型的Encoder-Decoder框架也取得了较好的结果,如[11][12],Attention模型也建立了语音与单词之间的对应关系。


图片名称

3. 研究进展

  自从Attention模型引入深度学习后,不但获得了广泛应用,也产生了很多改进,下面列举几个研究进展。
   [10]首次将Attention模型引入图像标题应用时,提出了两种Attention方法——soft attention和hard attention,其中soft attention就是最初的attention方法,而hard attention在选取特征组合时,并不针对所有的特征生成权值,而是只选取1个或者几个特征,因此是hard的。
  从Attention中的alignment模型et,i=fatt(st−1,hi)et,i=fatt(st−1,hi)可以看出,它实际上是基于Decoder的t-1时刻的状态预测t时刻状态与Encoder特征hihi的关联程度,在[13]中,首先不使用Attention模型进行Decoder,然后就可以使用Attenion计算t时刻的Decoder状态与Encoder特征的关联程度,et,i=fatt(st,hi)et,i=fatt(st,hi),并且文章基于bilinear方法提出了简化版的Attention模型,计算更加高效。
  在机器翻译中,存在过翻译和欠翻译的现象,即有些词被多次翻译,有些词却被漏掉,这是因为Attention模型没有记忆翻译进程的机制,[14]一文增加了Coverage模型,用于记录哪些单词已被翻译,哪些尚未翻译,从而使Attention模型专注于未翻译的单词,忽略已经翻译的单词。
  在2017年,google的团队提出一个只基于attention机制的结构来处理序列模型相关的问题[15],没有采用常见的RNN和CNN网络,该结构能够并行训练,大大地减少了训练时间。

所以说Attention的作用是?

Attention的出现就是为了两个目的:1. 减小处理高维输入数据的计算负担,通过结构化的选取输入的子集,降低数据维度。2. “去伪存真”,让任务处理系统更专注于找到输入数据中显著的与当前输出相关的有用信息,从而提高输出的质量。Attention模型的最终目的是帮助类似编解码器这样的框架,更好的学到多种内容模态之间的相互关系,从而更好的表示这些信息,克服其无法解释从而很难设计的缺陷。从上述的研究问题可以发现,Attention机制非常适合于推理多种不同模态数据之间的相互映射关系,这种关系很难解释,很隐蔽也很复杂,这正是Attention的优势—不需要监督信号,对于上述这种认知先验极少的问题,显得极为有效。

2. Soft Attention:

传统的Attention Mechanism就是Soft Attention,即通过确定性的得分计算来得到attended之后的编码隐状态。Soft Attention是参数化的(Parameterization),因此可导,可以被嵌入到模型中去,直接训练。梯度可以经过Attention Mechanism模块,反向传播到模型其他部分。
也有称作TOP-down Attention。

3. Hard Attention:

相反,Hard Attention是一个随机的过程。Hard Attention不会选择整个encoder的隐层输出做为其输入,Hard Attention会依概率Si来采样输入端的隐状态一部分来进行计算,而不是整个encoder的隐状态。为了实现梯度的反向传播,需要采用蒙特卡洛采样的方法来估计模块的梯度。
两种Attention Mechanism都有各自的优势,但目前更多的研究和应用还是更倾向于使用Soft Attention,因为其可以直接求导,进行梯度反向传播。

4. 总结

  Attention模型在深度学习的各个领域均取得广泛的应用,作为一个独立的框架,attention机制还可以使用更加复杂的网络结构来改善其效果。并且,attention机制尚有不完善之处,如未记忆历史信息、缺乏对attention的评价机制等,仍在存在一定的改进空间。

 

猜你喜欢

转载自blog.csdn.net/qq_41853758/article/details/82930154
今日推荐