Transformer总结
Posted GoAI
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Transformer总结相关的知识,希望对你有一定的参考价值。
学习资料推荐:
图解Transformer_夏目的博客-CSDN博客_transformer
图解Transformer(完整版)_龙心尘-CSDN博客_transformer
图解Transformer(完整版)!_abcdefg90876的博客-CSDN博客
深度学习:transformer模型_皮皮blog-CSDN博客_深度学习transformer
NLP:Transformer的简介(优缺点)、架构详解之详细攻略_一个处女座的程序猿-CSDN博客
1.前言
本文参考其他优秀博客资料进行总结,推荐阅读前两篇文章学习Transformer,仅供个人学习。
Google于2017年6月发布在arxiv上的一篇文章《Attention is all you need》,提出解决sequence to sequence问题的transformer模型,用全attention的结构代替了lstm,抛弃了之前传统的encoder-decoder模型必须结合cnn或者rnn的固有模式,只用attention。文章的主要目的是在减少计算量和提高并行效率的同时不损害最终的实验结果( GLUE 上效果排名第一https://gluebenchmark.com/leaderboard),创新之处在于提出了两个新的Attention机制,分别叫做 Scaled Dot-Product Attention 和 Multi-Head Attention。
考虑到RNN(或者LSTM、GRU等)的计算限制为是顺序的,也就是说RNN相关算法只能从左向右依次计算或者从右向左依次计算,这种机制带来了两个问题:
- 时间片t的计算依赖t-1时刻的计算结果,这样限制了模型的并行能力;
- 顺序计算的过程中信息会丢失,尽管LSTM等门机制的结构一定程度上缓解了长期依赖的问题,但是对于特别长期的依赖现象,LSTM依旧无能为力。
2.Transformer 原理
2.1 Transformer整体结构
根据上图进行一步步拆解Transformer:
Transformer的结构图,拆解开来,主要分为图上4个部分,其中最重要的就是2和3Encoder-Decoder部分,Transformer是一个基于Encoder-Decoder框架的模型。
接下来我将按照1,2,3,4的顺序逐步介绍上图中Transformer的网络结构,这样既能够弄清楚结构原理,又能够方便理解Transformer模型的工作流程。
2.2 Transformer的inputs 输入
Transformer输入是一个序列数据,还是以上篇中提到的"Tom chase Jerry" 翻译成中文"汤姆追逐杰瑞"为例:
Encoder 的 inputs就是"Tom chase Jerry" 分词后的词向量。可以是任意形式的词向量,如word2vec,GloVe,one-hot编码。
假设上图中每一个词向量都是一个512维的词向量。
我们注意到,输入inputs embedding后需要给每个word的词向量添加位置编码positional encoding,为什么需要添加位置编码呢?
首先咱们知道,一句话中同一个词,如果词语出现位置不同,意思可能发生翻天覆地的变化,就比如:我欠他100W 和 他欠我100W。这两句话的意思一个地狱一个天堂。可见获取词语出现在句子中的位置信息是一件很重要的事情。但是咱们的Transformer 的是完全基于self-Attention地,而self-attention是不能获取词语位置信息地,就算打乱一句话中词语的位置,每个词还是能与其他词之间计算attention值,就相当于是一个功能强大的词袋模型,对结果没有任何影响。(一会儿在介绍Encoder的时候再详细说明)所以在我们输入的时候需要给每一个词向量添加位置编码。
问题又来了,这个positional encoding怎么获取呢?
1.可以通过数据训练学习得到positional encoding,类似于训练学习词向量,goole在之后的bert中的positional encoding便是由训练得到地。
2.《Attention Is All You Need》论文中Transformer使用的是正余弦位置编码。位置编码通过使用不同频率的正弦、余弦函数生成,然后和对应的位置的词向量相加,位置向量维度必须和词向量的维度一致。过程如上图,PE(positional encoding)计算公式如下:
解释一下上面的公式:
pos表示单词在句子中的绝对位置,pos=0,1,2…,例如:Jerry在"Tom chase Jerry"中的pos=2;dmodel表示词向量的维度,在这里dmodel=512;2i和2i+1表示奇偶性,i表示词向量中的第几维,例如这里dmodel=512,故i=0,1,2…255。
至于上面这个公式是怎么得来地,其实不重要,因为很有可能是作者根据经验自己造地,而且公式也不是唯一地,后续goole在bert中的positional encoding也没有再使用这种方法而是通过训练PE,说明这种求位置向量的方法还是存在一定问题地。
这里我就不做详细的介绍了,想要深究的朋友可以参考一下知乎上的这些回答:如何理解Transformer论文中的positional encoding,和三角函数有什么关系?
为什么是将positional encoding与词向量相加,而不是拼接呢?
拼接相加都可以,只是本身词向量的维度512维就已经蛮大了,再拼接一个512维的位置向量,变成1024维,这样训练起来会相对慢一些,影响效率。两者的效果是差不多地,既然效果差不多当然是选择学习习难度较小的相加了。
Transformer 的 Decoder的输入与Encoder的输出处理方法步骤是一样地,一个接受source数据,一个接受target数据,对应到上面例子里面就是:Encoder接受英文"Tom chase Jerry",Decoder接受中文"汤姆追逐杰瑞"。只是在有target数据时也就是在进行有监督训练时才会接受Outputs Embedding,进行预测时则不会接收。
至此,Transformer的第一块输入部分已经讲解完了,接下来就要进入重点部分Encoder和Decoder了。
2.2 Transformer的Encoder
看上图第2部分 Encoder block。Encoder block是由6个encoder堆叠而成,Nx=6。上图2中的灰框部分就是一个encoder的内部结构,从图中我们可以看出一个encoder由Multi-Head Attention 和 全连接神经网络Feed Forward Network构成。
Multi-Head Attention:
首先回顾一下self-attention,假如输入序列是"Thinking Machines",x1,x2就是对应地"Thinking"和"Machines"添加过位置编码之后的词向量,然后词向量通过三个权值矩阵W Q , W K , W V W^Q,W^K,W^VWQ,WK,WV,转变成为计算Attention值所需的Query,Keys,Values向量。
因为咱们再实际使用中,每一个样本,也就是每一条序列数据都是以矩阵的形式输入地,故可以看到上图中,X矩阵是由"Tinking"和"Machines"词向量组成的矩阵,然后跟过变换得到Q,K,V。假设词向量是512维,X矩阵的维度是(2,512),W Q , W K , W V W^Q,W^K,W^VWQ,WK,WV均是(512,64)维,得到的Query,Keys,Values就都是(2,64)维。
得到Q,K,V之后,接下来就是计算Attention值了。
步骤1: 输入序列中每个单词之间的相关性得分,上篇中说过计算相关性得分可以使用点积法,就是用Q中每一个向量与K中每一个向量计算点积,具体到矩阵的形式:s c o r e = Q ⋅ K T score = Q\\cdot K^Tscore=Q⋅KT,socre是一个(2,2)的矩阵
步骤2: 对于输入序列中每个单词之间的相关性得分进行归一化,归一化的目的主要是为了训练时梯度能够稳定。s c o r e = s c o r e / d k score = score/\\sqrtd_kscore=score/dk,dk就是K的维度,以上面假设为例,dk=64
步骤3: 通过softmax函数,将每个单词之间的得分向量转换成[0,1]之间的概率分布,同时更加凸显单词之间的关系。经过softmax后,score转换成一个值分布在[0,1]之间的(2,2)α概率分布矩阵
步骤4: 根据每个单词之间的概率分布,然后乘上对应的Values值,α与V进行点积,Z = s o f t m a x ( s c o r e ) ⋅ V Z = softmax(score)\\cdot VZ=softmax(score)⋅V,V的为维度是(2,64),(2,2)x(2,64)最后得到的Z是(2,64)维的矩阵
整体的计算图如下:
说了这么多好像都只是在说self-attention,那么Multi-Head Attention呢?
Multi-Head Attention 很简单,就是在self-attention的基础上,对于输入的embedding矩阵,self-attention只使用了一组W Q , W K , W V W^Q,W^K,W^VWQ,WK,WV来进行变换得到Query,Keys,Values。而Multi-Head Attention使用多组W Q , W K , W V W^Q,W^K,W^VWQ,WK,WV得到多组Query,Keys,Values,然后每组分别计算得到一个Z矩阵,最后将得到的多个Z矩阵进行拼接。Transformer里面是使用了8组不同的W Q , W K , W V W^Q,W^K,W^VWQ,WK,WV。
从上图中可以看到,在经过Multi-Head Attention得到矩阵Z之后,并没有直接传入全连接神经网络FNN,而是经过了一步:Add&Normalize。
Add&Normalize:
Add
Add,就是在Z的基础上加了一个残差块X,加入残差块X的目的是为了防止在深度神经网络训练中发生退化问题,退化的意思就是深度神经网络通过增加网络的层数,Loss逐渐减小,然后趋于稳定达到饱和,然后再继续增加网络层数,Loss反而增大。可能看到这里,小朋友你一定有很多问号???为什么深度神经网络会发生退化,为什么添加残差块能够防止退化问题,残差块又是什么?这就牵扯到ResNet残差神经网络的知识了,既然是史上最小白系列,坚决不做标题党,一定把每个问题都解释清楚!
ResNet 残差神经网络:
首先解答第一个问题,为什么深度神经网络会发生退化?
举个例子:假如某个神经网络的最优网络层数是18层,但是我们在设计的时候并不知道到底多少层是最优解,本着层数越深越好的理念,我们设计了32层,那么32层神经网络中有14层其实是多余地,我们要想达到18层神经网络的最优效果,必须保证这多出来的14层网络必须进行恒等映射,恒等映射的意思就是说,输入什么,输出就是什么,可以理解成F(x)=x这样的函数,因为只有进行了这样的恒等映射咱们才能保证这多出来的14层神经网络不会影响我们最优的效果。
但现实是神经网络的参数都是训练出来地,要想保证训练出来地参数能够很精确的完成F(x)=x的恒等映射其实是很困难地。多余的层数较少还好,对效果不会有很大影响,但多余的层数一多,可能结果就不是很理想了。这个时候大神们就提出了ResNet 残差神经网络来解决神经网络退化的问题。
残差块是什么?
上图就是构造的一个残差块,可以看到X是这一层残差块的输入,也称作F(X)为残差,X为输入值,F(X)是经过第一层线性变化并激活后的输出,该图表示在残差网络中,第二层进行线性变化之后激活之前,F(X)加入了这一层输入值X,然后再进行激活后输出。在第二层输出值激活前加入X,这条路径称作shortcut连接。
为什么添加了残差块能防止神经网络退化问题呢?
咱们再来看看添加了残差块后,咱们之前说的要完成恒等映射的函数变成什么样子了。是不是就变成h(X)=F(X)+X,我们要让h(X)=X,那么是不是相当于只需要让F(X)=0就可以了,这里就巧妙了!神经网络通过训练变成0是比变成X容易很多地,因为大家都知道咱们一般初始化神经网络的参数的时候就是设置的[0,1]之间的随机数嘛。所以经过网络变换后很容易接近于0。举个例子:
假设该网络只经过线性变换,没有bias也没有激活函数。我们发现因为随机初始化权重一般偏向于0,那么经过该网络的输出值为[0.6 0.6],很明显会更接近与[0 0],而不是[2 1],相比与学习h(x)=x,模型要更快到学习F(x)=0。
并且ReLU能够将负数激活为0,过滤了负数的线性变化,也能够更快的使得F(x)=0。这样当网络自己决定哪些网络层为冗余层时,使用ResNet的网络很大程度上解决了学习恒等映射的问题,用学习残差F(x)=0更新该冗余层的参数来代替学习h(x)=x更新冗余层的参数。
这样当网络自行决定了哪些层为冗余层后,通过学习残差F(x)=0来让该层网络恒等映射上一层的输入,使得有了这些冗余层的网络效果与没有这些冗余层的网络效果相同,这样很大程度上解决了网络的退化问题。
到这里,关于Add中为什么需要加上一个X,要进行残差网络中的shortcut你清楚了吗?Transformer中加上的X也就是Multi-Head Attention的输入,X矩阵。
Normalize
为什么要进行Normalize呢?
在神经网络进行训练之前,都需要对于输入数据进行Normalize归一化,目的有二:1,能够加快训练的速度。2.提高训练的稳定性。
为什么使用Layer Normalization(LN)而不使用Batch Normalization(BN)呢?
先看图,LN是在同一个样本中不同神经元之间进行归一化,而BN是在同一个batch中不同样本之间的同一位置的神经元之间进行归一化。
BN是对于相同的维度进行归一化,但是咱们NLP中输入的都是词向量,一个300维的词向量,单独去分析它的每一维是没有意义地,在每一维上进行归一化也是适合地,因此这里选用的是LN。
Feed-Forward Networks
全连接层公式如下:
F F N ( x ) = m a x ( 0 , x W 1 + b 1 ) W 2 + b 2 FFN(x)=max(0,xW_1+b_1)W_2+b_2FFN(x)=max(0,xW1+b1)W2+b2
这里的全连接层是一个两层的神经网络,先线性变换,然后ReLU非线性,再线性变换。
这里的x就是我们Multi-Head Attention的输出Z,还是引用上面的例子,那么Z是(2,64)维的矩阵,假设W1是(64,1024),其中W2与W1维度相反(1024,64),那么按照上面的公式:
FFN(Z)=(2,64)x(64,1024)x(1024,64)=(2,64),我们发现维度没有发生变化,这两层网络就是为了将输入的Z映射到更加高维的空间中(2,64)x(64,1024)=(2,1024),然后通过非线性函数ReLU进行筛选,筛选完后再变回原来的维度。
然后经过Add&Normalize,输入下一个encoder中,经过6个encoder后输入到decoder中,至此Transformer的Encoder部分就全部介绍完了,搞懂了Encoder那么Decoder就so easy啦,基本上结构和Encoder差不多,接下来咱们就进入Decoder部分吧~
2.3 Transformer的Decoder
看上图第3部分 Decoder block。Decoder block也是由6个decoder堆叠而成,Nx=6。上图3中的灰框部分就是一个decoder的内部结构,从图中我们可以看出一个decoder由Masked Multi-Head Attention,Multi-Head Attention 和 全连接神经网络FNN构成。比Encoder多了一个Masked Multi-Head Attention,其他的结构与encoder相同,那么咱们就先来看看这个Masked Multi-Head Attention。
Transformer Decoder的输入
Decoder的输入分为两类:
一种是训练时的输入,一种是预测时的输入。
训练时的输入就是已经对准备好对应的target数据。例如翻译任务,Encoder输入"Tom chase Jerry",Decoder输入"汤姆追逐杰瑞"。
预测时的输入,一开始输入的是起始符,然后每次输入是上一时刻Transformer的输出。例如,输入"",输出"汤姆",输入"汤姆",输出"汤姆追逐",输入"汤姆追逐",输出"汤姆追逐杰瑞",输入"汤姆追逐杰瑞",输出"汤姆追逐杰瑞"结束。
Masked Multi-Head Attention
与Encoder的Multi-Head Attention计算原理一样,只是多加了一个mask码。mask 表示掩码,它对某些值进行掩盖,使其在参数更新时不产生效果。Transformer 模型里面涉及两种 mask,分别是 padding mask 和 sequence mask。为什么需要添加这两种mask码呢?
1.padding mask
什么是 padding mask 呢?因为每个批次输入序列长度是不一样的也就是说,我们要对输入序列进行对齐。具体来说,就是给在较短的序列后面填充 0。但是如果输入的序列太长,则是截取左边的内容,把多余的直接舍弃。因为这些填充的位置,其实是没什么意义的,所以我们的attention机制不应该把注意力放在这些位置上,所以我们需要进行一些处理。
具体的做法是,把这些位置的值加上一个非常大的负数(负无穷),这样的话,经过 softmax,这些位置的概率就会接近0!
2.sequence mask
sequence mask 是为了使得 decoder 不能看见未来的信息。对于一个序列,在 time_step 为 t 的时刻,我们的解码输出应该只能依赖于 t 时刻之前的输出,而不能依赖 t 之后的输出。因此我们需要想一个办法,把 t 之后的信息给隐藏起来。这在训练的时候有效,因为训练的时候每次我们是将target数据完整输入进decoder中地,预测时不需要,预测的时候我们只能得到前一时刻预测出的输出。
那么具体怎么做呢?也很简单:产生一个上三角矩阵,上三角的值全为0。把这个矩阵作用在每一个序列上,就可以达到我们的目的。
上面可能忘记说了,在Encoder中的Multi-Head Attention也是需要进行mask地,只不过Encoder中只需要padding mask即可,而Decoder中需要padding mask和sequence mask。OK除了这点mask不一样以外,其他的部分均与Encoder一样啦~
Add&Normalize也与Encoder中一样,接下来就到了Decoder中第二个Multi-Head Attention,这个Multi-Head Attention又与Encoder中有一点点不一样。
基于Encoder-Decoder 的Multi-Head Attention
Encoder中的Multi-Head Attention是基于Self-Attention地,Decoder中的第二个Multi-Head Attention就只是基于Attention,它的输入Quer来自于Masked Multi-Head Attention的输出,Keys和Values来自于Encoder中最后一层的输出。
跟我一样的牛角尖型选手可能又要发问啦,为啥Decoder中要搞两个Multi-Head Attention呢?
我个人理解是第一个Masked Multi-Head Attention是为了得到之前已经预测输出的信息,相当于记录当前时刻的输入之间的信息的意思。第二个Multi-Head Attention是为了通过当前输入的信息得到下一时刻的信息,也就是输出的信息,是为了表示当前的输入与经过encoder提取过的特征向量之间的关系来预测输出。
经过了第二个Multi-Head Attention之后的Feed Forward Network与Encoder中一样,然后就是输出进入下一个decoder,如此经过6层decoder之后到达最后的输出层。
2.4 Transformer的输出
Output如图中所示,首先经过一次线性变换,然后Softmax得到输出的概率分布,然后通过词典,输出概率最大的对应的单词作为我们的预测输出。
2.5 结构总结
好啦,以上就是Transformer的全部结构原理啦,Transformer真的不愧是近几年来最火的模型,很多细节都很巧妙,真的想要搞懂还是需要花点心思地。不知道看到这里,小伙伴们对于Transformer的结构有没有清晰一些呢?
3.Transformer优缺点
Transformer虽然好,但它也不是万能地,还是存在着一些不足之处,接下来就来介绍一下它的优缺点:
优点:
1.效果好
2.可以并行训练,速度快
3.很好地解决了长距离依赖的问题
缺点:
1.完全基于self-attention,对于词语位置之间的信息有一定的丢失,虽然加入了positional encoding来解决这个问题,但也还存在着可以优化的地方。
参考
史上最小白之Transformer详解
详解Transformer (Attention Is All You Need)
碎碎念:Transformer的细枝末节
以上是关于Transformer总结的主要内容,如果未能解决你的问题,请参考以下文章
transformer预测过程_Transformer在推荐模型中的应用总结
stn,spatial transformer network总结