(6)一文懂Transformer

1、简介

    Attention Is All You Need 是一篇Google 2017年提出的将Attention思想发挥到极致的论文。这篇论文中提出一个全新的模型,叫 Transformer,这个模型最初是为了提高机器翻译的效率,它的Self-Attention机制和Position Encoding可以替代RNN。因为RNN是顺序执行的,t时刻没有完成就不能处理t+1时刻,因此很难并行。

    Transformer抛弃了以往深度学习任务里面使用到的 CNN 和 RNN ,著名的OpenAI GPT和BERT模型都是基于Transformer构建的,这个模型广泛应用于NLP领域,例如机器翻译,问答系统,文本摘要和语音识别等等方向,目前也逐步应用在视觉领域。

1.1 Embedding

    input embedding是编码器的输入,output embedding是解码器的输入。最底层的编码器的输入为词向量,通过word2vec的算法得到的词embedding。

    input embedding和output embedding 都是通过token embedding matrix 得到的,需要先各自构建token embedding matrix,维度是vocab_size * d_model,其中vocab_size是词汇量的大小,d_model是词向量的长度,也就是说每一个词都用一个d_model维的向量表示,所有的词合起来就构成了这个矩阵,即词库。每个单词是由词的id构成的向量,以机器翻译为例,要把T1长的英文翻译成T2长的中文,那么encode inputs T1长的英文词id list,decoder inputs就是对应T2长的中文词id list,所以最终得到的output embedding是T2乘d_model维。

    这里可以看出,机器翻译的本质是学习不同语言间词的id的对应情况

1.2 Positional Encoding(位置嵌入)

    我们的目的是用Self-Attention替代RNN,RNN能够记住过去的信息,且能考虑词的顺序(位置)关系。一个句子即使词完全是相同的但是语义可能完全不同,比如”北京到上海的机票”与”上海到北京的机票”,它们的语义就有很大的差别。如果模型参数固定了,上面两个句子的北京都会被编码成相同的向量。但是实际上我们可以期望这两个北京编码的结果不同,前者可能需要编码出发城市的语义,而后者需要包含目的城市的语义。

    词序中最重要的两个信息,一个是绝对顺序,也就是一个词在整句话的第几个,另一个是相对顺序,也就是两个词之间的距离是多少,那么在论文中transformer如何保证保留这两个信息呢?对于一个input embedding来说,它输入到编码层时不像RNN是一个词一个词进去的,而是一次性进去的,失去了文本顺序,一句话很可能不再通畅。为了解决这个问题,我们需要引入位置编码(记录单词的先后顺序),也就是t时刻的输入,除了Embedding之外(这是与位置无关的),我们还引入一个向量,这个向量是与t有关的,我们把Embedding和位置编码向量加起来作为模型的输入。这样的话如果两个词在不同的位置出现了,虽然它们的Embedding是相同的,但是由于位置编码不同,最终得到的向量也是不同的。这个位置向量的具体计算方法有很多种,论文中的计算方法如下:

      PE(pos, 2i)=sin(pos/100002i/dmodel​)

      PE(pos, 2i+1)=cos(pos/100002i/dmodel​)

    其中pos是指当前词在句子中的位置,i是指d_model=512向量中每个值的index,可以看出,在偶数位置,使用正弦编码,在奇数位置,使用余弦编码。一个具体的Embedding +Positional Encoding的例子如下图所示:

2、Transformer架构

    和seq2seq模型一样,Transformer模型中也采用了 encoer-decoder 架构。但其结构相比于Attention更加复杂,论文中编码器由6个编码block组成,同样解码器是6个解码block组成。所有的编码器在结构上都是相同的,负责把自然语言序列映射成为隐藏层,它们含有自然语言序列的表达式,然后解码器把隐藏层再映射为自然语言序列,从而解决各种 NLP 问题,如图:

    Encoder 6 层组成,每一层包括两个子层:第一层 multi-head self-attention 层(8个heads),第二层是一个简单的全连接前馈网络。在每个子层后都接了一个残差连接以及归一化。

    Decoder同样由 6 层组成,不过在最下面额外多了一个masked mutil-head attetion,每一层包括三个子层:第一层是 masked multi-head self-attention 层,注意其输入仅包含当前位置之前的词语信息,第二层是 multi-head self-attention 层,其输入包含编码器的输出信息(矩阵 K 和矩阵 V ),第三层是全连接前馈网络。每个子层后同样加入了残差连接和归一化。如图(论文中Nx=6):

    位置编码采用正/余弦函数,最后把token embedding和position encoding相加,其实这才是真正意义上的编码器和解码器的输入:

3、 Encoder

3.1 Multi-head Attentio  

      论文中提出的Attention核心内容是为输入的每个单词向量学习一个权重,在self-attention中,每个单词有3个向量:Query向量,Key向量和Value向量,同时存在3个权重矩阵W(Q)/W(K)/W(V),矩阵维度为(512,512/8),矩阵是随机初始化的。

    Self-Attention整体的过程分为六步:

    1)word2embedding:通过word2vec的算法得到的词embedding,一个词对应一个d_mode=512词向量长度。(下面截图省略了位置编码,即省略了步骤2)

    2)位置编码,得到最终Encode输入:embedding + position encoding。假设输入2个单词x1/x2,则X =(2, 512)

    3)得到Q/K/V三个向量:X1/X2分别与W(Q)/W(K)/W(V)点积运算,维度为(2, 64)

      注:为了便于说明图示X=(2,4), W(Q)/W(K)/W(V)=(4,3), Q/K/V=(1,3)

             实际为:X=(2,512),W(Q)/W(K)/W(V)=(512,64),Q/K/V=(2,64)

    4)Score:计算self-attention的分数值,该分数值决定了当我们在某个位置encode一个词时,对输入句子的其他部分的关注程度。这个分数值的计算方法是Query与Key做点成,我们需要针对Thinking这个词,计算出其他词对于该词的一个分数值,首先是针对于自己本身即q1·k1,然后是针对于第二个词即q1·k2,Score=QK(T) =(2, 2)

    5)Divide:把点成的结果除以一个常数,这里我们除以8,这个值一般是采用上文提到的矩阵的第一个维度的开方即64的开方8,当然也可以选择其他的值,然后把得到的结果做一个softmax的计算。得到的结果即是每个词对于当前位置的词的相关性大小,当前位置的词相关性肯定会很大

    6)输出Z(Attention Value):Value和softmax得到的值进行相乘,并相加,得到的结果即是self-attetion在当前节点的值。Z=softmax(Score/8)*V=(2, 64)

     7)Multi-head Attention:8个heads concat又进行了线性变换:Z(concat)=(2, 64*8),

W(O) = (512, 512),最终Z = Z(concat)*W(O) = (2, 512),与输入保持一致

多头注意力机制概括步骤如下:

 3.3 残差与LN

    每个Self-Attention层都会加一个残差连接,然后是一个LayerNorm层,如下图所示:

    随着网络深度增加,网络的表现先是逐渐增加至饱和,然后迅速下降。残差缓解了梯度消失,能够使网络往深的做。采用LN而不使用BN的原因:

        1)长短不定

        2)同一维度信息没有相关性

4、 Decoder

    decoder部分其实和encoder部分大同小异,不过在最下面额外多了一个masked mutil-head attetion,这里的mask也是transformer一个很关键的技术。

1、encoder最终输出作为Decoder每层的输入:

 2、encoder最终输出K/V矩阵,decoder输入V矩阵:

3、为什么使用mask:

     上图为sequence mask,Transformer 模型里面涉及两种mask,分别是 padding mask 和 sequence mask。其中,padding mask 在所有的 scaled dot-product attention 里面都需要用到,而 sequence mask 只有在 decoder 的 self-attention 里面用到。

    Padding Mask:因为每个批次输入序列长度是不一样的也就是说,我们要对输入序列进行对齐。具体来说,就是给在较短的序列后面填充 0。但是如果输入的序列太长,则是截取左边的内容,把多余的直接舍弃。因为这些填充的位置,其实是没什么意义的,所以我们的attention机制不应该把注意力放在这些位置上,所以我们需要进行一些处理。具体的做法是,把这些位置的值加上一个非常大的负数(负无穷),这样的话,经过 softmax,这些位置的概率就会接近0!而我们的 padding mask 实际上是一个张量,每个值都是一个Boolean,值为 false 的地方就是我们要进行处理的地方。

    Sequence mask:为了使得 decoder 不能看见未来的信息。也就是对于一个序列,在 time_step 为 t 的时刻,我们的解码输出应该只能依赖于 t 时刻之前的输出,而不能依赖 t 之后的输出。因此我们需要想一个办法,把 t 之后的信息给隐藏起来。

    对于 decoder 的 self-attention,里面使用到的 scaled dot-product attention,同时需要padding mask 和 sequence mask 作为 attn_mask,具体实现就是两个mask相加作为attn_mask。其他情况,attn_mask 一律等于 padding mask。

5、Transformer参数量与计算量

      参考:https://blog.csdn.net/huangblog/article/details/119639001

      参考:https://blog.csdn.net/huangblog/article/details/119636791

  • 0
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值