BERT模型入门系列: Attention机制入门

2,004 阅读5分钟

Attention模型在NLP领域用的风生水起,但是一直对attention模型的基本原理不理解,看了很多别人的文章,似乎是看懂了,但实际上在真正理解起来的时候,就是没办法说出个所以然来,所以用自己的理解方式来写一篇。

Encoder-Decoder模型

说起Attention模型,就不得不先说一下seq2seq模型,seq2seq解决的问题,简单说来就是解决一个句子映射到另外一个句子的问题,例如下面的应用场景:

机器翻译:待翻译的文本序列-->翻译文本序列

语音识别:声学特征序列-->识别文本序列

问答系统:问题描述单词序列-->生成答案单词序列

文本摘要:文本序列-->摘要序列

而基础的seq2seq模型主要包括Encoder、Decoder、以及固定长度的语义向量。Encoder-Decoder模型在《Sequence to Sequence Learning with Neural Networks》中提出。以机器翻译为例,展示一下Encoder-Decoder模型的基本原理

Encoder和Decoder是神经网络,可以是RNN或者LSTM等,我们以RNN为例,将模型展开,其流程如下图所示

Encoder

[公式][公式][公式][公式] 是输入序列,如若是机器翻译任务,那么 [公式][公式][公式][公式] 就是输入待翻译的词语。

Encoder是神经网络,可以是RNN、LSTM等。

以RNN为例,RNN的当前隐藏状态是上一个输入的隐藏状态和当前输入决定的,所以:

当前RNN隐藏节点状态计算

[公式]

[公式] 表示RNN当前隐藏状态

[公式] 表示上一个输入的隐藏状态

[公式] 表示当前的输入

在输入结束, 得到了所有输入的隐藏层状态后,生成最后的语义向量C

语义向量C计算

[公式]

语义向量C是一个固定长度的向量,这个向量会作为Decoder的输入。

Decoder

同样,Decoder部分可以是RNN,也可以是LSTM,Decoder部分的输入是Encoder输出。 [公式][公式] 就是decoder解码出来的结果,如果是机器翻译任务,那么这个就是机器返回出来的结果。

这个阶段中,给定的语义向量 [公式] 和已经生成的输出序列 [公式][公式] 、...、 [公式] ,预测下一个输出单词yt

[公式]

也可以写作

[公式]

[公式] 为RNN的隐藏状态,那么,可以简写成

[公式]

即当前的输出 [公式] 有上一个输出 [公式] 、上一个输出的隐藏状态 [公式] 、Encoder输出的语义向量 [公式] ,经过 [公式] 函数运算得到,其中 [公式] 是一个非线性的神经网络,在这里为RNN

但是,这种方式存在缺陷: 由于Encoder编码输出的语义向量是固定长度,对于比较长的输入,会有部分信息丢失,导致Decoder出来的结果不佳,针对这个问题,KyungHyun Cho等人对Encoder-Decoder模型进行改造,提出了早期的Attention模型(NEURAL MACHINE TRANSLATION BY JOINTLY LEARNING TO ALIGN AND TRANSLATE)。

Attention模型:

为了解决固定长度语义向量导致的信息丢失问题,KyungHyun Cho等人引入了Attention模型,Attention模型的机制与人类翻译文章的思路相似,都是关注于要翻译的词,结合上下文进行翻译。Attention模型会寻找源语句对应的几个词,结合已经翻译出来的词语做相应的翻译。例如:我们翻译机器学习的时候,当翻译到机器的时候,Attention的注意力会集中在“机器”,这样,Decoder就可以看到Encoder的每个词的信息,而不局限于固定长度的隐藏向量而导致信息丢失。

具体流程如下:

对于一个句子 [公式][公式] 、...、 [公式]

1、输入序列编码,先用某种方法获的词语的向量,再输入到Encoder中进行编码,得到编码后的向量,这里记为 [公式][公式] 、...、 [公式] ,在这里,其中编码方式我们可以用RNN或者LSTM等,这里还是以RNN为例。

2、注意力权重的计算,为方便记录,定义注意力权重为 [公式],Decoder后的向量为 [公式][公式] 、...、 [公式] , 其中i为句子输入序列的下标

对于当前需要decoder的向量qi,其对应的注意力权重 [公式][公式] 、...、 [公式] 通过一个函数

[公式] 计算得到,我们也可以把Decoder后的向量当作Query,解码后的向量为字段,这里,我们就是用query查找字段对应权重的过程

3、计算语义向量 [公式][公式] (其中, [公式] 为注意力权重, [公式] 为Encoder得到的向量)

4、Decoder下一个输出 根据语义向量C,上一个Decoder的输出、上一个Decoder输出的隐藏状态,预测下一个输出

加入了Attention机制后,增加了两点不同之处

1、每次Decoder一个词的时候都需要计算一次注意力权重

2、每Decoder都需要重新计算语义向量 [公式]

计算注意力权重,需要两个信息:

  • Encoder后得到的向量[公式][公式] 、...、 [公式],这个向量包含了解码后所有单词的信息,我们可以把它当作一个字典
  • 第i-1个decoder得到的向量[公式]

以第一个例子进行讲解,

首先、输入文本“机器学习”经过RNN的Encoder之后,得到了隐藏状态[公式][公式][公式][公式]

第二步进行注意力权重计算,此处刚开始,还没有Decoder的隐藏状态, [公式] 一般是固定的start token

在得出注意力权重后,根据Encoder得到的隐藏状态[公式][公式][公式][公式],以及相应的注意力权重计算得到语义向量 [公式] ,最后Decoder得到结果machine

Decoder第二个词的时候,步骤也是一样的,不同的是计算注意里权重的时候,使用的是Decoder的得到的隐藏状态 [公式]

那这里问题来了,这个函数_F_是什么函数呢?一般,计算注意力权重有以下的方法

  • Bilinear方法

[公式]

用一个权重矩阵直接建立 [公式][公式] 的关系映射,比较直接,且计算速度较快。

  • Dot Product

[公式]

这个方法更直接,省掉了权重,直接建立 [公式][公式] 的关系映射,优点是计算速度更快了,且不需要参数,降低了模型的复杂度。但是需要 [公式][公式] 的维度要相同。

  • scaled-dot Product

[公式]

上面的点积方法有一个问题,就是随着向量维度的增加,最后得到的权重也会增加,为了提升计算效率,防止数据上溢,对其进行scaling。

Talk is cheap, show me the code!!!下一篇将会努力实现模型。