赞
踩
Transformer原理(一)_multi-head self-attention的随机梯度公式
Transformer实现(二)_transformer feedforward neural network
《Attention Is All You Need》是Google在2017年提出的一篇将Attention思想发挥到极致的论文。该论文提出的Transformer模型,基于encoder-decoder架构,抛弃了传统的RNN、CNN模型,仅由Attention机制实现,并且由于encoder端是并行计算的,训练时间大大缩短。
Transformer模型广泛应用于NLP领域,机器翻译、文本摘要、问答系统等等,目前火热的Bert模型就是基于Transformer模型构建的。
Transformer优点:transformer架构完全依赖于Attention机制,解决了输入输出的长期依赖问题,并且拥有并行计算的能力,大大减少了计算资源的消耗。self-attention模块,让源序列和目标序列首先“自关联”起来,这样的话,源序列和目标序列自身的embedding表示所蕴含的信息更加丰富,而且后续的FFN层也增强了模型的表达能力。Muti-Head Attention模块使得Encoder端拥有并行计算的能力.
Transformer 的代码:Attention Is All You Need | Papers With Code#2 best model for Multimodal Machine Translation on Multi30K (BLUE (DE-EN) metric)https://paperswithcode.com/paper/attention-is-all-you-need这部分我们来看看Transformer的架构。Transformer遵循了Encoder-Decoder的架构。
在Encoder方面,6个编码器组件协同工作,组成一个大的编码器,解码器同样由6个解码器组件组成。
说完了Encoder和Decoder,再说说输入,模型的输入部分由词向量(embedding)经位置编码(positional Encoding)后输入到Encoder和Decoder。编码器的输出由一个线性层和softmax组成,将浮点数映射成具体的符号输出。
首先,Transformer模型也是使用经典的encoer-decoder架构,由encoder和decoder两部分组成。
上图的左半边用Nx框出来的,就是我们的encoder的一层。encoder一共有6层这样的结构。
上图的右半边用Nx框出来的,就是我们的decoder的一层。decoder一共有6层这样的结构。
输入序列经过word embedding和positional encoding相加后,输入到encoder。
输出序列经过word embedding和positional encoding相加后,输入到decoder。
最后,decoder输出的结果,经过一个线性层,然后计算softmax。
这张图是一个已经简单的翻译模型,将英文翻译成中文.
比如我们输入英文 Why do we work ? 我们需要将其翻译成中文,我们根据序号来看
【1】将英文文本输入到输入到编码器的模型中去
【2】通过编码器得到我们的隐藏层特征
【3】我们输入<start>开始token
【4】解码器结合我们的隐藏层特征输出 为
【5】我们再将我们得到的 为 输出到解码器中
【6】解码器结合我们隐藏层特征会输出 什
【7】依次按照这种方式不断输入到解码器中,我们将得出我们解码器翻译出来的中文语句。
链接:https://www.jianshu.com/p/29e31b73528e
编码器和解码器块实际上是相互堆叠在一起的多个相同的编码器和解码器。 编码器堆栈和解码器堆栈都具有相同数量的单元。
编码器和解码器单元的数量是一个超参数。文中使用了 6 个编码器和解码器。
让我们看看编码器和解码器堆栈的设置是如何工作的:
将输入序列的词嵌入(word embeddings)传递给第一个编码器。
然后将它们进行转换并传播到下一个编码器。
编码器堆栈中最后一个编码器的输出将传递给解码器堆栈中所有的解码器,如下图所示:
这里需要注意的一点是,除了自注意力和前馈层外,解码器还有一层解码器 - 解码器注意力层。这有助于解码器将注意力集中在输入序列的适当部分上。
由 6 层组成,每一层包括两个子层:
「第一层」是 multi-head self-attention 层,
「第二层」是一个简单的全连接前馈网络。在每个子层后,都接了一个「残差连接以及归一化」,即每个子层的输出为 LayerNorm(X + Sublayer(X)) 为了方便残差连接,模型中的所有子层,包括 embedding 层(初始词嵌入) 输出向量维度均为
同样由 6 层组成,每一层包括三个子层:
「第一层」是 masked multi-head self-attention 层,注意其输入仅包含「当前位置之前的词语信息」,这样设计的目的是解码器是按顺序解码的,其当前输出只能基于已输出的部分。
「第二层」是 multi-head self-attention 层,其输入包含编码器的输出信息(矩阵 K 和矩阵 V ),「第三层」是全连接前馈网络。每个子层后同样加入了「残差连接和归一化」。下图给出了编码器和解码器的内部结构,注意前馈神经网络对于序列每个位置的独立性。
自注意力,有时也称为内部注意力(intra-attention),是一种注意力机制,它将一个序列的不同位置联系起来,以计算出序列的表示形式。
它指的是 street 还是 animal?这对我们来说是一个简单的问题,但对算法来说可不是这样的。当模型处理到“it”这个单词时,自注意力试图将“it”与同一句话中的“animal”联系起来。
熟悉attention原理的童鞋都知道,attention可由以下形式表示
首先说明一下我们的K、Q、V是什么:
scaled dot-product attention和dot-product attention唯一的区别就是,scaled dot-product attention有一个缩放因子 上面公式中的dk表示的是K的维度,在论文里面,默认是64
。
那么为什么需要加上这个缩放因子呢?
论文里给出了解释:对于dk很大的时候,点积得到的结果维度很大,使得结果处于softmax函数梯度很小的区域。我们知道,梯度很小的情况,这对反向传播不利。为了克服这个负面影响,除以一个缩放因子,可以一定程度上减缓这种情况。
其思想和attention类似,但是self-attention是Transformer用来将其他相关单词的“理解”转换成我们正在处理的单词的一种思路
我们看个例子:
1. The animal didn’t cross the street because it was too tired
2. The animal didn’t cross the street because it was too wide
两句话中的单词 it 指代不同,第一句话 it 指代 animal 而第二句指代 street。对于我们来说能很简单的判断出来,但是对于机器来说,是很难判断的,尤其是相对于传统seq2seq模型。两句话在单词 it 之前的内容是一样的,传统seq2seq模型encoder的顺序输入导致模型无法区分这种差别。而self-attention机制通过计算单词it与其他词之间的联系得知it的具体指代,最终结果如下图所示。
Self Attention就是句子中的某个词对于本身的所有词做一次Attention。算出每个词对于这个词的权重,然后将这个词表示为所有词的加权和。每一次的Self Attention操作,就像是为每个词做了一次Convolution操作或Aggregation操作。具体操作如下:
1.首先,self-attention会计算出三个新的向量,在论文中,向量的维度是512维,我们把这三个向量分别称为Query、Key、Value,这三个向量是用embedding向量与一个矩阵相乘得到的结果,这个矩阵是随机初始化的,维度为(64,512)注意第二个维度需要和embedding的维度一样,其值在BP的过程中会一直进行更新,得到的这三个向量的维度是64。
2. 计算self-attention的分数值,该分数值决定了当我们在某个位置encode一个词时,对输入句子的其他部分的关注程度。这个分数值的计算方法是Query与Key做点成,以下图为例,首先我们需要针对Thinking这个词,计算出其他词对于该词的一个分数值,首先是针对于自己本身即q1·k1,然后是针对于第二个词即q1·k2。
3. 接下来,把点成的结果除以一个常数,这里我们除以8,这个值一般是采用上文提到的矩阵的第一个维度的开方即64的开方8,当然也可以选择其他的值,然后把得到的结果做一个softmax的计算。得到的结果即是每个词对于当前位置的词的相关性大小,当然,当前位置的词相关性肯定会会很大。
4.下一步就是把Value和softmax得到的值进行相乘,并相加,得到的结果即是self-attetion在当前节点的值。
在实际的应用场景,为了提高计算速度,我们采用的是矩阵的方式,直接计算出Query, Key, Value的矩阵,然后把embedding的值与三个矩阵直接相乘,把得到的新矩阵 Q 与 K 相乘,除以一个常数,做softmax操作,最后乘上 V 矩阵。
归一化之前需要通过除以向量的维度dk来进行标准化,所以最终Self Attention用矩阵变换的方式可以表示为
最终每个Self Attention接受n个词向量的输入,输出n个Aggregated的向量。
这种通过 query 和 key 的相似性程度来确定 value 的权重分布的方法被称为scaled dot-product attention。
上文提到Encoder中的Self Attention与Decoder中的有所不同,Encoder中的Q、K、V全部来自于上一层单元的输出,而Decoder只有Q来自于上一个Decoder单元的输出,K与V都来自于Encoder最后一层的输出。也就是说,Decoder是要通过当前状态与Encoder的输出算出权重后,将Encoder的编码加权得到下一层的状态。
理解了Scaled dot-product attention,Multi-head attention也很简单了。Multi-Head Attention就是将上述的Attention做h遍,然后将h个输出进行concat得到最终的输出。这样做可以很好地提高算法的稳定性,在很多Attention相关的工作中都有相关的应用。
论文进一步增加了multi-headed的机制到self-attention上,在如下两个方面提高了attention层的效果:
论文提到,他们发现将Q、K、V通过一个线性映射之后,分成 h份,对每一份进行scaled dot-product attention效果更好。然后,把各个部分的结果合并起来,再次经过线性映射,得到最终的输出。这就是所谓的multi-head attention。上面的超参数 h就是heads数量。论文默认是8
。
这会带来点麻烦,前向网络并不能接收八个矩阵,而是希望输入是一个矩阵,所以要有种方式处理下八个矩阵合并成一个矩阵。
Transformer的实现中,为了提高Multi-Head的效率,将W扩大了h倍,然后通过view(reshape)和transpose操作将相同词的不同head的k、q、v排列在一起进行同时计算,完成计算后再次通过reshape和transpose完成拼接,相当于对于所有的head进行了一个并行处理。
值得注意的是,上面所说的分成 h 份是在 dk,kq,dv 维度上面进行切分的。因此,进入到scaled dot-product attention的 dk 实际上等于未进入之前的 Dk/h, self-attention则是取Q,K,V相同。
作者同样提到了另一种复杂度相似但计算方法additive attention,在 dk 很小的时候和dot-product结果相似,dk大的时候,如果不进行缩放则表现更好,但dot-product的计算速度更快,进行缩放后可减少影响(由于softmax使梯度过小,具体可见论文中的引用)
Attention是将query和key映射到同一高维空间中去计算相似度,而对应的multi-head attention把query和key映射到高维空间,的不同子空间 中去计算相似度。
为什么要做multi-head attention?论文原文里是这么说的:
Multi-head attention allows the model to jointly attend to information from different representation subspaces at different positions. With a single attention head, averaging inhibits this.
也就是说,这样可以在不改变参数量的情况下增强每一层attention的表现力。
在多头注意力中,对于初学者来说一个比较经典的问题就是,在相同维度下使用单头和多头的区别是什么?这句话什么意思呢?以图1-10中示例为例,此时的自注意力中使用了两个头,每个头的维度为dq,即采用了多头的方式。另外一种做法就是,只是用一个头,但是其维度为2*dq,即采用单头的方式。那么在这两种情况下有什么区别呢?
首先,从论文中内容可知,作者在头注意力机制与多头个数之间做了如下的限制
可以看出,单个头注意力机制的维度dq乘上多头的个数h就等于模型的维度
。
那现在的问题是图1-16中的Z能够计算得到吗?答案是不能。为什么?因为我没有告诉你这里的h等于多少。如果我告诉你多头h=2,那么毫无疑问图1-16的计算过程就等同于图1-14的计算过程. 且此时dk=dm/2。
但是如果我告诉你多头h=3,那么图1-16的计算过程会变成
且此时dk=dm/3。
现在回到一开始的问题上,根据上面的论述我们可以发现,在dm固定的情况下,不管是使用单头还是多头的方式,在实际的处理过程中直到进行注意力权重矩阵计算前,两者之前没有任何区别。当进行进行注意力权重矩阵计算时,h越大那么Q,K,V就会被切分得越小,进而得到的注意力权重分配方式越多,
同时,当h不一样时,dk的取值也不一样,进而使得对权重矩阵的scale的程度不一样。例如,如果dm=768,那么当
时,则
;当
时,则
。
所以,当模型的维度dm确定时,一定程度上h越大整个模型的表达能力越强,越能提高模型对于注意力权重的合理分配。
Multi-head Attention的本质是,在参数总量保持不变的情况下,将同样的query, key, value映射到原来的高维空间的不同子空间中进行attention的计算,在最后一步再合并不同子空间中的attention信息。这样降低了计算每个head的attention时每个向量的维度,在某种意义上防止了过拟合;由于Attention在不同子空间中有不同的分布,Multi-head Attention实际上是寻找了序列之间不同角度的关联关系,并在最后concat这一步骤中,将不同子空间中捕获到的关联关系再综合起来。
每一层经过attention之后,还会有一个FFN,这个FFN的作用就是空间变换。FFN包含了2层linear transformation层,中间的激活函数是ReLu。
曾经我在这里有一个百思不得其解的问题:attention层的output最后会和 Wo相乘,为什么这里又要增加一个2层的FFN网络?
其实,FFN的加入引入了非线性(ReLu激活函数),变换了attention output的空间, 从而增加了模型的表现能力。把FFN去掉模型也是可以用的,但是效果差了很多。
Transformer为什么需要进行Multi-head Attention?
原论文中说到进行Multi-head Attention的原因是将模型分为多个头,形成多个子空间,可以让模型去关注不同方面的信息,最后再将各个方面的信息综合起来。其实直观上也可以想到,如果自己设计这样的一个模型,必然也不会只做一次attention,多次attention综合的结果至少能够起到增强模型的作用,也可以类比CNN中同时使用多个卷积核的作用,直观上讲,多头的注意力有助于网络捕捉到更丰富的特征/信息。
Transformer相比于RNN/LSTM,有什么优势?为什么?
RNN系列的模型,并行计算能力很差。RNN并行计算的问题就出在这里,因为 T 时刻的计算依赖 T-1 时刻的隐层计算结果,而 T-1 时刻的计算依赖 T-2 时刻的隐层计算结果,如此下去就形成了所谓的序列依赖关系。
Transformer的特征抽取能力比RNN系列的模型要好。
具体实验对比可以参考:放弃幻想,全面拥抱Transformer:自然语言处理三大特征抽取器(CNN/RNN/TF)比较
但是值得注意的是,并不是说Transformer就能够完全替代RNN系列的模型了,任何模型都有其适用范围,同样的,RNN系列模型在很多任务上还是首选,熟悉各种模型的内部原理,知其然且知其所以然,才能遇到新任务时,快速分析这时候该用什么样的模型,该怎么做好。
为什么说Transformer可以代替seq2seq?
seq2seq缺点:这里用代替这个词略显不妥当,seq2seq虽已老,但始终还是有其用武之地,seq2seq最大的问题在于将Encoder端的所有信息压缩到一个固定长度的向量中,并将其作为Decoder端首个隐藏状态的输入,来预测Decoder端第一个单词(token)的隐藏状态。在输入序列比较长的时候,这样做显然会损失Encoder端的很多信息,而且这样一股脑的把该固定向量送入Decoder端,Decoder端不能够关注到其想要关注的信息。
Transformer优点:transformer不但对seq2seq模型这两点缺点有了实质性的改进(多头交互式attention模块),而且还引入了self-attention模块,让源序列和目标序列首先“自关联”起来,这样的话,源序列和目标序列自身的embedding表示所蕴含的信息更加丰富,而且后续的FFN层也增强了模型的表达能力,并且Transformer并行计算的能力是远远超过seq2seq系列的模型,因此我认为这是transformer优于seq2seq模型的地方。
Transformer如何并行化的?
Transformer的并行化我认为主要体现在self-attention模块,在Encoder端Transformer可以并行处理整个序列,并得到整个输入序列经过Encoder端的输出,在self-attention模块,对于某个序列x1,x2,…,xn,self-attention模块可以直接计算xi,xj的点乘结果,而RNN系列的模型就必须按照顺序从x1计算到xn。
训练-模型的参数在哪里?
Transformer的工作流程就是上面介绍的每一个子流程的拼接
Encoder端可以并行计算,一次性将输入序列全部encoding出来,但Decoder端不是一次性把所有单词(token)预测出来的,而是像seq2seq一样一个接着一个预测出来的。
transformer的核心点积是没有参数,transformer结构的训练,会优化的参数主要在:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。