Transformer模型

参考文章:
神经机器翻译 之 谷歌 transformer 模型
Self-attention and Transformer
大数据文摘-BERT大火却不懂Transformer&version=11020201&lang=zh_CN&pass_ticket=sLCET0Y%2BZTkYDsKSej3nfbOS885niL2%2Bt2ffNlFmQw3FszFuawe4q3nwl02gUnCe)
从头开始了解Transformer

背景

  • 首先理解Attention模型,个人理解Transformer本质其实就是对selt-attention的包装
  • 论文《Attention is all you need》特点:
    重点关注了复杂度,并行度,长距离依赖学习三个问题
    • 现在做神经翻译里最好的BLUE结果
    • 没有采取大热的RNN/LSTM/GRU的结构,而是使用attention layer 和全连接层,达到了较好的效果,并且解决了 RNN/LSTM/GRU 里的long dependency problem
    • 解决了传统RNN 训练并行度的问题,并降低了计算复杂度

Encoder-Decoder架构

  • Encoder-Decoder架构整体

    • 在编码器的一个网络块中,由一个多头attention子层和一个前馈神经网络子层组成,整个编码器栈式搭建了N个块
    • 解码器的一个网络块中多了一个多头attention层。为了更好的优化深度网络,整个网络使用了残差连接和对层进行了规范化(Add&Norm)
      • 这里有个特别点就是masking, masking 的作用就是防止在训练的时候 使用未来的输出的单词。 比如训练时, 第一个单词是不能参考第二个单词的生成结果的。 Masking就会把这个信息变成0, 用来保证预测位置 i 的信息只能基于比 i 小的输出
  • Encode组件

  • Decode组件

    • 编码器通过处理输入序列开启工作。顶端编码器的输出之后会变转化为一个包含向量K(键向量)和V(值向量)的注意力向量集 。这些向量将被每个解码器用于自身的“编码-解码注意力层”,而这些层可以帮助解码器关注输入序列哪些位置合适
    • 接下来的步骤重复了这个过程,直到到达一个特殊的终止符号, - 它表示transformer的解码器已经完成了它的输出。每个步骤的输出在下一个时间步被提供给底端解码器,并且就像编码器之前做的那样,这些解码器会输出它们的解码结果
    • 这个“编码-解码注意力层”工作方式基本就像多头自注意力层一样,只不过它是通过在它下面的层来创造查询矩阵,并且从编码器的输出中取得键/值矩阵

  • 最终的线性变换和Softmax层
    解码组件最后会输出一个实数向量。我们如何把浮点数变成一个单词?这便是线性变换层要做的工作,它之后就是Softmax层

    • 线性变换层是一个简单的全连接神经网络,它可以把解码组件产生的向量投射到一个比它大得多的、被称作对数几率(logits)的向量里
    • 接下来的Softmax 层便会把那些分数变成概率(都为正数、上限1.0)。概率最高的单元格被选中,并且它对应的单词被作为这个时间步的输出

scaled dot-Product attention

  • 核心理解
    点积表示输入序列中两个向量的由学习任务定义的“相关”程度,并且输出向量是整个输入序列的加权和,其权重由这些点积确定
  • 本质:其实scaled dot-Product attention就是我们常用的使用点积进行相似度计算的attention,只是多除了一个(为K的维度)起到调节作用,使得内积不至于太大
  • 操作步骤
    • 每个query-key 会做出一个点乘的运算过程
    • 最后会使用soft max 把他们归一
    • 再到最后会乘以V (values) 用来当做attention vector.
  • 详细理解

Multi-head attention

  • 核心:
    我们必须考虑到一个词对不同的邻居有不同的意思,按照上面所描述,一个词对对应的输出也只是一个vector,只对应一种情况,但有些场景相同的语言,句子表达的含义完全不同,所以有了Multi head

Multi-head attention(1)

  • 它扩展了模型专注于不同位置的能力
    • 我理解就是不同的每个注意力头都会对会有不同的关注点,就是丰富了一个词的注意点
  • 它给出了注意力层的多个“表示子空间”(representation subspaces)

    • 接下来我们将看到,对于“多头”注意机制,我们有多个查询/键/值权重矩阵集(Transformer使用八个注意力头,因此我们对于每个编码器/解码器有八个矩阵集合)。这些集合中的每一个都是随机初始化的
    • 在训练之后,每个集合都被用来将输入词嵌入(或来自较低编码器/解码器的向量)投影到不同的表示子空间中
  • 如果我们做与上述相同的自注意力计算,只需八次不同的权重矩阵运算,我们就会得到八个不同的Z矩阵

  • 前馈层不需要8个矩阵,它只需要一个矩阵(由每一个单词的表示向量组成)

    • 所以我们需要一种方法把这八个矩阵压缩成一个矩阵。那该怎么做?其实可以直接把这些矩阵拼接在一起,然后用一个附加的权重矩阵WO与它们相乘

Multi-head attention(2)

  • Query,Key,Value首先进过一个线性变换
  • 然后输入到放缩点积attention
    • 注意这里要做h次,其实也就是所谓的多头,每一次算一个头
    • 每次Q,K,V进行线性变换的参数W是不一样的,所以每个头都计算自己的特征
    • 进行h个头计算好处:好处是可以允许模型在不同的表示子空间里学习到相关的信息
  • 然后将h次的放缩点积attention结果进行拼接(concat)
  • 再进行一次线性变换得到的值作为多头attention的结果

如何使用attention

  • 首先在编码器到解码器的地方使用了多头attention进行连接,编码器的层输出(这里K=V)和解码器中都头attention的输入。其实就和主流的机器翻译模型中的attention一样
  • 在Encoder,Decoder中都使用的self-attention
    • 例如输入一个句子,那么里面的每个词都要和该句子中的所有词进行attention计算。目的是学习句子内部的词依赖关系,捕获句子的内部结构

构建Transformer

  • Transformer不只是一个self-attention层,它是一个架构。目前Transformer的定义还不清楚,但在这里我们将使用以下定义:
    • 任何用于处理连接单元集 (connected units) 的体系结构——例如序列中的标记或图像中的像素——单元之间的唯一交互是通过self-attention
  • 如何构建:大致的结构如下
    • 各种组件的顺序不是一成不变的;重要的是将self-attention与本地前馈相结合,并添加归一化和残差连接
    • 归一化和残差连接是用于帮助深度神经网络训练更快,更准确的标准技巧。归一化层仅作用于嵌入维度。
  • 为什么这么设计?
    结合了RNN和CNN的优势,改善他们的缺点:Transformer试图吸收两者的优点。它们可以对输入序列的整个范围建立依赖关系,就像它们彼此相邻的单词一样容易(事实上,没有位置向量,它们甚至无法区分) 。然而,这里没有循环连接
    • RNN问题
      这里最大的弱点是循环连接,串行,并且时间步相隔较远的单元相互影响较小了
    • CNN问题
      在该模型中,每个输出向量可以与其他每个输出向量并行计算。这使得卷积更快。然而,卷积的缺点在于它们在模拟远程依赖方面受到严重限制。在一个卷积层中,只有相距比卷积核大小更小的单词才能相互交互。为了更长的依赖性,我们需要堆叠许多卷积

Transformer解决问题

  • 并行问题
    • 首先each head, 是可以并行计算的, 然后每个head 都有自己对应的weight, 实现不同的线性转换, 这样每个head 也就有了自己特别的表达信息
    • 多头attention和CNN一样不依赖于前一时刻的计算,可以很好的并行,优于RNN
  • 长距离依赖学习
    • self-attention是每个词和所有词都要计算attention,所以不管他们中间有多长距离,最大的路径长度也都只是1。可以捕获长距离依赖关系
  • RNN,CNN计算复杂度的比较
    • 如果输入序列n小于表示维度d的话,每一层的时间复杂度self-attention是比较有优势的。当n比较大时,作者也给出了一种解决方案self-attention(restricted)即每个词不是和所有词计算attention,而是只与限制的r个词去计算attention

训练部分&损失函数

Transformer只是一个encode-decode框架架构,后面的,训练&损失函数&优化算法就也能共用其他了,比如BP,集束搜索(beam search)…

  • 既然我们已经过了一遍完整的transformer的前向传播过程,那我们就可以直观感受一下它的训练过程。
  • 在训练过程中,一个未经训练的模型会通过一个完全一样的前向传播。但因为我们用有标记的训练集来训练它,所以我们可以用它的输出去与真实的输出做比较

Transformer应用

  • transformer本身并不能识别单词直接次序,句子前后次序等,bert是对transformer很成功的应用,在输入上增加了其他的信息:比如位置嵌入,句子次序,mask等的预训练模型