This week studied an article,《Attention Is All You Need》 ,presented the Transformer, the first sequence transduction model based entirely on attention, replacing the recurrent layers most commonly used in encoder-decoder architectures with multi-headed self-attention.
In addition, the mathematical expressions and the backpropagation problem of LSTM were derived,and i get the Attention of what 、why and how to.
本周研究了一篇名为《Attention Is All You Need》的文章,介绍了Transformer,第一个完全基于注意力的序列转换模型,用Multi-HeadAttention取代了编解码器架构中最常用的循环层。此外,还推导了 LSTM 的数学表达式和反向传播问题,学习了为什么用Attention,Attention是什么,怎么用Attention。
2017 年,Google 机器翻译团队发表的《Attention is All You Need》中,完全抛弃了RNN和CNN等网络结构,而仅仅采用Attention机制来进行机器翻译任务,并且取得了很好的效果,注意力机制也成为了大家近期的研究热点。
自从Attention机制在提出之后,加入Attention的Seq2Seq模型在各个任务上都有了提升,所以现在的Seq2Seq模型指的都是结合RNN和Attention的模型。传统的基于RNN的Seq2Seq模型难以处理长序列的句子,无法实现并行,并且面临对齐的问题。
所以之后这类模型的发展大多数从三个方面入手:
(1)Input的方向性从单向到多向;
(2)深度从单层到多层;
(3)类型从RNN到LSTM GRU。
但是依旧收到一些潜在问题的制约,神经网络需要能够将源语句的所有必要信息压缩成固定长度的向量。这可能使得神经网络难以应付长时间的句子,特别是那些比训练语料库中的句子更长的句子;每个时间步的输出需要依赖于前面时间步的输出,这使得模型没有办法并行,效率低;仍然面临对齐问题。
再然后CNN由计算机视觉也被引入到Deep NLP中,CNN不能直接用于处理变长的序列样本但可以实现并行计算。完全基于CNN的Seq2Seq模型虽然可以并行实现,但非常占内存,很多的trick,大数据量上参数调整并不容易。
本篇文章创新点在于抛弃了之前传统的Encoder-Decoder模型必须结合CNN或者RNN的固有模式,只用Attention机制。
大多数竞争的神经序列转导模型都具有编码器-解码器结构。
在这里,编码器映射一个符号表示的输入序列(x1,…, xn)到一个连续表示的序列z = (z1,…、zn)。给定z,解码器然后生成一个输出序列(y1,…, ym)的符号一次一个元素。在每个步骤中,模型都是自回归,在生成下一个步骤时,使用先前生成的符号作为附加输入。
Transformer遵循这种总体架构,使用堆叠的自注意层和点状的完全连接层,分别用于编码器和解码器,如图1的左半部分和右半部分所示。
理解部分:
整体框架很容易理解,但看上图又很复杂,简化一下:
其实这就是一个Seq2Seq模型,左边一个encoder把输入读进去,右边一个decoder得到输出,第一眼看到论文中的框图,随之产生问题就是左边encoder的输出是怎么和右边decoder结合的。因为decoder里面是有N层的。再画张图直观的看就是这样:
也就是说,Encoder的输出,会和每一层的Decoder进行结合
注意力函数可以描述为将一个查询和一组键-值对映射到一个输出,其中查询、键、值和输出都是向量。输出是按值的加权和计算的,其中分配给每个值的权重是通过查询的兼容性函数与相应键计算的。
Attention用于计算"相关程度",例如在翻译过程中,不同的英文对中文的依赖程度不同,Attention通常可以进行如下描述,表示为将query(Q)和key-value pairs映射到输出上,其中query、每个key、每个value都是向量,输出是V中所有values的加权,其中权重是由Query和每个key计算出来的,计算方法分为三步:
详细可以看下面第三部分三、attention机制。
这里称为“缩放点积注意”。输入由维度dk的查询和键以及维度dv的值组成。我们计算查询的所有键的点积,每个键除以√dk,然后应用一个softmax函数来获得值的权重。
在实践中,我们同时计算一组查询的注意函数,它们被打包到一个矩阵q中。键和值也被打包到矩阵K和V中。我们计算输出矩阵为:
理解部分:
像大部分NLP应用一样,我们首先将每个输入单词通过词嵌入算法转换为词向量。每个单词都被嵌入为512维的向量,我们用一些简单的方框来表示这些向量。词嵌入过程只发生在最底层的编码器中。所有的编码器都有一个相同的特点,即它们接收一个向量列表,列表中的每个向量大小为512维。在底层(最开始)编码器中它就是词向量,但是在其他编码器中,它就是下一层编码器的输出(也是一个向量列表)。向量列表大小是我们可以设置的超参数——一般是我们训练集中最长句子的长度。将输入序列进行词嵌入之后,每个单词都会流经编码器中的两个子层。
接下来我们看看Transformer的一个核心特性,在这里输入序列中每个位置的单词都有自己独 特的路径流入编码器。在自注意力层中,这些路径之间存在依赖关系。而前馈(feed-forward)层没有这些依赖关系。因此在前馈(feed-forward)层时可以并行执行各种路径。
我们发现,与使用dmodel维的键、值和查询执行单一的注意函数不同,将查询、键和值分别线性投影到dk、dk和dv维h次是有益的。在查询、键和值的每个投影版本上,我们并行执行注意函数,生成dv维输出值。这些被连接起来并再次进行投影,产生最终的值,如图2所示。
多头注意使模型能够联合注意来自不同位置的不同表示子空间的信息。对于单一注意力头,平均会抑制这一点。
理解部分:
Multi-Head Attention就是把Scaled Dot-Product Attention的过程做H次,然后把输出Z合起来。它使得模型可以关注不同位置。
如想知道“The animal didn’t cross the street because it was too tired” 中 it 的含义时,这时就需要关注到其他位置。这个机制为注意层提供了多个“表示子空间”(representation Subspaces)。下面具体介绍:
(1)经过 Multi-Headed,我们会得到和 heads 数目一样多的 Query / Key / Value 权重矩阵组.论文中用了8个,那么每个Encoder/Decoder我们都会得到 8 个集合。这些集合都是随机初始化的,经过训练之后,每个集合会将input Embeddings (或者来自较低编码器/解码器的向量)投影到不同的表示子空间中。
(2)我们重读记忆八次相似的操作,得到八个Zi矩阵。简单来说,就是定义8组权重矩阵,每个单词会做8次上面的Self-Attention的计算这样每个单词就会得到8个不同的加权求和Z。
(3)feed-forward处只能接受一个矩阵,所以需要将这八个矩阵压缩成一个矩阵。方法就是先将八个矩阵连接起来,然后乘以一个额外的权重矩阵W0。为了使得输出与输入结构对标 乘以一个线性W0 得到最终的Z.
由于模型不包含递归和卷积,为了让模型利用序列的顺序,作者注入了一些关于序列中标记的相对或绝对位置的信息。为此,作者在编码器和解码器栈底部的输入嵌入中添加了“位置编码”。位置编码具有与嵌入相同的维数模型,因此二者可以求和。有许多位置编码的选择,学习和固定[8]。
在这项工作中,作者使用了不同频率的正弦和余弦函数:
其中pos是位置,I是维度。也就是说,位置编码的每个维度对应一个正弦信号。波长形成一个从2π到10000·2π的几何级数。我们选择这个函数是因为我们假设它可以让模型很容易地学会通过相对位置参加。
后面还有,Position-wise Feed-Forward Networks(位置前馈网络)、Embeddings and Softmax(嵌入式和Softmax)、Why Self-Attention(为什么Self-Attention的解释)、Training(训练)和Regularization(总结部分)。这里就不大解释了。
可以参考原文地址、解释
上周已经学习了LSTM模型的结构以及正向推导,所以本周学习LSTM的反向推导也就是权重训练的过程。
LSTM的参数非常的多,遗忘门,更新门等每一个门两个参数,所以训练起来非常的繁琐,本次学习以遗忘门的Wxf权重为例子。
LSTM的结构:
当时刻t=3,从L3对Wxf进行训练,会发现L3分别受Wxf(1)、Wxf(2)、Wxf(3)影响,所以:
这里只是把t时刻设置为3,已经出现如此多的路径,可想而知当时刻很大时,Ct和Ct-1做偏导会出现很多偏导联系相乘,从而引起梯度消失问题。
但这是可以缓解的,LSTM模型可以通过权重的训练缓解梯度消失。
从正向传播角度:因为LSTM的记忆细胞拥有强大的记忆能力,在正向传播的时候,前面很多的特征都被保留了下来,虽然有很多的消除和加入,但是一些重要的特征是会一直保留的,而这些保留的特征相差不会很大,所以在进行梯度下降的时候可以稳定在 1 附近。
————————————
从反向传播角度:在上面反向推导的时候,可以发现是存在很多连续Ct和Ct-1在做偏导的。
可以通过调节Whf、Whi、Whg等权重,灵活地控制Ct和Ct-1做偏导的值,使得他可以尽可能的接近于 1 ,从而大大缓解梯度消失。
Encoder-Decoder框架顾名思义也就是编码-解码框架,目前大部分attention模型都是依附于Encoder-Decoder框架进行实现,在NLP中Encoder-Decoder框架主要被用来处理序列-序列问题。也就是输入一个序列,生成一个序列的问题。这两个序列可以分别是任意长度。具体到NLP中的任务比如:
文本摘要,输入一篇文章(序列数据),生成文章的摘要(序列数据)
文本翻译,输入一句或一篇英文(序列数据),生成翻译后的中文(序列数据)
问答系统,输入一个question(序列数据),生成一个answer(序列数据)
如上图所示,输入,如何确定语义编码C呢?最简单的办法直接用最后时刻输出的ht作为C的状态值,这里也就是可以用h4直接作为语义编码C的值,也可以将所有时刻的隐藏层的值进行汇总,然后生成语义编码C的值。
Decoder:解码器,根据输入的语义编码C,然后将其解码成序列数据,解码方式也可以采用RNN/LSTM/GRU等,Decoder和Encoder的编码解码方式可以任意组合。
1.在上面解码编码的过程可以看出,每一时刻的输出如上式所示,在生成目标句子的单词时,不论生成哪个单词,是y1,y2也好,还是y3也好,他们使用的语义编码C都是一样的,没有任何区别。而语义编码C是由输入序列X的每个单词经过Encoder 编码产生的,这意味着不论是生成哪个单词,y1,y2还是y3,其实输入序列X中任意单词对生成某个目标单词yi来说影响力都是相同的,没有任何区别
(其实如果Encoder是RNN的话,理论上越是后输入的单词影响越大,并非等权的,估计这也是为何Google提出Sequence to Sequence模型时发现把输入句子逆序输入做翻译效果会更好的小Trick的原因)这对应我上周看的论文《 Sequence to Sequence Learning with Neural Networks.》留下来的问题–逆序输入做翻译效果会更好–的确有这样的可能!
2.将整个序列的信息压缩在了一个语义编码C中,用一个语义编码C来记录整个序列的信息,序列较短还行,如果序列是长序列,只是用一个语义编码C来表示整个序列的信息肯定会损失很多信息,而且序列一长,就可能出现梯度消失问题,这样将所有信息压缩在一个C里面显然就不合理。
一个C不行,那就用多个C,于是基于Encoder-Decoder的attention model就出现了。
attention机制最早是在视觉图像领域被提出来的,早在90年代就已经有了,不过真正让其大火特火的应该是2014年google mind团队的论文《Recurrent models of visual attention》,该论文在RNN模型中使用了attention机制来做图像分类。之后,bahdanau等人发表论文《Neural Machine Translation by Jointly Learning to Align and Translate》中,使用类似attention的机制在机器翻译任务上将翻译与对齐同时进行,将attention机制应用到NLP领域。2017年,google的《attention is all you need》中大量使用了self-attention机制来学习文本表示。(《attention is all you need》正是本周阅读的论文)
attention机制的本质是来自人类视觉注意力机制。人的视觉在感知东西的时候一般会不是对整个场景从头到尾全部看的,而往往是根据需求观察注意特定的部分。
上图就是引入了Attention 机制的Encoder-Decoder框架。上图不再只有一个单一的语义编码C,而是有多个C1,C2,C3这样的编码。当我们在预测Y1时,可能Y1的注意力是放在C1上,那咱们就用C1作为语义编码,当预测Y2时,Y2的注意力集中在C2上,就用C2作为语义编码。
以机器翻译例子"Tom chase Jerry" - "汤姆追逐杰瑞"来说明:
当我们在翻译"杰瑞"的时候,为了体现出输入序列中英文单词对于翻译当前中文单词不同的影响程度,比如给出类似下面一个概率分布值:
(Tom,0.3)(Chase,0.2)(Jerry,0.5)
每个英文单词的概率代表了翻译当前单词“杰瑞”时,注意力分配模型分配给不同英文单词的注意力大小。每翻译目标语单词时,都会引入了新的信息,每个词都有新的分配概率信息产生。和传统的,Encoder-Decoder框架相比,理解AM模型(Attention model)的关键就是这里,即由固定的中间语义表示C换成了根据当前输出单词来调整成加入注意力模型的变化的Ci。
f2(“Tom”),f2(“Chase”),f2(“Jerry”)就是对应的隐藏层的值h(“Tom”),h(“Chase”),h(“Jerry”)。g函数就是加权求和。αi表示权值分布。因此Ci的公式就可以写成:
那么怎么知道attention模型所需要的输入句子单词注意力分配概率分布值呢?也就是αij?
以普通的RNN-RNN Encoder-Decoder结构为例,注意上图Decoder初始输入用初始符,这里使用eos作为初始符。将输入eos与初始S0通过RNN生成h(eos),然后分别计算h(eos)与h1,h2,h3…hm的相关性,这个相关性怎么计算一会儿再介绍。得到h(eos)与h1,h2,h3…hm的相关性评分[f1,f2,f3…fm],然后跟多分类一样使用softmax,就能得到相关性的概率分布α(eos)。
推广到预测decoder的每一个输出值Yi:
decoder上一时刻的输出值Yi-1与上一时刻传入的隐藏层的值Si-1通过RNN生成Hi,然后计算Hi与h1,h2,h3…hm的相关性,得到相关性评分[f1,f2,f3…fm],然后对Fi进行softmax就得到注意力分配αij。然后将encoder的输出值h与对应的概率分布αij进行点乘求和,就能得到注意力attention值了。
(这是Soft Attention是所有的数据都会注意,都会计算出相应的注意力权值,不会设置筛选条件。还有一种Hard Attention会在生成注意力权重后筛选掉一部分不符合条件的注意力,让它的注意力权值为0,即可以理解为不再注意这些不符合条件的部分。)
参照上图可以这么来理解Attention,将Source中的构成元素想象成是由一系列的
上面三种方法都是求相似性的公式,其中多层感知机方法:
主要是先将query和key进行拼接,然后接一个激活函数为tanh的全连接层,然后再与一个网络定义的权重矩阵做乘积。但这种方法计算比较复杂,训练成本比较高。
计算出Query和Keyi的相似性后,引入类似SoftMax的计算方式对第一阶段的相似性得分进行数值转换,一方面可以进行归一化,将原始计算分值整理成所有元素权重之和为1的概率分布;另一方面也可以通过SoftMax的内在机制更加突出重要元素的权重。
流程如下:
阶段1:Query与每一个Key计算相似性得到相似性评分s
阶段2:将s评分进行softmax转换成[0,1]之间的概率分布
阶段3:将[a1,a2,a3…an]作为权值矩阵对Value进行加权求和得到最后的Attention值
1.只能在Decoder阶段实现并行运算,Encoder部分依旧采用的是RNN,LSTM这些按照顺序编码的模型,Encoder部分还是无法实现并行运算,不够完美。
2.就是因为Encoder部分目前仍旧依赖于RNN,所以对于中长距离之间,两个词相互之间的关系没有办法很好的获取。
为了改进上面两个缺点,更加完美的Self-Attention出现了。(《attention is all you need》正是本周阅读的论文)
主要参考的文章:1、2、3
本周学习了《attention is all you need》这篇论文,这是里程碑式的,抛弃了RNN或者CNN模型,直接用Attention机制来做机器翻译。这周还学习了LSTM的反向传播的推导,和理解了从Encoder到Decoder,再到Attention机制的运行过程。