🧸Transformer模型详解
2022-9-26
| 2024-9-11
0  |  阅读时长 0 分钟
type
status
password
date
slug
summary
category
URL
tags
icon
建议大家看一下李宏毅老师讲解的Transformer,非常简单易懂(个人觉得史上最强transformer讲解):

前言

Transformer由论文《Attention is All You Need》提出,现在是谷歌云TPU推荐的参考模型。论文相关的Tensorflow的代码可以从GitHub获取,其作为Tensor2Tensor包的一部分。哈佛的NLP团队也实现了一个基于PyTorch的版本,并注释该论文。

一、Transformer 整体结构

首先介绍 Transformer 的整体结构,右图是 Transformer 用于中英文翻译的整体结构,可以看到 Transformer 由 Encoder 和 Decoder 两个部分组成,Encoder 和 Decoder 都包含 6 个 block。Transformer 的工作流程大体如下:
  1. Transformer输入
  1. Transformer的Encoder
  1. Transformer的Decoder
 
第一步:Transformer 的输入表示
第一步:Transformer 的输入表示
第一步:如上图(Transformer 的输入表示)所示,获取输入句子的每一个单词的表示向量 XX由单词的 Embedding(Embedding就是从原始数据提取出来的Feature) 和单词位置的 Embedding 相加得到。
 
第三步:Transofrmer Decoder 预测
第三步:Transofrmer Decoder 预测
第三步将 Encoder 输出的编码信息矩阵 C 传递到 Decoder 中,Decoder 依次会根据当前翻译过的单词 1 ~ i 翻译下一个单词 i+1,如下图所示。在使用的过程中,翻译到单词 i+1 的时候需要通过 Mask (掩盖) 操作遮盖住 i+1 之后的单词。
Transformer 的整体结构,左图Encoder和右图Decoder
Transformer 的整体结构,左图Encoder和右图Decoder
第二步:Transformer Encoder 编码句子信息
第二步:Transformer Encoder 编码句子信息
 
第二步:如上图(Transformer Encoder 编码句子信息)所示将得到的单词表示向量矩阵 (左图,每一行是一个单词的表示 x) 传入Encoder 中,经过 6 个 Encoder block 后可以得到句子所有单词的编码信息矩阵 C。单词向量矩阵用 表示, n 是句子中单词个数,d 是表示向量的维度 (论文中 d=512)。每一个 Encoder block 输出的矩阵维度与输入完全一致
上图 Decoder 接收了 Encoder 的编码矩阵 C,然后首先输入一个翻译开始符 "<Begin>",预测第一个单词 "I";然后输入翻译开始符 "<Begin>" 和单词 "I",预测单词 "have",以此类推。这是 Transformer 使用时候的大致流程,接下来是里面各个部分的细节。

二、Transformer 的输入

Transformer 中单词的输入表示 x单词 Embedding位置 Embedding (Positional Encoding)相加得到。
Transformer 的输入表示
Transformer 的输入表示

2.1 单词 Embedding

单词的 Embedding 有很多种方式可以获取,例如可以采用 Word2Vec、Glove 等算法预训练得到,也可以在 Transformer 中训练得到。

2.2 位置 Embedding

Transformer 中除了单词的 Embedding,还需要使用位置 Embedding 表示单词出现在句子中的位置。因为 Transformer 不采用 RNN 的结构,而是使用全局信息,不能利用单词的顺序信息,而这部分信息对于 NLP 来说非常重要。所以 Transformer 中使用位置 Embedding 保存单词在序列中的相对或绝对位置。

Transformer中位置信息的表示

位置 Embedding 用 PE表示,PE 的维度与单词 Embedding 是一样的。PE 可以通过训练得到,也可以使用某种公式计算得到。在 Transformer 中采用了后者,计算公式如下:
其中, 表示单词在句子中的位置, 表示 PE 的维度 (与词 Embedding 一样), 表示偶数的维度, 表示奇数维度 (即 , )。
使用这种公式计算 PE 有以下的好处:
越是前面的维度,它随位置的变化越快;越是后面的维度,它的变化就越慢。所以前面的维度能够区别很短的距离,而后面的维度只能能识别远距离的关系。
越是前面的维度,它随位置的变化越快;越是后面的维度,它的变化就越慢。所以前面的维度能够区别很短的距离,而后面的维度只能能识别远距离的关系。
  • 使 PE 能够适应比训练集里面所有句子更长的句子,假设训练集里面最长的句子是有 20 个单词,突然来了一个长度为 21 的句子,则使用公式计算的方法可以计算出第 21 位的Embedding。
  • 可以让模型容易地计算出相对位置,对于固定长度的间距 可以用 计算得到。因为
💡
将单词的词 Embedding 和位置 Embedding 相加,就可以得到单词的表示向量 xx 就Transformer 的输入。

2.3 Transformer输入的实现

  • 输入的维度是:(batch_size, num_steps, encoding_dim)
  • 位置嵌入向量:(1, num_steps, encoding_dim)
  • 输入维度+位置嵌入向量: (batch_size, num_steps, encoding_dim)

三、 Self-Attention(自注意力机制)

右图是论文中 Transformer 的内部结构图,左侧为 Encoder block,右侧为Decoder block。红色圈中的部分为Multi-Head Attention,是由多个Self-Attention组成的。Encoder block 包含一个 Multi-Head Attention,而 Decoder block 包含两个 Multi-Head Attention (其中有一个用到 Masked)。Multi-Head Attention 上方还包括一个 Add & Norm 层,Add 表示残差连接 (Residual Connection) 用于防止网络退化,Norm 表示 Layer Normalization,用于对每一层的激活值进行归一化。
因为 Self-Attention是 Transformer 的重点,所以我们重点关注 Multi-Head Attention 以及 Self-Attention,首先详细了解一下 Self-Attention 的内部逻辑。

3.1 Self-Attention 结构

右图是 Self-Attention 的结构,在计算的时候需要用到矩阵Q(查询),K(键值),V(值)。在实际中,Self-Attention 接收的是输入(单词的表示向量x组成的矩阵X) 或者上一个Encoder block 的输出。而Q,K,V正是通过 Self-Attention 的输入进行线性变换得到的。
Q, K, V 的计算(注意 X, Q, K, V 的每一行都表示一个单词,多行表示一个句子)
Q, K, V 的计算(注意 X, Q, K, V 的每一行都表示一个单词,多行表示一个句子)
Transformer Encoder 和 Decoder
Transformer Encoder 和 Decoder
Self-Attention 结构
Self-Attention 结构

3.2 Q, K, V 的计算

Self-Attention 的输入用矩阵X进行表示,则可以使用线性变阵矩阵WQ,WK,WV计算得到Q,K,V。计算如左图所示,注意 X, Q, K, V 的每一行都表示一个单词。多行表示一个句子

3.3 Self-Attention 的输出

得到矩阵 Q, K, V 之后就可以计算出 Self-Attention 的输出了,计算的公式如下,其中 是Q、K矩阵的列数,即向量维度:
💡
为什么需要位置编码
notion image
  • 计算相似度
    • 公式中计算矩阵 每一行向量的内积,为了防止内积过大,因此除以 的平方根。 乘以 的转置后,得到的矩阵行列数都为 为句子单词数,这个矩阵可以表示单词之间的 attention 强度。右图为 乘以
  • softmax归一化
    • 得到 之后,使用 Softmax 计算每一个单词对于其他单词的 attention 系数,公式中的 Softmax 是对矩阵的每一行进行 Softmax,即每一行的和都变为 1.(因为Q表示查询query、K表示key;所以对每一行,即每个query进行softmax)
Q乘以K的转置的计算。计算query与key之间attention强度
Q乘以K的转置的计算。计算query与key之间attention强度
归一化。对矩阵的每一行进行 Softmax。计算每个query与其他单词的相似度
归一化。对矩阵的每一行进行 Softmax。计算每个query与其他单词的相似度
得到 Softmax 矩阵之后可以和相乘,得到最终的输出
Self-Attention 输出。最左边的矩阵是每个query与其他单词的相似度;紫色是所有单词的value值;最右侧每一行代表每一个单词,列代表单词的隐藏层
Self-Attention 输出。最左边的矩阵是每个query与其他单词的相似度;紫色是所有单词的value值;最右侧每一行代表每一个单词,列代表单词的隐藏层
上图中 Softmax 矩阵的第 1 行表示单词 1 与其他所有单词的 attention 系数,最终单词 1 的输出 等于所有单词 的值 根据 attention 系数的比例加在一起得到,如下图所示:
 的计算方法。其中  表示单词 1 与其他所有单词的 attention 系数;紫色矩阵代表每个单词的新value;最终单词 1 的输出 等于所有单词  的值  根据 attention 系数的比例加在一起得到。
的计算方法。其中 表示单词 1 与其他所有单词的 attention 系数;紫色矩阵代表每个单词的新value;最终单词 1 的输出 等于所有单词 的值 根据 attention 系数的比例加在一起得到。

3.4 Self-Attention 的实现

notion image

3.4.1 masked_softmax

在Transformer里面,Encoder和Decoder的attention计算都需要相应的mask处理,但功能却不同。在Encoder中,mask主要是为了让那些在一个batch中长度较短的序列的padding不参与attention的计算,而在Decoder中,还要考虑不能发生数据泄露
💡
mask方法: 在得到 之后需要进行 Softmax,计算 attention score,我们在 Softmax 之前需要将任何超出有效长度的位置都被掩蔽并置为 。 因为, 所以Mask填充来遮蔽单词。
  • 测试:将最后一个维度的value进行置零

    3.4.2 self-attention 输出的实现

    下面代码实现了 self-attention的输出 部分内容,不包括 QKV的实现。具体实现部分的理论部分如下所示:
    • 测试:将句子中用不到的单词进行置零

      3.5 Multi-Head Attention

      在上一步,我们已经知道怎么通过 Self-Attention 计算得到输出矩阵 Z。而 Multi-Head Attention 是由多个 Self-Attention 组合形成的,下图是论文中 Multi-Head Attention 的结构图。
      Multi-Head Attention结构图
      Multi-Head Attention结构图
      从上图可以看到 Multi-Head Attention 包含多个 Self-Attention 层,首先将输入X分别传递到 h 个不同的 Self-Attention 中,计算得到 h 个输出矩阵Z。下图是 h=8 时候的情况,此时会得到 8 个输出矩阵Z
      多个 Self-Attention
      多个 Self-Attention
      得到 8 个输出矩阵 之后,Multi-Head Attention 将它们拼接(Concat)在一起 ,然后传入一个Linear层,得到 Multi-Head Attention 最终的输出Z
      可以看到 Multi-Head Attention 输出的矩阵Z与其输入的矩阵X的维度是一样的。

      3.6 Multi-Head Attention实现

      为了并行计算会将多头与batch拼接在一起。剩余其他维度进行相似度计算。Multi-Head Attention的并行化原理,如下图所示,最终输出shape与输入X的shape 相同。
      Multi-Head Attention的并行化原理
      Multi-Head Attention的并行化原理
      Multi-Head Attention 的输出
      Multi-Head Attention 的输出
      代码实现部分(李沐版并行化基本原理)
      代码实现部分(李沐版并行化基本原理)
      上图两种并行化原理基本相同。唯一的区别是最后一步中的线性变换部分,左图最后一步的线性变换矩阵的shape是(num_hiddens, num_of_QKV),输出结果的是(num_steps, num_of_QKV);右图最后输出的线性变换矩阵矩阵的shape是(num_hiddens, num_hiddens),输出结果是(num_steps, num_hiddens)

      3.6.1 转置函数

      • 测试

        3.6.2 Multi-Head Attention实现

        如果我们将查询、键和值的线性变换的输出数量设置为 , 则可以并行计算 个头。 在下面的实现中,是通过参数num_hiddens指定的。
        • 测试

          函数

          函数
          描述
          input must be 3-D tensors, ()  ()= ()

          四、Encoder 结构

          Transformer 的 Encoder block 结构是由 Multi-Head Attention, Add & Norm, Feed Forward, 组成的。刚刚已经了解了 Multi-Head Attention 的计算过程,现在了解一下 Add & Norm 和 Feed Forward 部分。

          4.1 Add & Norm

          Encond结构
          Encond结构
          Add & Norm 层由 Add 和 Norm 两部分组成,其计算公式如下:
          其中 X表示 Multi-Head Attention 或者 Feed Forward 的输入,MultiHeadAttention(X) 和 FeedForward(X) 分别表示表示 Multi-Head Attention 或者 Feed Forward 的输出 (输出与输入 X 维度是一样的,所以可以相加)。
          • AddX+MultiHeadAttention(X),是一种残差连接,通常用于解决多层网络训练的问题,可以让网络只关注当前差异的部分,在 ResNet 中经常用到,如右图所示
          残差连接
          残差连接
          • Norm指 Layer Normalization,通常用于 RNN 结构,Layer Normalization 会将每一句中的每个单词的隐藏向量进行标准化,这样可以加快收敛。
            • LN是针对单个训练样本进行,不依赖于其他数据进行标准化,在C,H,W上进行归一化,也就是与batch无关。在语言模型中输入是(batch_size, num_step,  num_hidden), LN会计算(num_step, num_hidden)的均值、方差进行标准化。计算得到的均值(batch_size),方差(batch_size),并对除了batch_size之外,所有维度进行归一化计算。
              LN是针对单个训练样本进行,不依赖于其他数据进行标准化,在C,H,W上进行归一化,也就是与batch无关。在语言模型中输入是(batch_size, num_step, num_hidden), LN会计算(num_step, num_hidden)的均值、方差进行标准化。计算得到的均值(batch_size),方差(batch_size),并对除了batch_size之外,所有维度进行归一化计算。
              💡
              在transformer中只对隐含层进行了归一化,详情可以参考训练部分的代码。避免同一个batch中不同句子的有效长度问题

          4.1.1 Add & Norm的实现

          • 测试

            4.2 Feed Forward

            Feed Forward 层比较简单,是一个两层的全连接层,第一层的激活函数为 Relu,第二层不使用激活函数,对应的公式如下。
            X是输入,Feed Forward 最终得到的输出矩阵的维度与X一致。

            4.2.1 Feed Forward的实现

            • 测试

              4.3 组成 Encoder

              通过上面描述的 Multi-Head Attention, Feed Forward, Add & Norm 就可以构造出一个 Encoder block,Encoder block 接收输入矩阵 ,并输出一个矩阵 。通过多个 Encoder block 叠加就可以组成 Encoder。
              第一个 Encoder block 的输入为句子单词的表示向量矩阵,后续 Encoder block 的输入是前一个 Encoder block 的输出,最后一个 Encoder block 输出的矩阵就是编码信息矩阵 C,这一矩阵后续会用到 Decoder 中。
              在 Transformer 里面,Encoder 和 Decoder 的Muti-Head Attention计算都需要相应的mask处理,但功能却不同。在Encoder中,mask主要是为了让那些在一个batch中长度较短的序列的padding不参与attention的计算。
              Encoder 编码句子信息
              Encoder 编码句子信息
              💡
              Encoder 的有一个Muti-Head Attention、Decoder有两个Muti-Head Attention

              4.3.1 Encoder Block实现

              • 测试

                4.3.2 Encoder 实现

                • 测试

                  五、Decoder 结构

                  右图红色部分为 Transformer 的 Decoder block 结构,与 Encoder block 相似,但是存在一些区别:
                  • 包含两个 Multi-Head Attention 层。
                  • 最后有一个 Softmax 层计算下一个翻译单词的概率。
                  Transformer Decoder block
                  Transformer Decoder block

                  5.1 DecoderBlock

                  5.1.1 第一个 Multi-Head Attention(使用decoder的有效长度)

                  Decoder block 的第一个 Multi-Head Attention 采用了 Masked 操作,因为在翻译的过程中是顺序翻译的,即翻译完第 个单词,才可以翻译第 个单词。通过 Masked 操作可以防止第 个单词知道 个单词之后的信息。
                  notion image
                  Decoder 部分使用了 Teacher Forcing。在 Decoder 的时候,是需要根据之前的翻译,求解当前最有可能的翻译,如上图所示。首先根据输入 "<Begin>" 预测出第一个单词为 "I",然后根据输入 "<Begin> I" 预测下一个单词 "have",那么在预测第 i 个输出时,就要将第 i+1 之后的单词掩盖住,注意 Mask 操作是在 Self-Attention 的 Softmax 之前使用的,mask的基本原理与self-attention中的 masked_softmax相同
                  💡
                  Encoder与Decoder中的mask相同。都是使用 masked_softmax函数 实现,Encoder、Decoder两者的区别如下所示:
                  • Encoder:为了让序列的pad不参与attention的计算,所以valid_lens是序列的有效长度(即句子长度)
                  • Decoder:为了预测第 i 个输出时,第 i+1 之后的单不参与attention的计算,所以valid_lens是序列中单词的位置(第一个单词是1、第二个单词是2. etc)
                  第一步:是 Decoder 的输入矩阵和 Mask 矩阵,输入矩阵包含 "<Begin> I have a cat" 五个单词的表示向量,Mask 是一个 5×5 的矩阵。在 Mask 可以发现单词 <Begin> 只能使用单词 <Begin> 的信息,而单词 I 可以使用单词 <Begin> I 的信息,即只能使用之前的信息。
                  第二步:接下来的操作和之前的 Self-Attention 一样,通过输入矩阵计算得到Q,K,V矩阵。然后计算 的乘积
                  第三步:在得到 之后需要进行 Softmax,计算 attention score,我们在 Softmax 之前需要使用Mask矩阵遮挡住每一个单词之后的信息,如右图所示。得到 Mask 之后在 Mask 上进行 Softmax,每一行的和都为 1。
                  注意: , 所以Mask填充来遮蔽单词。
                  第四步:使用 Mask 与矩阵 相乘,得到输出 Z,则单词 1 的输出向量 是只包含单词 1 信息的。
                  第五步:通过上述步骤就可以得到一个 Mask Self-Attention 的输出矩阵 ,然后和 Encoder 类似,通过 Multi-Head Attention 拼接多个输出 然后计算得到第一个 Multi-Head Attention 的输出ZZ与输入X维度一样。
                  第一步:输入矩阵与 Mask 矩阵. Mask矩阵实际上也是通过masked_softmax中的Valid_lens长度控制
                  第一步:输入矩阵与 Mask 矩阵. Mask矩阵实际上也是通过masked_softmax中的Valid_lens长度控制
                  第二步:Q乘以K的转置
                  第二步:Q乘以K的转置
                  第三步:Softmax 之前 Mask。, 所以Mask填充来遮蔽单词。例如单词 <Begin> 在单词 I have a cat 上的 attention score 都为 0。
                  第三步:Softmax 之前 Mask。, 所以Mask填充来遮蔽单词。例如单词 <Begin> 在单词 I have a cat 上的 attention score 都为 0。
                  Mask 之后的输出
                  Mask 之后的输出

                  5.1.2 第二个 Multi-Head Attention(使用encoder的有效长度)

                  Decoder block 第二个 Multi-Head Attention 变化不大, 主要的区别在于其中 Self-Attention 的 K, V矩阵不是使用 上一个 Decoder block 的输出计算的,而是使用 Encoder 的编码信息矩阵 C 计算的;Self-Attention的Q是根据根据上一个 Decoder block 的输出 Z 计算 Q。
                  💡
                  这样做的好处是在 Decoder 的时候,每一位单词都可以利用到 Encoder 所有单词的信息 (这些信息无需 Mask)。

                  5.1.3 实现

                  5.2 Decoder

                  如右图所示,与 Encoder 一样,Decoder 是由多个 Decoder block 组合而成。如下图所示,Decoder最后得到一个最终的输出 ,因为 Mask 的存在,使得单词 0 的输出 只包含单词 0 的信息;单词 4 的输出 包含单词 0、1、2、3、4 的信息,
                  notion image

                  5.3 Softmax 预测输出单词

                  Transformer 的整体结构,左图Encoder和右图Decoder
                  Transformer 的整体结构,左图Encoder和右图Decoder
                  如下图所示,Decoder block 最后的部分是利用 Softmax 预测下一个单词。最终的输出,首先进行线性变换,将隐藏层的维度扩展到vocab_size,并vocab_size维度,进行softmax函数计算,最终输出单词。
                  notion image

                  5.4 decoder实现

                  六、训练阶段

                  notion image

                  七、预测阶段

                  notion image

                  八、Transformer 总结

                  • Transformer 与 RNN 不同,可以比较好地并行训练。
                  • Transformer 本身是不能利用单词的顺序信息的,因此需要在输入中添加位置 Embedding,否则 Transformer 就是一个词袋模型了。
                  • Transformer 的重点是 Self-Attention 结构,其中用到的 Q, K, V矩阵通过输出进行线性变换得到。
                  • Transformer 中 Multi-Head Attention 中有多个 Self-Attention,可以捕获单词之间多种维度上的相关系数 attention score。

                  参考

                • NLP
                • Teacher forcing来自Transformers的双向编码器表示(BERT)
                  Loading...
                  目录