【学习笔记】Transformer详解

参考链接:【手撕Transformer】Transformer输入输出细节以及代码实现(pytorch),Transformer模型详解(图解最完整版)

模型结构

1、结构图如下。

【学习笔记】Transformer详解_第1张图片
上图是论文中 Transformer 的内部结构图,左侧为 Encoder block,右侧为 Decoder block。可以看到 Encoder block 包含一个 Multi-Head Attention,而 Decoder block 包含两个 Multi-Head Attention (其中有一个用到 Masked)。Multi-Head Attention 上方还包括一个 Add & Norm 层,Add 表示残差连接 (Residual Connection) 用于防止网络退化,Norm 表示 Layer Normalization,用于对每一层的激活值进行归一化。

2、名词解释

Input Embedding: 可以理解为将输入的数据转化为特定的向量。本文中是将输入数据转化为512纬的向量。
Positional Encoding: 因为Attention机制关注全局信息,所以需要用一个位置向量来记住单词的位置。这个位置向量可以通过公式或者算法获得,文中采用的是公式。
【学习笔记】Transformer详解_第2张图片
Self-Attention: 顾名思义就是自己和自己计算的注意力机制。输入的数据通过这个模块可以得到三个不同的矩阵Q,K,V。然后对这三个矩阵进行运算输出一个包含输入单词信息的矩阵Z。

Multi-Head Attention: 多头自注意力就是多个自注意力机制,文章中是8个自注意力。
Add & Norm: Add 表示残差连接 (Residual Connection) 用于防止网络退化,Norm 表示 Layer Normalization,用于对每一层的激活值进行归一化。
①Add指X+MultiHeadAttention(X),是一种残差连接,即每一个前馈神经网络的输入不光包含上述self-attention的输出Z,还包含最原始的输入。通常用于解决多层网络训练的问题,可以让网络只关注当前差异的部分,在 ResNet 中经常用到。

【学习笔记】Transformer详解_第3张图片
Norm指 Layer Normalization,通常用于 RNN 结构,Layer Normalization 会将每一层神经元的输入都转成均值方差都一样的,这样可以加快收敛。
Feed Forward: Feed Forward 层比较简单,是一个两层的全连接层,第一层的激活函数为 Relu,第二层不使用激活函数,对应的公式如下。
【学习笔记】Transformer详解_第4张图片
X是输入,Feed Forward 最终得到的输出矩阵的维度与 X 一致。
Masked Multi-Head Attention: 即多个自注意力,论文中采用的是8个。
多头注意力机制:
他扩展了模型关注不同位置的能力,这对翻译一下句子特别有用,因为我们想知道“it”是指代的哪个单词。
第二个方面,他给了自注意力层多个“表示子空间”。对于多头自注意力机制,我们不止有一组Q/K/V权重矩阵,而是有多组(论文中使用8组),所以每个编码器/解码器使用8个“头”(可以理解为8个互不干扰自的注意力机制运算),每一组的Q/K/V都不相同。然后,得到8个不同的权重矩阵Z,每个权重矩阵被用来将输入向量投射到不同的表示子空间。
Linear layer:
- 目的:将由解码器堆栈产生的向量投影到一个更大的向量中,称为对数向量。这个向量对应着模型的输出词汇表;向量中的每个值,对应着词汇表中每个单词的得分;
softmax层:
- 操作:这些分数转换为概率(所有正数,都加起来为1.0)。选择具有最高概率的单元,并且将与其相关联的单词作为该时间步的输出

Attention 机制 是对 source 中各个元素 的 value 进行加权求和,而 query 和 key 用于计算 对应 value 的权值系数

  • attention 的核心 就是从 大量信息中 筛选出少量的 重要信息;
    • 具体操作:每个 value 的 权值系数,代表 其 重要度;
      缺点:忽略了 源端或目标端 词与词间 的依赖关系

self-attention的结构在计算每个token时,总是会考虑整个序列其他token的表达;学习句子内部的词依赖关系,捕获句子的内部结构。

  • 优点

    • 捕获源端和目标端词与词间的依赖关系

    • 捕获源端或目标端自身词与词间的依赖关系

  • self-attention 是如何解决长距离依赖问题的呢?

    • 解决方式:

      • 利用注意力机制来“动态”地生成不同连接的权重,从而处理变长的信息序列

工作流程

数据从输入到encoder到decoder输出这个过程中的流程(以机器翻译为例子):

1、获取Transformer的输入

对于机器翻译来说,一个样本是由原始句子和翻译后的句子组成的。比如原始句子是: “我爱机器学习”,那么翻译后是 ’i love machine learning‘。 则该一个样本就是由“我爱机器学习”和 “i love machine learning” 组成。

这个样本的原始句子的单词长度是length=4,即‘我’ ‘爱’ ‘机器’ ‘学习’。经过embedding后每个词的embedding向量是512。那么“我爱机器学习”这个句子的embedding后的维度是[4,512 ] (若是批量输入,则embedding后的维度是[batch, 4, 512])。

Transformer的输入是句子中每一个单词的表示向量X,X由单词的 Embedding 和单词位置的 Embedding 相加得到。
【学习笔记】Transformer详解_第5张图片

单词Embedding

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

位置Embedding

因为 Transformer 不采用 RNN 的结构,而是使用全局信息,不能利用单词的顺序信息,所以 Transformer 中使用位置 Embedding 保存单词在序列中的相对或绝对位置。
位置 Embedding 用 PE表示,PE 的维度与单词 Embedding 是一样的。PE 可以通过训练得到,也可以使用某种公式计算得到。在 Transformer 中采用了后者,计算公式如下:
【学习笔记】Transformer详解_第6张图片
其中,pos 表示单词在句子中的位置,d 表示 PE的维度 (与词 Embedding 一样),2i 表示偶数的维度,2i+1 表示奇数维度 (即 2i≤d, 2i+1≤d)。使用这种公式计算 PE 有以下的好处:

  • 使 PE 能够适应比训练集里面所有句子更长的句子,假设训练集里面最长的句子是有 20 个单词,突然来了一个长度为 21 的句子,则使用公式计算的方法可以计算出第 21 位的 Embedding。
  • 可以让模型容易地计算出相对位置,对于固定长度的间距 k,PE(pos+k) 可以用 PE(pos) 计算得到。因为 Sin(A+B) = Sin(A)Cos(B) + Cos(A)Sin(B), Cos(A+B) = Cos(A)Cos(B) - Sin(A)Sin(B)。

padding

假设样本中句子的最大长度是10,那么对于长度不足10的句子,需要补足到10个长度,shape就变为[10, 512], 补全的位置上的embedding数值自然就是0了

Padding Mask

对于输入序列一般要进行padding补齐,也就是说设定一个统一长度N,在较短的序列后面填充0到长度为N。对于那些补零的数据来说,attention机制不应该把注意力放在这些位置上,所以需要进行一些处理。具体的做法是,把这些位置的值加上一个非常大的负数(负无穷),这样经过softmax后,这些位置的权重就会接近0。Transformer的padding mask实际上是一个张量,每个值都是一个Boolean,值为false的地方就是要进行处理的地方。

2、Encoder过程

Self-Attention的作用

解决长距离依赖问题

  • 长距离依赖:对于序列问题,第 t 时刻的输出 y t y_t yt 依赖于 t 之前的输入,也就是说依赖于 x t − k , k = 1 , 2 , . . . t x_{t-k},k=1,2,...t xtk,k=1,2,...t ,当间隔 k 逐渐增大时, x t − k x_{t-k} xtk 的信息将难以被 y t y_t yt 所学习到,也就是说,很难建立这种长距离依赖关系,这个也就是长距离依赖问题(Long-Term Dependencies Problem)。
  • 对于当前query,你需要与句子中 所有 key 进行点乘后再 Softmax ,以获得句子中所有 key对于当前query的 score(可以理解为贡献度),然后与所有词的value向量进行加权融合之后,就能使当前 y t y_t yt 学习到句子中其他词的信息;
  • 因为有Position Encoding(PE)和Q,K,V。所以Self-Attention可以实现长距离依赖,关注上下文信息。Q,K,V可以计算其他单词与本单词之间的联系,PE可以记住单词的位置。

Self-Attention结构

【学习笔记】Transformer详解_第7张图片
上图是 Self-Attention 的结构,在计算的时候需要用到矩阵 Q(查询), K(键值), V(值)。在实际中,Self-Attention 接收的是单词的表示向量X(第一个Encoder) 或者上一个 Encoder block 的输出的矩阵Z。而 Q, K, V 正是通过 Self-Attention 的输入X进行线性变换得到的。计算如下图:
【学习笔记】Transformer详解_第8张图片

Attention与Self-Attention的区别

  • 具体计算过程是一样的,都是先计算Q与K的点积,获取关系系数,然后再与V相乘。
  • 计算对象不同,attention是source对target的attention,而self attention 是source 对source的attention。Attention机制发生在Target和Source中的所有元素之间。
  • attention告诉的是每个部分的重要程度,self-attention告诉的是各个部分的关联关系!
  • 举例:比如entity1,entity2,entity3….,attn会输出[0.1,0.2,0.5,….]这种,Attention告诉你entity3重要些。self attention会给你一个矩阵,告诉你 entity1 和entity2、entity3 ….的关联程度、entity2和entity1、entity3…的关联程度。
  • Attention是两个系统的,Self-Attention是一个系统内部的。

Q、K、V是干嘛的?

Q即Query,K即Key,V即Value。

  • query和key用于计算对应value 的权值系数。查询向量query点乘key得到score: 计算其他词对这个词的重要性,也就是权值;
  • 权值score和各个上下文中的V向量的加权求和
  • 把上下文各个字的V融入目标字的原始 V 中
  • 文章中的Q,K,V,这三个向量都可以表示"我"这个词,但每个向量的作用并不一样,Q 代表 query,当计算"我"这个词时,它就能代表"我"去和其他词的 K 进行点乘计算其他词对这个词的重要性,当计算完点乘后,我们只是得到了每个词对“我”这个词的权重,需要再乘以一个其他词的向量,也就是V(value),才完成"我"这个词的计算,同时也是完成了用其他词来表征"我"的一个过程。

Q、K、V的计算

Self-Attention 的输入用矩阵 X进行表示,则可以使用线性变阵矩阵 WQ, WK, WV 计算得到 Q, K, V。计算如下图所示,注意 X, Q, K, V 的每一行都表示一个单词
【学习笔记】Transformer详解_第9张图片

Self-Attention的输出

得到矩阵 Q, K, V之后就可以计算出 Self-Attention 的输出了,计算的公式如下。
【学习笔记】Transformer详解_第10张图片
公式中计算矩阵 Q和 K 每一行向量的内积,为了防止内积过大,因此除以 dk 的平方根。还起到调节作用,使得内积不至于太大。实际上是Q,K,V的最后一个维度,当 d k d_k dk 越大,Q与K的转置 就越大,可能会将 Softmax 函数推入梯度极小的区域;
Q 乘以 K 的转置后,得到的矩阵行列数都为 n,n 为句子单词数,这个矩阵可以表示单词之间的 attention 强度。下图为 Q 乘以 K 的转置,1234 表示的是句子中的单词。
【学习笔记】Transformer详解_第11张图片
得到 QKT 之后,使用 Softmax 计算每一个单词对于其他单词的 attention 系数(这里可以根据矩阵乘法理解,对应行乘对应列,即每个单词相乘)。 公式中的 Softmax 是对矩阵的每一行进行 Softmax,即每一行的和都变为 1。
【学习笔记】Transformer详解_第12张图片
得到 Softmax 矩阵之后可以和 V相乘,得到最终的输出 Z。
【学习笔记】Transformer详解_第13张图片
上图中 Softmax 矩阵的第 1 行表示单词 1 与其他所有单词的 attention 系数,最终单词 1 的输出 Z1 等于所有单词 i 的值 Vi 根据 attention 系数的比例加在一起得到,如下图所示:
【学习笔记】Transformer详解_第14张图片
注意上图中不再是矩阵的乘法,这一步是经过softmax归一化之后,将V向量乘上softmax的结果,这个思想主要是为了保持我们想要关注的单词的值不变,而掩盖掉那些不相关的单词(例如将他们乘上很小的数字)

Multi-Head Attention

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

组成 Encoder

通过上面描述的 Multi-Head Attention, Feed Forward, Add & Norm 就可以构造出一个 Encoder block,Encoder block 接收输入矩阵 X(n×d),并输出一个矩阵 C(n×d),其中n是单词个数,d是向量维度。通过多个 Encoder block 叠加就可以组成 Encoders。

第一个 Encoder block 的输入为句子单词的表示向量矩阵,后续 Encoder block 的输入是前一个 Encoder block 的输出,最后一个 Encoder block 输出的矩阵就是 编码信息矩阵 C,这一矩阵后续会用到 Decoder 中。
【学习笔记】Transformer详解_第18张图片
encoder输入输出
从输入开始,再从头理一遍单个encoder这个过程:

  1. 输入x
  2. x 做一个层归一化: x1 = norm(x)
  3. 进入多头self-attention: x2 = self_attention(x1)
  4. 残差加成:x3 = x + x2
  5. 再做个层归一化:x4 = norm(x3)
  6. 经过前馈网络: x5 = feed_forward(x4)
  7. 残差加成: x6 = x3 + x5
  8. 输出x6

3、Decoder过程

Sequence Mask

具体的例子如下:

样本:“我/爱/机器/学习”和 “i/ love /machine/ learning”
训练:

  1. 把“我/爱/机器/学习”embedding后输入到encoder里去,最后一层的encoder最终输出的outputs [10, 512](假设我们采用的embedding长度为512,而且batch size = 1),此outputs 乘以新的参数矩阵,可以作为decoder里每一层用到的K和V;
  2. 将作为decoder的初始输入,将decoder的最大概率输出词 A1和‘i’做cross entropy计算error。
  3. 将,“i” 作为decoder的输入,将decoder的最大概率输出词 A2 和‘love’做cross entropy计算error。
  4. 将,“i”,“love” 作为decoder的输入,将decoder的最大概率输出词A3和’machine’ 做cross entropy计算error。
  5. 将,“i”,"love ",“machine” 作为decoder的输入,将decoder最大概率输出词A4和‘learning’做cross entropy计算error。
  6. 将,“i”,"love ",“machine”,“learning” 作为decoder的输入,将decoder最大概率输出词A5和终止符做cross entropy计算error。

上述训练过程是挨个单词串行进行的,那么能不能并行进行呢, 当然可以。可以看到上述单个句子训练时候,输入到 decoder的分别是

,“i”

,“i”,“love”

,“i”,"love ",“machine”

,“i”,"love ",“machine”,“learning”

那么为何不将这些输入组成矩阵,进行输入呢?这些输入组成矩阵形式如下:

,“i”

,“i”,“love”

,“i”,"love ",“machine”

,“i”,"love ",“machine”,“learning” 】

怎么操作得到这个矩阵呢?

将decoder在上述2-6步次的输入补全为一个完整的句子

,“i”,"love ",“machine”,“learning”
,“i”,"love ",“machine”,“learning”
,“i”,"love ",“machine”,“learning”
,“i”,"love ",“machine”,“learning”
,“i”,"love ",“machine”,“learning”】

然后将上述矩阵矩阵乘以一个 mask矩阵

【1 0 0 0 0

1 1 0 0 0

1 1 1 0 0

1 1 1 1 0

1 1 1 1 1 】

这样是不是就得到了

,“i”

,“i”,“love”

,“i”,"love ",“machine”

,“i”,"love ",“machine”,“learning” 】

这样将这个矩阵输入到decoder(其实你可以想一下,此时这个矩阵是不是类似于批处理,矩阵的每行是一个样本,只是每行的样本长度不一样,每行输入后最终得到一个输出概率分布,作为矩阵输入的话一下可以得到5个输出概率分布)。
这样就可以进行并行计算进行训练了。

第一个 Multi-Head Attention

Decoder block 的第一个 Multi-Head Attention 采用了 Sequence Masked 操作,因为在翻译的过程中是顺序翻译的,即翻译完第 i 个单词,才可以翻译第 i+1 个单词。通过 Masked 操作可以防止第 i 个单词知道 i+1 个单词之后的信息。 下面以 “我有一只猫” 翻译成 “I have a cat” 为例,了解一下 Masked 操作。

在 Decoder 的时候,是需要根据之前的翻译,求解当前最有可能的翻译,如下图所示。首先根据输入 “” 预测出第一个单词为 “I”,然后根据输入 “ I” 预测下一个单词 “have”。
【学习笔记】Transformer详解_第19张图片
Decoder 可以在训练的过程中使用 Teacher Forcing 并且并行化训练,即将正确的单词序列 ( I have a cat) 和对应输出 (I have a cat ) 传递到 Decoder。那么在预测第 i 个输出时,就要将第 i+1 之后的单词掩盖住,注意 Mask 操作是在 Self-Attention 的 Softmax 之前使用的,下面用 0 1 2 3 4 5 分别表示 “ I have a cat ”。
第一步: 是 Decoder 的输入矩阵和 Mask 矩阵,输入矩阵包含 “ I have a cat” (0, 1, 2, 3, 4) 五个单词的表示向量,Mask 是一个 5×5 的矩阵。在 Mask 可以发现单词 0 只能使用单词 0 的信息,而单词 1 可以使用单词 0, 1 的信息,即只能使用之前的信息。
【学习笔记】Transformer详解_第20张图片
第二步: 接下来的操作和之前的 Self-Attention 一样,通过输入矩阵 X计算得到 Q, K, V 矩阵。然后计算 Q 和 KT 的乘积 QKT。
【学习笔记】Transformer详解_第21张图片
第三步: 在得到 QKT 之后需要进行 Softmax,计算 attention score,我们在 Softmax 之前 需要使用 Mask矩阵遮挡住每一个单词之后的信息,遮挡操作如下:
【学习笔记】Transformer详解_第22张图片
得到 Mask QKT 之后在 Mask QKT 上进行 Softmax,每一行的和都为 1。

第四步: 使用 Mask QKT 与矩阵 V相乘,得到输出 Z,则单词 1 的输出向量 Z1 是只包含单词 1 信息的。被mask掉的部分不包含信息。
【学习笔记】Transformer详解_第23张图片
第五步: 通过上述步骤就可以得到一个 Mask Self-Attention 的输出矩阵 Zi,然后和 Encoder 类似,通过 Multi-Head Attention 拼接多个输出 Zi 然后计算得到第一个 Multi-Head Attention 的输出 Z,Z与输入 X 维度一样。

第二个 Multi-Head Attention

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

根据 Encoder 的输出 C计算得到 K, V,根据上一个 Decoder block 的输出 Z 计算 Q (如果是第一个 Decoder block 则使用输入矩阵 X 进行计算),后续的计算方法与之前描述的一致。

这样做的好处是在 Decoder 的时候,每一位单词都可以利用到 Encoder 所有单词的信息 (这些信息无需 Mask)。

Softmax 预测输出单词

Decoder block 最后的部分是利用 Softmax 预测下一个单词,在之前的网络层我们可以得到一个最终的输出 Z,因为 Mask 的存在,使得单词 0 的输出 Z0 只包含单词 0 的信息,如下。
【学习笔记】Transformer详解_第24张图片
Softmax 根据输出矩阵的每一行预测下一个单词
【学习笔记】Transformer详解_第25张图片
这就是 Decoder block 的定义,与 Encoder 一样,Decoder 是由多个 Decoder block 组合而成。

4、优势

  1. self-attention + position embedding(PE)解决长依赖问题,PE提供单词的位置信息,self-attention提供单词之间的依赖关系信息。
  2. 可以并行运行。
    • encoder的并行:单词之间不存串行的依赖关系,Multi-Head Attention通过拼接可以同时计算多个单词。
    • decoder的并行:单词之间存在串行的依赖关系,利用sequence masked矩阵mask后面的单词实现并行计算。
  3. 可以获取全局信息\上下文信息。原因跟解决长依赖问题一样,基于self-attention + position embedding。

你可能感兴趣的:(深度学习,学习,transformer,深度学习)