学习笔记:深度学习(7)——从Encoder-Decoder到Transformer

学习时间:2022.04.22~2022.04.24

6. 从Encoder-Decoder到Transformer

6.1 Encoder-Decoder框架

Encoder-Decoder 通常称作 编码器-解码器,是深度学习中常见的模型框架,很多常见的应用都是利用编码-解码框架设计的。

  • 编码(encode),由一个编码器将输入序列转化成一个固定维度的稠密向量;

  • 解码(decode),就是将之前生成的固定维度的稠密向量再转化成输出序列。

在这里插入图片描述

img

Encoder-Decoder 并不是一个具体的模型,而是一个通用的框架,并不是特指某一个具体的算法。Encoder 和 Decoder 部分可以是任意文字,语音,图像,视频数据,模型可以是 CNN,RNN,LSTM,GRU,Attention 等等。所以,基于 Encoder-Decoder,我们可以设计出各种各样的模型。

特别说明:

  • 不管输入序列和输出序列长度是什么,中间的「向量 C」长度都是固定的,而输入序列和输出序列的长度是可变的;
  • 中间向量的长度固定也是它的一个缺陷:向量压缩损失了信息;存在长程梯度消失问题,对于较长的句子,我们很难寄希望于将输入的序列转化为定长的向量而保存所有有效信息,即便 LSTM 加了门控机制可以选择性遗忘和记忆,随着所需翻译的句子难度怎能更加,这个结构的效果仍然不理想;
  • 不同的任务可以选择不同的编码器和解码器 (RNN,CNN,LSTM,GRU);
  • Encoder-Decoder的一个显著特征就是:它是一个end-to-end的学习算法,只要符合这种框架结构的模型都可以统称为Encoder-Decoder模型。

6.2 Seq2Seq序列到序列

Seq2Seq(Sequence-to-Sequence)如字面意思,输入一个序列,输出另一个序列。Seq2Seq是Encoder-Decoder模型框架的一个典型代表,可以看作是Encoder-Decoder针对某一类任务的模型框架。

img

所谓的Seq2Seq任务主要是泛指一些Sequence到Sequence的映射问题,Sequence在这里可以理解为一个字符串序列,当我们在给定一个字符串序列后,希望得到与之对应的另一个字符串序列(如 翻译后的、如语义上对应的)时,这个任务就可以称为Seq2Seq了。

Encoder-Decoder强调的是模型设计(编码-解码的一个过程),Seq2Seq强调的是任务类型/目的(序列到序列的问题),满足输入序列,输出序列的任务都可以统称为Seq2Seq模型。

应用场景:机器翻译、文本生成、语言模型、语音识别、抽象文本摘要、文本摘要、语义分析、问答、语音转换。

以机器翻译为例,可以将法语翻译成英语,满足这样任务的模型也可以叫做Seq2Seq。

在这里插入图片描述

早期的Seq2Seq,其编码和解码都使用RNN、LSTM、GRU等(最早的提出就用了两个RNN),但缺点显而易见:

一是语义向量无法完全表示整个序列的信息;二是先输入的内容携带的信息会被后输入的信息稀释掉,或者说,被覆盖了,输入序列越长,这个现象就越严重。这就使得在解码的时候一开始就没有获得输入序列足够的信息, 那么解码的准确度自然也就要打折扣。

因此,后续又提出了Attention机制、或者采用CNN(CNN可以并行,改善了lstm的性能瓶颈)来改善任务效果。

目前的Seq2Seq模型主要分为三种:

  1. 一种是以RNN为基础的模型, 一般是LSTM+Attention,顺序处理输入信息;
  2. 一种是以CNN为基础的模型,比如Fairseq;
  3. 一种是完全依靠Attention的模型,如谷歌的Transformer。

补充:Seq2Seq模型使用技巧——“Teacher Forcing”

Teacher Forcing 用于训练阶段,主要针对上面第三种Decoder模型来说的,第三种Decoder模型神经元的输入包括了上一个神经元的输出 y ′ y' y。如果上一个神经元的输出是错误的,则下一个神经元的输出也很容易错误,导致错误会一直传递下去。

而 Teacher Forcing 可以在一定程度上缓解上面的问题,在训练 Seq2Seq 模型时,Decoder 的每一个神经元并非一定使用上一个神经元的输出,而是有一定的比例采用正确的序列作为输入。即把正确的输出当做输入的一部分。

6.3 Attention注意力机制

为了解决上面的弊端,提升模型效果,就需要用到Attention注意力机制来解决该问题(Attention一般是跟Seq2Seq模型一起用的)。

在解码的时候,让生成词不是只能关注全局的语义编码向量C,而是增加了一个“注意力范围”来动态处理和解码(即没有把所有的内容都放到一个向量中)。在解码当前词时,会寻找于原语句中相对应的几个词语,然后结合之前已经翻译的序列来翻译下一个词。

通过这种方法,模型能够有选择地关注输入序列的有用部分,从而了解它们之间的对齐关系,有助于模型更好地处理输入较长的句子。

直观理解:

当我们翻译 Knowledge 时,我们只需要将注意力集中在 “知识” 上面,翻译 “is” 的时候,只需要将注意力集中在 “就是” 上面,翻译 “力量” 时将注意力集中在 “power” 上面。这样,当 Decoder 在预测目标翻译的时候,就可以看到 Encoder 的所有信息,而不仅局限于模型的定长隐向量,并且不会丢失重要信息。

在这里插入图片描述

6.3.1 模型概述

本部分参考:Attention原理详解。Seq2Seq +Attention的实现大致如下:

语义编码C随着decode的不同时刻,内容是动态变化的。用decode的每一个时刻的隐藏层输出去和encode的所有时刻的隐藏层输出计算一个Attention Score, 也就是decode当前时刻和enocde的每一个时刻的相关性,相关性大的计算的权重就大,最后对enocde的隐藏层做一个加权和作为decode当前时刻的语义编码C,这个C和decode的隐藏层做连接,然后接个全连接层(维度变一致)作为decode当前时刻的输出。

在Attention模型中,语义编码c1、c2、c3各不相同,y1、y2、y3的生成方法为: y 1 = f 1 ( C 1 ) ;   y 2 = f 1 ( C 2 , y 1 ) ; y 3 = f 1 ( C 3 , y 1 , y 2 ) y_1 = f1(C_1);\ y_2 = f1(C_2, y_1); y_3 = f1(C_3,y_1,y_2) y1=f1(C1); y2=f1(C2,y1);y3=f1(C3,y1,y2)

在这里插入图片描述

比如输入的是英文句子:Tom chase Jerry,生成:“汤姆”,“追逐”,“杰瑞”。注意力分配概率分布值的通用计算过程如下(以第一个词“Tom”为例):

在这里插入图片描述

当前输出词 Y i Y_i Yi针对某一个输入词j的注意力权重由当前的隐层 H i H_i Hi,以及输入词j的隐层状态 h j h_j hj共同决定;然后再接一个Softmax得到 [ 0 , 1 ] [0, 1] [0,1]的概率值。即通过函数 F ( h j , H i ) F(h_j,H_i) F(hj,Hi)来获得目标单词 Y i Y_i Yi和每个输入单词对应的对齐可能性。 a i j a_{ij} aij 衡量编码中第 j j j阶段的 h j h_j hj和解码时第 i i i阶段的相关性,最终解码中第 i i i阶段的输入的上下文信息 C i C_i Ci就来自于所有 h j h_j hj a i j a_{ij} aij的加权和。

那么整个翻译过程就可以表示为(每一个 C C C会自动去选取与当前所要输出的 y y y最合适的上下文信息):
C 汤 姆 = g ( 0.6 × f 2 ( T o m ) ,   0.2 × f 2 ( C h a s e ) ,   0.2 × f 2 ( J e r r y ) ) C 追 逐 = g ( 0.2 × f 2 ( T o m ) ,   0.7 × f 2 ( C h a s e ) ,   0.1 × f 2 ( J e r r y ) ) C 杰 瑞 = g ( 0.3 × f 2 ( T o m ) ,   0.2 × f 2 ( C h a s e ) ,   0.5 × f 2 ( J e r r y ) ) C_{汤姆} = g(0.6×f2(Tom),\ 0.2×f2(Chase),\ 0.2×f2(Jerry))\\ C_{追逐} = g(0.2×f2(Tom),\ 0.7×f2(Chase),\ 0.1×f2(Jerry))\\ C_{杰瑞} = g(0.3×f2(Tom),\ 0.2×f2(Chase),\ 0.5×f2(Jerry)) C=g(0.6×f2(Tom), 0.2×f2(Chase), 0.2×f2(Jerry))C=g(0.2×f2(Tom), 0.7×f2(Chase), 0.1×f2(Jerry))C=g(0.3×f2(Tom), 0.2×f2(Chase), 0.5×f2(Jerry))

如下图所示,红色代表输入输出相关性很强,相应的权重会很大,比如“ I ”和“我”的相关性就很大,“China” 和 “中”、“国” 两个输入的相关性很大。

输入的序列是“我爱中国”,因此,Encoder中的h1、h2、h3、h4就可以分别看做是“我”、“爱”、“中”、“国”所代表的信息。在翻译成英语时,第一个上下文c1应该和“我”这个字最相关,因此对应的 a11就比较大,而相应的 a12 、a13 、 a14 就比较小。c2应该和“爱”最相关,因此对应的 a22 就比较大。最后的c3和h3、h4最相关,因此 a33 、 a34的值就比较大。

img

总结一下就是:通过为每个单词分配一个权重,注意力机制能够保证当前翻译的单词对原文各个单词的关注点不同(就是对照着原文翻译)。由于这个权重可能大于1,为了方便我们使用softmax进行归一化,得到归一化权重,然后计算Encoder隐藏状态和其对应归一化权重的加权和,得上下文向量C(语义编码)。

6.3.2 过程详解

注意力层的实现可以分为7个步骤。

  1. 计算Encoder的隐藏状态和Decoder的隐藏状态

首先计算第一个解码器隐藏状态(红色)和所有可用的编码器隐藏状态(绿色)。下图中有4个编码器隐藏状态和当前解码器的隐藏状态。要想输出Decoder的第一个隐藏的状态,需要给Decoder一个初始状态和一个输入,例如采用Encoder的最后一个状态作为Decoder的初始状态,输入为0。

在这里插入图片描述

  1. 获取每个编码器隐藏状态对应的分数(Attention Score)

计算Decoder的第一个隐藏状态(当前单词)和Encoder所有的隐藏状态的相关性。计算相似性/相似度的方法有很多(比如dot、general、concat等),这里采用点积的方式(默认两个向量长度一样)。

在这里插入图片描述

  1. 通过softmax归一化分数

把得到的分数输入到softmax层进行归一化,归一化之后的分数(标量)加起来等于1,归一化后的分数代表注意力分配的权重 。

在这里插入图片描述

  1. 用每个编码器的隐藏状态乘以其softmax得分

通过将每个编码器的隐藏状态与其softmax之后的分数(标量)相乘,我们得到对齐向量 或标注向量。这正是对齐产生的机制。

在这里插入图片描述

  1. 把所有对齐的向量加起来

对齐向量进行求和,生成上下文向量 C 1 C_1 C1(语义编码)。上下文向量是前一步对齐向量的聚合信息。

在这里插入图片描述

  1. 将上下文向量输入到Decoder中

将上下文向量输入到Decoder中进行解码,具体的解码器输入方式和模型有关。

Decoder每个时刻都会将第5步的注意力权重输入到Decoder中,此时Decoder中的输入有:Encoder的输出向量,以及Decoder上一时刻的隐向量。

在这里插入图片描述

  1. 反向传播

    通过不断迭代,更新编码器和解码器的权重参数(以及Score中的权重,如果有的话),Decoder可以输出最终翻译的序列。

  2. 完整过程如下

在这里插入图片描述

6.3.3 Score评分函数

score函数涉及点积运算(点积、余弦相似度等),其思想是度量两个向量之间的相似度。对于前馈神经网络评分函数,其思想是让模型在变换的同时学习对齐权值

下图是几种主要的计算方式:

Summary of score functions img

6.3.4 基于seq2seq的Attention实例

接下来会介绍3个基于Seq2Seq的NMT(Neural Machine Translation,机器翻译)架构,通过了解具体的使用方式来加深对Attention的理解,来源:Attention原理详解

  1. Neural Machine Translation by Learning to Jointly Align and Translate

注意力机制用于机器翻译的开篇之作,作者在WMT’14英语 - 法语数据集上获得了26.75的BLEU分数。

[BLEU得分](https://blog.csdn.net/weixin_36815313/article/details/106649367#:~:text=BLEU 得分是一个有用的单一实数评估指标,用于评估生成文本的算法,判断输出的结果是否与人工写出的参考文本的含义相似。 不过它并没有用于语音识别(,speech recognition )。):是一个有用的单一实数评估指标(a single real number evaluation metric),用于评估生成文本的算法,判断输出的结果是否与人工写出的参考文本的含义相似。

标题中的“Align”意思是在训练模型的同时直接调整负责得分的权重。以下是该模型的特点:

  • 编码器是一个双向(正向+反向)门控循环单元(BiGRU)。解码器是一个GRU,其初始隐藏状态是从反向编码器GRU的最后隐藏状态修改而来的向量;

  • 注意层中的score函数是Additive/Concat;

  • 下一个解码器时间步的输入是前一个解码器时间步(粉红色)的输出与当前时间步(深绿色)的上下文向量之间的拼接。

img
  1. 《[Effective Approaches to Attention-based Neural Machine Translation](http://diyhpl.us/~bryan/papers2/ai/speech-recognition/Effective approaches to attention-based neural machine translation - 2015.pdf)》

在WMT’15英德测试中,该模型的BLEU得分为25.9。这篇论文的关键点如下:

  • Encoder是两层的LSTM网络。 Decoder也一样,其初始隐藏状态是最后一个编码器的隐藏状态;
  • 他们实验的score函数是(i) additive/concat, (ii) 点积,(iii) location-based,和(iv) “general”;
  • 来自当前解码器时间步长的输出与来自当前时间步长的上下文向量之间的串联被输入到前馈神经网络,以给出当前解码器时间步长的最终输出(粉红色)。
img
  1. Google’s Neural Machine Translation System: Bridging the Gap between Human and Machine Translation

GNMT,Google的神经机器翻译,是前面两个例子的组合(深受第一个例子的启发)。该模型在WMT’14英法测试上达到38.95 BLEU,在WMT’14英德测试上达到24.17 BLEU。这篇论文的关键点如下:

  • 编码器由8个LSTM组成,其中第一个LSTM是双向的(其输出是拼接起来的),来自连续层的输出之间存在残差连接(从第3层开始)。残差连接用曲线箭头表示。解码器是8个单向LSTM的独立堆叠;
  • 使用的score函数是additive/concat,类似于第一个例子;
  • 同样,就像第一个例子中一样,下一个解码器时间步的输入是前一个解码器时间步(粉红色)的输出和当前时间步(深绿色)的上下文向量之间的连接。
img

6.4 Self-Attention机制

Self Attention是提出Transformer的论文《Attention is all you need》中提出的一种新的注意力机制。

在机器翻译中,一般输入Source和输出Target内容是不一样的,如英文翻译成中文,Source是英文,Target是中文,上一节所讲的Attention机制发生在Target元素和Source中所有元素之间。

而Self-Attention顾名思义,指的不是Target和Source之间的Attention机制,而是Source内部元素之间或者Target内部元素之间发生的Attention机制,也可以理解为Target = Source的特殊情况下的Attention机制。其具体计算过程是一样的,只是计算对象发生了变化而已。

因此,我们可以把上一节所讲的Attention机制称为Seq2Seq Attention或传统Attention机制,Self Attention也可以被称为intra Attention(内部Attention)。

Seq2Seq Attention:本质上是目标语单词和源语单词之间的一种单词对齐机制

Self Attention:可以捕获同一个句子中单词之间的一些句法特征或者语义特征

6.4.1 机制详解

本节来源:超详细图解Self-Attention

在谈论Self Attention之前我们首先认识一下以KQV模型来解释的Attention机制,这也是Transformer最核心的部分。键值对Attention最核心的公式如下图。
A t t e n t i o n ( Q , K , V ) = s o f t m a x ( Q K T d k ) V Attention(Q,K,V)=softmax(\frac{QK^T}{\sqrt d_k})V Attention(Q,K,V)=softmax(d kQKT)V
其中, Q Q Q是Query、 K K K是Key、 V V V是Value。假定词的输入为 Q Q Q(Query),内存中以键值对 ( K , V ) (K,V) (K,V)形式存储其上下文。那么任何注意力机制其实都是Query到一系列键值对(Key, Value)上的映射函数。而Self Attention也即是Key=Value=Query。

接下来一步步拆解:

1. 键值对注意力

我们先抛开Q、K、V三个矩阵不谈,Self-Attention最原始的形态其实长这样(X是一个矩阵):
S o f t m a x ( X X T ) X Softmax(XX^T)X Softmax(XXT)X

  1. 第一步,看其中的 X X T XX^T XXT,一个矩阵乘以它自己的转置。img

    矩阵 X X T XX^T XXT是一个方阵,我们以行向量的角度理解,里面保存了每个向量与自己和其他向量进行内积运算的结果。向量的内积表征两个向量的夹角,表征一个向量在另一个向量上的投影。投影的值大,说明两个向量相关度高。

  2. 第二步,进行Softmax运算。

    preview

    Softmax操作的意义就是进行归一化。Softmax之后,这些数字的和为1了。

    Attention机制的核心就是加权求和,权重的来源就是这些归一化之后的数据。

  3. 最后,和矩阵 X X X再次相乘。

    preview

    S o f t m a x ( X X T ) Softmax(XX^T) Softmax(XXT)的一个行向量与 X X X相乘,得到了一个与 X X X维度相同的行向量。在新的向量中,每一个维度的数值都是由三个词向量在这一维度的数值加权求和得来的,这个新的行向量就是"早"字词向量经过注意力机制加权求和之后的表示。

一张更形象的图是这样的,图中右半部分的颜色深浅,其实就是我们上图中黄色向量中数值的大小,意义就是单词之间的相关度。

preview

2. Q、K、V矩阵

Q、K、V三个矩阵并不是公式中最本质的内容,但他们究竟是什么,可以看下图:

preview

其实,Q、K、V三个矩阵的来源是 X X X与权重矩阵 W W W的乘积,本质都是 X X X的线性变换。加入权重矩阵的原因是为了提高模型的拟合能力,权重矩阵 W W W是可以随网络一起训练而优化的。

3. 尺度标度 d k \sqrt d_k d k

我们可以看到 A t t e n t i o n ( Q , K , V ) = s o f t m a x ( Q K T d k ) V Attention(Q,K,V)=softmax(\frac{QK^T}{\sqrt d_k})V Attention(Q,K,V)=softmax(d kQKT)V,最终的公式中 Q K T QK^T QKT还会多除了一个 d k \sqrt d_k d k d k d_k dk是一个key vectors( K K K向量)的维度。加入的原因在于:

假设 Q , K Q, K Q,K里的元素的均值为0,方差为1,那么中 A T = Q T K A^T = Q^TK AT=QTK中元素的均值为0,方差为 d k d_k dk。当 d k d_k dk变得很大时, A A A中的元素的方差也会变得很大,如果 A A A中的元素方差很大,那么 S o f t m a x ( A ) Softmax(A) Softmax(A)的分布会趋于陡峭(分布的方差大,分布集中在绝对值大的区域)。

总结一下就是 S o f t m a x ( A ) Softmax(A) Softmax(A)的分布会和 d k d_k dk有关。因此 A A A中每一个元素除以 d k d_k dk后,方差又变为1。这使得 S o f t m a x ( A ) Softmax(A) Softmax(A)的分布“陡峭”程度与 d k d_k dk解耦,从而使得训练过程中梯度值保持稳定。

6.4.2 计算过程

了解了核心的公式,我们可以对Self-Attention整个的计算过程做一个了解(来源:The Illustrated Transformer),一共6步:

1. 输入向量

计算Self-Attention的第一步是根据编码器,为每个输入的向量创建三个向量(在本例中为每个单词嵌入的词向量Embedding)。因此,对于每个单词,我们都有创建一个Query向量 Q Q Q、Key向量 K K K、Value向量 V V V

这3个向量是通过将词向量(Embedding)乘以训练过程中的三个权重矩阵( W Q 、 W K 、 W V W^Q、W^K、W^V WQWKWV)来生成的。这3个向量的维数小于Embedding向量,为64维(在本例中)。

img

注意:Embedding和Decoder输入/输出向量的维数都是512,这是Transformer的一种结构选择,可以使大部分的Multi-Head Attention计算恒定,维数不用更小。

2. 计算分数

计算Self-Attention的第二步是计算分数(相关性)。假设我们正在计算这个例子中第一个词“Thinking”的Self-Attention,我们需要根据输入句子的每个单词对这个词进行评分。分数决定了当我们在某个位置对单词进行编码时,将多少权重(注意力)放在输入句子的其他单词上。

分数的计算方法是将查询向量的点积与我们评分的相应单词的关键向量相乘( Q K T QK^T QKT)。因此,如果我们处理"Thinking"的自我关注,则第一个分数将是 q 1 q_1 q1 k 1 k_1 k1的点积、第二个分数是 q 1 q_1 q1 k 2 k_2 k2的点积。

img

3. 归一化

将第二步所得到的分数除以 d k \sqrt d_k d k(本例中为8= 6 4 \sqrt64 6 4),使其具有更稳定的梯度,然后通过softmax对分数进行标准化操作传递结果。

此时Softmax分数决定了每个单词在此位置(对于当前单词)的表达量。显然,此位置的单词(当前单词本身)将具有最高的softmax分数,但有时关注与当前单词相关的另一个单词很有用。

img

4. 乘值向量

第五步是将每个Value向量 V V V都乘以上一步计算得出的Softmax分数。

这一步的目的是保持我们想要关注的单词的值不变,并减小不相关的单词的权重(例如,将它们乘以0.001等小数字)。

image-20220423175648352

5. 汇总加权

第六步是汇总加权上一步与Softmax相乘后的Value向量。这就是对于当前单词(本例中为“Thinking”)产生的Self-Attention的输出。

img

6. 遍历循环

最后,Self Attention会把每一个输入的词向量都做一遍Attention,然后在网络中不断更新迭代参数。

也是因为,它跟每一个input vector都做attention,所以没有考虑到input sequence的顺序。更通俗来讲,每一个词向量都与其他词向量计算内积,得到的结果就丢失了我们原来文本的顺序信息,你打乱词向量的顺序,得到的结果仍然是相同的。

但是对于具有时序性的文本数据,使用这种Self-Attention结构会破坏时序性。Transformer论文中使用了position embedding来解决,但只是一个权宜之计。

6.4.3 三种类型

Transformer里面一共有三种Self-Attetnion,其介绍如下(后面有详细介绍):

img

6.4.4 作用与优势

  1. 相对于RNN:
  • RNN本身对于长距离的依赖关系有一定的捕捉能力,但由于序列模型是通过门控单元使得信息保持流动,并且选择性地传递信息。但这种方式在文本长度越来越长的条件下,捕捉依赖关系的能力越来越低,因为每一次递归都伴随着信息的损耗,所以有了Attention机制来增强对我们所关注的那部分依赖关系的捕捉。除此之外,序列模型也不能对层次结构的信息进行有效的表达。

    • 引入Self Attention后会更容易捕获句子中长距离的相互依赖的特征,在计算过程中会直接将句子中任意两个单词的联系通过一个计算步骤直接联系起来,所以远距离依赖特征之间的距离被极大缩短,有利于有效地利用这些特征;

    • Self Attention不依赖序列运算,可以增加计算的并行性。

  1. 相对于CNN:
  • CNN在NLP领域也有比较广泛的应用。CNN模型可以被看作n-gram的detector,n-gram的n对应CNN卷积核的大小。CNN基于的假设是局部信息存在相互依赖关系,而卷积核可以把这些依赖关系以类似于n-gram的形式提取出来。另外,CNN具备Hierachicial Receptive Filed,使得任意两个位置之间的长度距离是对数级别。
    • Self Attention中元素与元素之间的距离从CNN的logarithmic path length进一步缩短到constant path length;
    • 由CNN fixed size perceptive变成了variable-sized的 perceptive,具体的长度等于文本长度(长度可变),这也是self-attention相对于普通attention的优点。
  1. 相对于Seq2Seq Attention:
  • 如果普通attention机制在一个窗口下计算attention score,那么这种attention机制的感受野就只有窗口,而且随着窗口移动还需要计算多次。
    • Self Attention通过一步矩阵计算得到了文本序列中任意两个元素的相似度,而且是以整个文本作为观察范围的。

6.5 Transformer

Transformer架构最早是由谷歌在 2017 年的论文《Attention Is All You Need》中引入的,抛弃了以往深度学习任务里面使用到的CNN和RNN。它受欢迎的主要原因是其架构引入了并行化,Transformer 利用了强大的 TPU 和并行训练,从而减少了训练时间。此后在此基础上又出现了GPT、Bert等优秀模型,这些优秀模型都是在Transformer的基础上衍生出来的。

6.5.1 整体结构

这里先对Transformer的大体框架做一个介绍,具体的解释放在后面。

Transformer由6个Encoder和6个Decoder堆叠而成,其结构如下图(其中: N × N× N×表示有 6 个这样的结构):

img

1. Encoder层结构

首先,模型需要对输入的数据进行一个Embedding操作,也可以理解为类似w2c的操作,Embedding结束之后,输入到Encoder层。

每一个Encoder有两个子层:Multi-Head Self-Attention层和Position-Wise Feed-Forward Network全连接前馈神经网络层(即全连接层),子层之间使用残差(Redidual Connection)和LayerNorm连接,避免梯度消失和爆炸。其中,全连接层可以并行计算,得到的输出会输入到下一个Encoder层。

img

Add表示残差Residual Connection,是为了解决多层神经网络训练困难的问题,通过将前一层的信息无差的传递到下一层,可以有效的仅关注差异部分。是借鉴了CNN中ResNet模型的思想。

Norm表示Layer Normalization,通过对当层的激活值归一化,加速模型的训练过程,使其更快的收敛。

2. Decoder层结构

每个Decoder也同样具有和Encoder类似的层级结构,有一点例外的是在Masked Multi-Head Self-Attention层和Position-Wise Feed-Forward Network全连接层之间还有一个Encoder-Decoder Attention层(也称为Multi-Head Context-Attention),用于帮助Decoder在解码时专注于输入句子中对应的那个单词。

Masked操作:其作用就是防止在训练的时候使用未来的输出的单词。比如训练时, 第一个单词不能参考第二个单词的生成结果。Masking就会把这个信息变成0,用来保证预测位置i的信息只能基于i前面的输出。

3. Positional Encoding

Transformer中缺少一种解释输入序列中单词顺序的方法,它跟序列模型还不一样。为了处理这个问题,Transformer给Encoder层和Decoder层的输入添加了一个额外的向量Positional Encoding,保存单词在序列中的相对或绝对位置,维度和Embedding的维度一样。

这个向量采用了一种很独特的方法来让模型学习到这个值,这个向量能决定当前词的位置,或者说在一个句子中不同的词之间的距离。这个位置向量的计算方法有很多种,论文中选取了三角函数的方式,如下:
P E ( p o s , 2 i ) = s i n ( p o s 1000 0 2 i / d ) P E ( p o s , 2 i + 1 ) = c o s ( p o s 1000 0 2 i / d ) PE(pos,2i)=sin(\frac{pos}{10000^{2i/d}})\\ PE(pos,2i+1)=cos(\frac{pos}{10000^{2i/d}}) PE(pos,2i)=sin(100002i/dpos)PE(pos,2i+1)=cos(100002i/dpos)
其中 p o s pos pos是指当前词在句子中的位置, i i i是指向量中每个值的index, d d d表示 P E PE PE的维度 (与词 Embedding 一样)。可以看出,在偶数位置( 2 i 2i 2i),使用正弦编码 s i n sin sin;在奇数位置( 2 i + 1 2i+1 2i+1),使用余弦编码 c o s cos cos

最后把这个Positional Encoding与Embedding的值相加(加法),作为输入送到下一层。

在这里插入图片描述

如果假设词向量的维度为4,则一个Positional Encoding的真实示例可能是下面这样:

img

对于一个有8个词(Token Position为10),其词向量维度(Embedding Dimension)为64维的的句子,其外观可能如下图所示:

img

4. 计算流程

  • 第一步:获取输入句子的每一个单词的表示向量X,X由单词的Embedding和单词位置的Embedding相加得到;

  • 第二步:将得到的单词Embedding矩阵传入编码器 中,经过6个Encoder block后可以得到句子所有单词的编码信息矩阵 Z Z Z,(第一个Encoder的输入为句子单词的表示向量矩阵,后续Encoder的输入是前一个Encoder的输出,最后一个Encoder输出的矩阵就是编码信息矩阵 Z Z Z);

  • 第三步:将 Encoder 输出的编码信息矩阵 Z Z Z传递到解码器中,编码器依次会根据当前翻译过的 1~ i 个单词,翻译下一个单词 i+1。在使用的过程中,翻译到单词 i+1 的时候需要通过Mask (掩盖) 操作遮盖住 i+1 之后的单词;

  • 第四步:解码器接收了编码器的信息矩阵 Z Z Z,然后先传入一个翻译开始符 “< Begin >”,预测第一个单词 “I”,并输出;然后传入翻译开始符 “< Begin >” 和预测的第一个单词 “I”,预测下一个单词 “have”,并输出,以此类推。

总体的动态流程图如下:

在这里插入图片描述

6.5.2 细节信息

接下来按照Encoder层到Decoder层的顺序,对Transformer内部的部件一个个进行详细分析。

1. Multi-Head Attention多头注意力机制

Multi-Head Attention,也称为Multi-Head Seft-Attention。在Self Attention一节,我们已经知道Self-Attention是如何计算得到输出的了,而Multi-Head Self-Attention是由多个Self-Attention组合形成的。

下图是论文中Multi-Head Attention结构图( h h h即为Self-Attention的个数):

img

将输入矩阵 X X X分别传递到 h h h个不同的Self-Attention中,每一个Self-Attention都将有不同的Query/Key/Value权重矩阵(即不同的 W Q 、 W K 、 W V W^Q、W^K、W^V WQWKWV),由此计算得到 h h h个不同的输出矩阵 Z i ,   i = 1 , 2 , … , h Z_i,\ i = 1,2,…,h Zi, i=1,2,,h。原论文中 h = 8 h=8 h=8,即有8个Self-Attention。

img

但Self-Attention后面接的全连接层并不需要8个矩阵,而是只要1个矩阵(每个单词的向量)。因此,我们需要一种方法将这8个缩减到1个矩阵中。论文中采取的办法是将8个矩阵 Z i Z_i Zi相连接,然后乘以额外的权重矩阵 W O W^O WO

img

最后,整个Multi-Head Attention的计算过程可以通过一张图表示:

img

Multi-Head的使用,可以从两个方面提高Self-Attention的性能:

  • 它扩展了模型专注于不同位置的能力。在单个Self-Attention中, Z Z Z虽然包含了一点点其他编码的信息,但实际上可能还是由实际单词本身主导。如果我们翻译一个句子,比如“动物没有过马路,因为它太累了”,我们会想知道“它”指的是“动物”;

  • 它为Attention层提供了多个“表示子空间”(representation subspaces)。在训练之后,每一组Query/Key/Value的权重矩阵集合,都会将输入的词嵌入(或上一层编码器/解码器的向量)投影到不同的表示子空间中。

    可类比CNN中同时使用多个卷积核的作用,直观上讲,多头有助于网络捕捉到更丰富的特征/信息。

2. Add&Norm

在Transformer中,每个编码器中的每一个子层之后,都会有一个Add(residual connection,残差连接)和一个Norm(layer-normalization,层标准化)操作。表示如下:
L N ( X + F ( X ) ) LN(X+F(X)) LN(X+F(X))
其中的 F ( X ) F(X) F(X)可以是Multi-Head Attention的 X X X,也可以是Feed Forward的 X X X。在网络中图示如下:

img
  1. Residual Connection

残差(residual):在数理统计中是指实际观察值与估计值(拟合值)之间的差。

ResNet残差连接的简化示意如下:

在这里插入图片描述

残差连接简单说就是:计算几层输出( F ( X ) F(X) F(X))之后再把 X X X加进来,可以让网络只关注当前差异的部分,从而有效解决梯度消失和网络退化的问题,通常用于解决多层网络训练的问题。

  1. Layer Normalization

Norm指Normalization,通常用于RNN结构,其归一化数据的方法有很多种,但都有一个共同的目标:将每一层神经元的输入都转换成均值为0方差为1的数据,这样可以规范优化空间,加速收敛。然后再将数据输入激活函数(防止输入数据集中在激活函数的饱和区)。

  • Batch Normalization(BN):在每一层的每一批数据上进行归一化。

    • 当我们使用梯度下降算法做优化时,我们可能会对输入数据进行归一化,但是经过网络层作用后,我们的数据已经不是归一化的了。随着网络层数的增加,数据分布不断发生变化,偏差越来越大,导致我们不得不使用更小的学习率来稳定梯度,防止梯度消失或者梯度爆炸。
    • BN的具体做法就是对每一小批数据,在批这个方向上做归一化。
  • Layer normalization(LN):在每一个样本上计算均值和方差。
    L N ( X i ) = α X i − μ i σ 2 + ε + β LN(X_i) = α\frac{X_i−μ_i}{\sqrt{σ^2+ε}}+β LN(Xi)=ασ2+ε Xiμi+β

img

3. Feed Forward

Feed Forward层比较简单,就是一个2层的全连接层。第一层的激活函数为Relu,第二层不使用激活函数,对应的公式: F F N ( X ) = M a x ( 0 , X ⋅ W 1 + b 1 ) ⋅ W 2 + b 2 FFN(X) = Max(0, X·W_1 + b_1)·W_2 + b_2 FFN(X)=Max(0,XW1+b1)W2+b2

这个FFN的作用就是空间变换,FFN的加入引入了非线性(ReLu激活函数),变换了Attention Output的空间,从而增加了模型的表现能力(把FFN去掉模型也是可以用的,但是效果会差很多)。

4. Masked Mutil-Head Attetion

Decoder层的第一个Multi-Head Attention采用了Masked操作,因为在翻译的过程中是顺序翻译的,即翻译完第i个单词,才可以翻译第i+1个单词。通过Masked操作可以防止第i个单词知道i+1个单词之后的信息(将第i+1之后的单词掩盖住)。

Mask表示掩码,它对某些值进行掩盖,使其在参数更新时不产生效果。

Decoder在训练的过程中使用Teacher Forcing进行训练,即将正确的单词序列和对应输出传递到Decoder中。其步骤和Mutil-Head Attetion基本相同:

  • 第一步:输入Decoder的向量矩阵 X X XMask矩阵,通过输入矩阵 X X X计算得到 Q , K , V Q, K, V Q,K,V矩阵。然后计算 Q Q Q K T K^T KT的乘积 Q K T QK^T QKT

  • 第二步:在 Softmax之前需要使用Mask矩阵遮挡住每一个单词之后的信息,遮挡操作如下(黑色部分即为0):

在这里插入图片描述
  • 第三步:使用 M a s k   Q K T Mask\ QK^T Mask QKT与矩阵 V V V相乘,得到输出矩阵 Z i Z_i Zi。然后和Encoder类似,通过Mutil-Head拼接多个输出 Z i Z_i Zi然后计算得到第一个Multi-Head Attention的输出 Z Z Z

其实,Transformer模型里面涉及两种mask,分别是Padding Mask和Sequence Mask。其中,Padding Mask在所有的Scaled dot-product Attention里面都需要用到,而Sequence Mask只有在 Decoder的Self-Attention里面用到(Sequence Mask就是我们上面说的这种)。

  • Padding Mask:
    • 因为每个批次输入序列长度是不一样的也就是说,我们要对输入序列进行对齐。具体来说,就是给在较短的序列后面填充 0。但是如果输入的序列太长,则是截取左边的内容,把多余的直接舍弃。因为这些填充的位置,其实是没什么意义的,所以我们的attention机制不应该把注意力放在这些位置上,所以我们需要进行一些处理。
    • 具体的做法是,把这些位置的值加上一个非常大的负数(负无穷),这样的话,经过Softmax,这些位置的概率就会接近0。而我们的Padding Mask实际上是一个张量,每个值都是一个Boolean,值为 false 的地方就是我们要进行处理的地方。
  • Sequence Mask:
    • Sequence Mask是为了使得Decoder不能看见未来的信息。
    • 具体做法如上。即:产生一个上三角矩阵,上三角的值全为0。把这个矩阵作用在每一个序列上,就可以达到我们的目的。

5. Encoder-Decoder Attention

Encoder-Decoder Attention是Decoder中的第二个Multi-Head Attention,与Multi-Head Attention差别不大,其主要区别在于其中Self-Attention的 K , V K, V K,V矩阵不是使用上一个Decoder的输出计算的,而是使用Encoder的编码信息矩阵 Z Z Z计算的。

即,根据Encoder的输出 Z Z Z计算得到 K , V K, V K,V,根据上一个Decoder的输出计算 Q Q Q(如果是第一个Decoder则使用输入矩阵 X X X进行计算),后续的计算方法与之前描述的一致。这样做的好处是在 Decoder 的时候,每一位单词都可以利用到Encoder所有单词的信息(这些信息无需Masked)。

6. Linear & Softmax

Output层:当Decoder层全部执行完毕后,最后会输出一个实数向量,只需要在结尾再添加一个全连接层和softmax层,就可以把得到的向量映射为我们需要的词。

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

假如我们的词典是1w个词,那么通过全连接层把输出的词向量升维到1w维(称为logits向量),再通过softmax将其转为概率,概率值最大的对应的词就是我们最终的结果(One Hot)。

在这里插入图片描述

6.5.3 总结

到此,Transformer的内容也就介绍完了,最后再回顾一下Transformer的结构如下:

在这里插入图片描述

优点

  • 虽然Transformer最终也没有逃脱传统学习的套路,Transformer也只是一个全连接(或者是一维卷积)加Attention的结合体。但是其设计已经足够有创新,因为其抛弃了在NLP中最根本的RNN或者CNN并且取得了非常不错的效果,算法的设计非常精彩,值得每个深度学习的相关人员仔细研究和品位;
  • Transformer的设计最大的带来性能提升的关键是将任意两个单词的距离是1,这对解决NLP中棘手的长期依赖问题是非常有效的;
  • Transformer不仅仅可以应用在NLP的机器翻译领域,甚至可以不局限于NLP领域,是非常有科研潜力的一个方向;
  • 算法的并行性非常好,符合目前的硬件(主要指GPU)环境。

缺点

  • 粗暴的抛弃RNN和CNN虽然非常炫技,但是它也使模型丧失了捕捉局部特征的能力,RNN + CNN + Transformer的结合可能会带来更好的效果;
  • Transformer失去的位置信息其实在NLP中非常重要,而论文中在特征向量中加入Position Embedding也只是一个权宜之计,并没有改变Transformer结构上的固有缺陷。

其他

实际特定任务下可以通过对Transformer里面的模块做相应的调整,从而使得模型可以适应多种特定的任务。有若干种在Transformer基础上引进额外Embedding的模型、改造Attention机制的模型、扩展Transformer的模型,来完成特定任务的适配,具体内容可见:transformer结构扩展(一)transformer结构扩展(二)transformer结构扩展(三)

6.6 Transformer-XL

CMU联合Google Brain在2019年1月推出的一篇新论文《Transformer-XL:Attentive Language Models beyond a Fixed-Length Context》同时结合了RNN序列建模和Transformer自注意力机制的优点,在输入数据的每个段上使用Transformer的注意力模块,并使用循环机制来学习连续段之间的依赖关系。

具体介绍可见:Transformer-XL解读

猜你喜欢

转载自blog.csdn.net/Morganfs/article/details/124373914