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!!!下一篇将会努力实现模型。