zoukankan      html  css  js  c++  java
  • 【NLP-12】Transformer(Atention is all you need)

    目录

    1. transformer简介
    2. transformer模型分析
    3. 相关对比和问题

    一句话简介2017年(Atention is all you need)引出,采用了 从Encoder(2个子层)-Decoder(3个子层)架构,包含几个重要组件:Self-Attention,Multi-Headed Attention(8个矩阵,类似CNN中的多个卷积核)以及FFN,masked mutil-head attetion,LN,Positional Encoding这些组件。

       

    一、transformer简介

    1.1 基础介绍

    首先回顾下将Attention(实质上就是Encoder中隐层输出的加权和)机制从encoer-decoder 框架中抽出,进一步抽象化,其本质上如下图

    计算Attention的整个流程大致如下:

    1)计算Query和source中各个Key的相似性,得到每个Key对应的Value的权重系数。在这里我认为Key的值是source的隐层输出,Key是等于Value的,Query是target的word embedding(这种想法保留);

    2)利用计算出来的权重系数对各个Value的值加权求和,就得到了我们的Attention的结果。

    1.2 Transformer介绍

    《Attention Is All You Need》是一篇Google提出的将Attention思想发挥到极致的论文。这篇论文中提出一个全新的模型,叫 Transformer,抛弃了以往深度学习任务里面使用到的 CNN(当然实际构建构成中也用到了CNN的思想) 和 RNN。大热的Bert就是基于Transformer构建的,这个模型广泛应用于NLP领域,例如机器翻译,问答系统,文本摘要和语音识别等等方向。

    二、transformer模型分析

    2.1 总体结构

    Transformer的结构和Attention模型一样,Transformer模型中也采用了 encoer-decoder 架构。但其结构相比于Attention更加复杂,论文中encoder层由6个encoder堆叠在一起,decoder层也一样。

    不了解Attention模型的,可以回顾之前的文章:【NLP-11-1】注意力机制(Attention)

    每一个encoder和decoder的内部结构如下图:

    1encoder,包含两层,一个self-attention层和一个前馈神经网络,self-attention能帮助当前节点不仅仅只关注当前的词,从而能获取到上下文的语义。

    输入的序列长度是n,embedding维度是d,所以输入是n*d的矩阵 由两个子层组成:

    Sub-L1:

    • Multi-head self-attention
    • 残余连接和LN:
    • Output = LN (x+sublayer(x))
    • N=6,6个重复一样的结构

    Sub-L2:

    • Position-wise fc(跟卷积很像)
    • n*d的矩阵的每一行进行操作(相当于把矩阵每一行铺平,接一个FC),同一层的不同行FC层用一样的参数,不同层用不同的参数(对于全连接的节点数目,先从512变大为2048,再缩小为512),这里的max表示使用relu激活函数:

    整个encoder的输出也是n*d的矩阵

    2decoder也包含encoder提到的两层网络,但是在这两层中间还有一层attention层,帮助当前节点获取到当前需要关注的重点内容。

    •输入:假设已经翻译出k个词,向量维度还是d

    •同样使用N=6个重复的层,依然使用残余连接和LN

    •3个子层,比encoder多一个attention层,是Decoder端去attend encoder端的信息的层:

    Sub-L1:self-attention,同encoder,但要Mask掉未来的信息,得到k*d的矩阵

    Sub-L2:和encoder做attention的层,输出k*d的矩阵

    Sub-L3:全连接层,输出k*d的矩阵,用第k行去预测输出y

    另外特征提取方面的图,再看下各层的位置,后续会展开描述:

    2.2 Self-Attention

    self-attention在上一篇文章【NLP-11】注意力机制(Attention)中也有介绍。思想和attention类似,但是self-attention是Transformer用来将其他相关单词的"理解"转换成我们正在处理的单词的一种思路,实际上相当于QKV都来自本身,可以表示成Attention(X,X,X)形式。

    作用的话我们看个例子:The animal didn't cross the street because it was too tired

    这里的 it 到底代表的是 animal 还是 street 呢,对于我们来说能很简单的判断出来,但是对于机器来说,是很难判断的,self-attention就能够让机器把 it 和 animal 联系起来。

    Google论文的主要贡献之一是它表明了内部注意力在机器翻译(甚至是一般的Seq2Seq任务)的序列编码上是相当重要的,而之前关于Seq2Seq的研究基本都只是把注意力机制用在解码端。类似的事情是,目前SQUAD阅读理解的榜首模型R-Net也加入了自注意力机制,这也使得它的模型有所提升。

    2.3 Multi-Headed Attention

    这个是Google提出的新概念,是Attention机制的完善。不过从形式上看,它其实就再简单不过了,就是把Q,K,V通过参数矩阵映射一下,然后再做Attention,把这个过程重复做h次,结果拼接起来就行了,可谓"大道至简了。tranformer是使用了8,所以最后得到的结果是8个矩阵。

    表达式的计算如下:

    1)假设现在头数为h,首先按照每一时序上的向量长度(如果是词向量的形式输入,可以理解为embedding size的值)等分成h份。

    2)然后将上面等分后的h份数据分别通过不同的权重映射得到新的Q, K, W的值。

    3)将上述映射后的h份数据计算相应的Attention的值。

    4)按照之前分割的形式重新拼接起来,再映射到原始的向量维度。就得到Multi-Head Attention的值。在这里每一次映射的矩阵都不相同,因此映射之后再计算也就会得到不一样的结果。Multi-Head Attention的机制有点类似与卷积中的多个卷积核,在卷积网络中,我们认为不同的卷积核会捕获不同的局部信息,在这里也是一样,我们认为Multi-Head Attention主要有两个作用:

    1)增加了模型捕获不同位置信息的能力,如果你直接用映射前的Q, K, V计算,只能得到一个固定的权重概率分布,而这个概率分布会重点关注一个位置或个几个位置的信息,但是基于Multi-Head Attention的话,可以和更多的位置上的词关联起来。

    2)因为在进行映射时不共享权值,因此映射后的子空间是不同的,认为不同的子空间涵盖的信息是不一样的,这样最后拼接的向量涵盖的信息会更广。

    2.4 Layer normalization

    在transformer中,每一个子层(self-attetion,Feed Forward Neural Network)之后都会接一个残缺模块,并且有一个Layer normalization。

       

    Normalization有很多种,但是它们都有一个共同的目的,那就是把输入转化成均值为0方差为1的数据。我们在把数据送入激活函数之前进行normalization(归一化),因为我们不希望输入数据落在激活函数的饱和区。

    Batch Normalization

    BN的主要思想就是:在每一层的每一批数据上进行归一化。我们可能会对输入数据进行归一化,但是经过该网络层的作用后,我们的数据已经不再是归一化的了。随着这种情况的发展,数据的偏差越来越大,我的反向传播需要考虑到这些大的偏差,这就迫使我们只能使用较小的学习率来防止梯度消失或者梯度爆炸。BN的具体做法就是对每一小批数据,在批这个方向上做归一化。

    Layer normalization

    它也是归一化数据的一种方式,不过LN 是在每一个样本上计算均值和方差,有点类似CV用到的instance normalization而不是BN那种在批方向计算均值和方差!公式如下:

    直观比较下两者差异:

    2.5 Feed Forward Neural NetworkFFN层)

    前馈神经网络没法输入 8 个矩阵呀,这该怎么办呢?所以我们需要一种方式,把 8 个矩阵降为 1 个,首先,我们把 8 个矩阵连在一起,这样会得到一个大的矩阵,再随机初始化一个矩阵和这个组合好的矩阵相乘,最后得到一个最终的矩阵。

    具体公式可以表示为:FFN(x)=Relu(xW1+b1)W2+b2

    层采用了全连接层加Relu函数实现,其实关于在这里并不一定要用全连接层,也可以使用卷积层来实现。

    2.6 masked mutil-head attetion

    mask 表示掩码,它对某些值进行掩盖,使其在参数更新时不产生效果。Transformer 模型里面涉及两种 mask,分别是 padding mask 和 sequence mask。其中,padding mask 在所有的 scaled dot-product attention 里面都需要用到,而 sequence mask 只有在 decoder 的 self-attention 里面用到。

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

    Sequence mask
    文章前面也提到,sequence mask 是为了使得 decoder 不能看见未来的信息。也就是对于一个序列,在 time_step 为 t 的时刻,我们的解码输出应该只能依赖于 t 时刻之前的输出,而不能依赖 t 之后的输出。因此我们需要想一个办法,把 t 之后的信息给隐藏起来。
    那么具体怎么做呢?也很简单:产生一个上三角矩阵,上三角的值全为0。把这个矩阵作用在每一个序列上,就可以达到我们的目的

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

    2.7 Output

    decoder层全部执行完毕后,怎么把得到的向量映射为我们需要的词呢,很简单,只需要在结尾再添加一个全连接层和softmax层,假如我们的词典是1w个词,那最终softmax会输入1w个词的概率,概率值最大的对应的词就是我们最终的结果。

    2.9 Positional Encoding

    引入的原因:transformer模型因为抛弃了CNNRNN,而使用attention机制来关注重点信息,故缺少时序序列比较重要的位置信息,顾引入此模块。

    transformer给encoder层和decoder层的输入添加了一个额外的向量Positional Encoding,维度和embedding的维度一样,这个向量采用了一种很独特的方法来让模型学习到这个值,这个向量能决定当前词的位置,或者说在一个句子中不同的词之间的距离。这个位置向量的具体计算方法有很多种,论文中的计算方法如下:

    其中pos是指当前词在句子中的位置,i是指向量中每个值的index,可以看出,在偶数位置,使用正弦编码,在奇数位置,使用余弦编码

    最后把这个Positional Encodingembedding的值相加,作为输入送到下一层。

    Position Embedding并不算新鲜的玩意,在FaceBook的《Convolutional Sequence to Sequence Learning》也用到了这个东西。但在Google的这个作品中,它的Position Embedding有几点区别:

    1、以前在RNN、CNN模型中其实都出现过Position Embedding,但在那些模型中,Position Embedding是锦上添花的辅助手段,也就是"有它会更好、没它也就差一点点"的情况,因为RNN、CNN本身就能捕捉到位置信息。但是在这个纯Attention模型中,Position Embedding是位置信息的唯一来源,因此它是模型的核心成分之一,并非仅仅是简单的辅助手段。

    2、Position Embedding本身是一个绝对位置的信息,但在语言中,相对位置也很重要,Google选择前述的位置向量公式的一个重要原因是:这表明位置p+k的向量可以表示成位置p的向量的线性变换,这提供了表达相对位置信息的可能性。

    三、相关对比和问题

    3.1 Transformer为什么需要进行Multi-head Attention

    原论文中说到进行Multi-head Attention的原因是将模型分为多个头,形成多个子空间,可以让模型去关注不同方面的信息,最后再将各个方面的信息综合起来。其实直观上也可以想到,如果自己设计这样的一个模型,必然也不会只做一次attention,多次attention综合的结果至少能够起到增强模型的作用,也可以类比CNN中同时使用多个卷积核的作用,直观上讲,多头的注意力有助于网络捕捉到更丰富的特征/信息

    3.2 Transformer相比于RNN/LSTM,有什么优势?

    RNN系列的模型,并行计算能力很差。RNN并行计算的问题就出在这里,因为 T 时刻的计算依赖 T-1 时刻的隐层计算结果,而 T-1 时刻的计算依赖 T-2 时刻的隐层计算结果,如此下去就形成了所谓的序列依赖关系。

    Transformer的特征抽取能力比RNN系列的模型要好。
    具体实验对比可以参考:参考文献【4】
    但是值得注意的是,并不是说Transformer就能够完全替代RNN系列的模型了,任何模型都有其适用范围,同样的,RNN系列模型在很多任务上还是首选,熟悉各种模型的内部原理,知其然且知其所以然。

    3.3 Transformer对比seq2seq优势?

    seq2seq缺点:seq2seq最大的问题在于将Encoder端的所有信息压缩到一个固定长度的向量中,并将其作为Decoder端首个隐藏状态的输入,来预测Decoder端第一个单词(token)的隐藏状态。在输入序列比较长的时候,这样做显然会损失Encoder端的很多信息,而且这样一股脑的把该固定向量送入Decoder端,Decoder端不能够关注到其想要关注的信息。

    Transformer优点:transformer不但对seq2seq模型这两点缺点有了实质性的改进(Multi-head Attention模块),而且还引入了self-attention模块,让源序列和目标序列首先"自关联"起来,这样的话,源序列和目标序列自身的embedding表示所蕴含的信息更加丰富,而且后续的FFN层也增强了模型的表达能力,并且Transformer并行计算的能力是远远超过seq2seq系列的模型,因此我认为这是transformer优于seq2seq模型的地方。

    3.4 Transformer缺陷

    1. Transformer不像CNN那样可以抽取局部特征,RNN + CNN + Transformer的结合可能会带来更好的效果;
    2. 位置信息其实在NLP中非常重要,Transformer中用的Position Embedding也不是一个最终的解决方案。
    3. 捕捉长距离信息能力还有待提升,这个不足将在Transformer-XL中进行改进。可见后面文章。

    3.5 Transformer优势

    1. 并行运算能力
    2. 有CNN的速度,兼有RNN的性能
    3. 使得深度网络在NLP领域成为可能
    4. 为大火的Bert的产生打下了坚实的基础

    参考文献

    【1】The Illustrated Transformer : https://jalammar.github.io/illustrated-transformer/

    【2】transformer : https://www.cnblogs.com/jiangxinyang/p/10069330.html

    【3】《Attention is All You Need》浅读(简介+代码): https://kexue.fm/archives/4765

    4】自然语言处理三大特征抽取器(CNN/RNN/TF)比较: https://zhuanlan.zhihu.com/p/54743941

    5github大火的transformers: https://github.com/huggingface/transformers

  • 相关阅读:
    Fix Installing .NET Framework 3.5 failed Error Code 0x800F0954 on Windows 10
    RHEL8安装五笔输入法
    Enable EPEL and Local Repository on RHEL8
    Why is Yum Replaced by DNF?
    检查Linux服务器是否被攻击的常用命令及方法
    IDEA 主题
    IDEA 如何显示一个类中所有的方法
    Appium 安装以及安装过程中遇到的问题
    Maven 如何发布 jar 包到 Nexus 私库
    java泛型的基本使用
  • 原文地址:https://www.cnblogs.com/yifanrensheng/p/13167769.html
Copyright © 2011-2022 走看看