目录

  • 1、一切从Self-attention开始
  • 1.1 处理Sequence数据的模型
  • 1.2 Self-attention
  • 1.3 Multi-head Self-attention
  • 1.4 Positional Encoding
  • 2、Transformer讲解
  • 2.1 原理分析
  • 2.1.1 Encoder
  • 2.1.2 Decoder
  • Masked Self-Attention



Transformer 是 Google 的团队在 2017 年提出的一种 NLP 经典模型,现在比较火热的 Bert 也是基于 Transformer。Transformer 模型使用了

Self-Attention 机制,不采用 RNN 的顺序结构,使得模型可以

并行化训练 ,而且能够拥有

全局信息

1、一切从Self-attention开始

1.1 处理Sequence数据的模型

Transformer是一个Sequence to Sequence model,特别之处在于它大量用到了self-attention。

要处理一个Sequence,最常想到的就是使用RNN ,它的输入是一串vector sequence,输出是另一串vector sequence。

如果假设是一个single directional的RNN,那当输出b4时,默认a1,a2,a3,a4都已经看过了。如果假设是一个bi-directional的RNN,那当输出b任意时,默认a1,a2,a3,a4都已经看过了。RNN非常擅长于处理input是一个sequence的状况。

那RNN有什么样的问题呢?它的问题就在于:RNN很不容易并行化 (hard to parallel)。

为什么说RNN很不容易并行化呢?假设在single directional的RNN的情形下,你今天要算出 b4 ,就必须要先看a1 再看 a2再看 a3 再看 a4,所以这个过程很难平行处理。

那么这时就想到了使用CNN ,它可以实现并行计算,为什么呢?

CV 中,图片在卷积的过程中,下一层每张特征图的计算都与上一层所有或者部分特征图有关,并且下一层每张特征图的计算都是相互独立的,因此可以将每张特征图的计算认为是GPU中不同的线程核在跑,从而实现了并行,不需要等待。

但是必须要叠很多层filter,才可以看到长时的资讯。

因此,self-attention的出现了集成了上述二者的优点,既能解决长期依赖的问题同时可以实现并行计算。

RKNN Transformer模型_python

1.2 Self-attention

RKNN Transformer模型_yolo_02


如上图,x1-x4是输入序列,首先乘以W得到embedding,即a1-a4,接着这些embedding进入self-attention层,分别乘以三个不同的transformation matrix(Wq,Wk,Wv),得到q,k,v。

RKNN Transformer模型_RKNN Transformer模型_03


接下来使用每个query 去对每个key 做attention ,attention就是匹配这2个向量有多接近,比如我现在要对 q1和 k1 做attention,我就可以把这2个向量做scaled inner product ,得到 α11 。接下来你再拿 q1 和 k2 做attention,得到 α12。这里的 scaled inner product 就是:

RKNN Transformer模型_Self_04


式中, d 是 q 跟 k 的维度。因为 q x k 的数值会随着dimension的增大而增大,所以要除以 d开方 的值,相当于归一化的效果。接下来要做的事如图6所示,把计算得到的所有 α1i 值取 softmax 操作。

RKNN Transformer模型_深度学习_05


取完 softmax操作以后,我们将该结果和所有的 vi 值进行相乘,最后把结果通通加起来得到 b1 ,所以,在产生 b1 的过程中用了整个sequence的资讯 (Considering the whole sequence)。

RKNN Transformer模型_RKNN Transformer模型_06


同样的方法,也可以计算出b2,b3,b4。经过了以上一连串计算,self-attention layer做的事情跟RNN是一样的,只是它可以并行的得到layer输出的结果。现在我们要用矩阵表示上述的计算过程。

RKNN Transformer模型_深度学习_07


首先输入的embedding是 I=[a1,a2,a3,a4] ,然后用 I 乘以transformation matrix Wq 得到 Q=[q1, q2, q3, q4] ,它的每一列代表着一个vector q 。同理,得到k与v。

接下来是 q与 k 的attention过程,我们可以把vector k 横过来变成行向量,与列向量 q 做内积 。这样, α 就成为了 4x4 的矩阵,它由4个行向量拼成的矩阵和4个列向量拼成的矩阵做内积得到。

在得到 A 以后,如上文所述,要得到 b, 就要使用 A 分别与 v 相乘再求和得到,所以 A 要再左乘 v 矩阵。

RKNN Transformer模型_深度学习_08


RKNN Transformer模型_RKNN Transformer模型_09


RKNN Transformer模型_yolo_10

所以最后的公式如下:

RKNN Transformer模型_深度学习_11

1.3 Multi-head Self-attention

RKNN Transformer模型_yolo_12

RKNN Transformer模型_RKNN Transformer模型_13

RKNN Transformer模型_python_14


从下图14可以看到 Multi-Head Attention 包含多个 Self-Attention 层,首先将输入 X 分别传递到 2个不同的 Self-Attention 中,计算得到 2 个输出结果。得到2个输出矩阵之后,Multi-Head Attention 将它们拼接在一起 (Concat),然后传入一个Linear层,得到 Multi-Head Attention 最终的输出 Z。可以看到 Multi-Head Attention 输出的矩阵 [公式] 与其输入的矩阵 X 的维度是一样的。下面一组Multi-head Self-attention的结果,其中绿色部分是一组query和key,红色部分是另外一组query和key,可以发现绿色部分其实更关注global的信息,而红色部分其实更关注local的信息。

RKNN Transformer模型_深度学习_15


这里multihead是如何实现的呢?我们举一个例子,以[10, 32, 512](seq_len, batch_size, feature_dimension,在pytorch中计算nlp时,一般是这样的顺序,与cv中会有不同 )这样的输入为例,在计算q, k, v时,他们的Wq, Wk, Wv的维度是[512, 512], 这样得到q,k,v均为[10, 32, 512]维。 然后就是multi-head的部分了,transformer在计算时并没有将他们分开计算,仍然是矩阵的思想 ,比如说有12个head,那么会将q, k, v中的feature_dimension维进行划分,划分为12,这样就变成了[10, 32, 12, 64] ,也就是说每一个head的feature_dimension维度是64维 , 然后将其reshape为[10, 384,64] ,在最后计算结束后再reshape到原来维度。

因此,使用multihead的好处是:在不增加计算量的基础上,学习更多的特征,例如全局,局部等

1.4 Positional Encoding

以上是multi-head self-attention的原理,但是还有一个问题是:现在的self-attention中没有位置的信息,一个单词向量的“近在咫尺”位置的单词向量和“远在天涯”位置的单词向量效果是一样的,没有表示位置的信息(No position information in self attention)。所以你输入"A打了B"或者"B打了A"的效果其实是一样的,因为并没有考虑位置的信息。

RKNN Transformer模型_python_16


具体的做法是:给每一个位置规定一个表示位置信息的向量 ei,让它与 ai 加在一起之后作为新的 ai 参与后面的运算过程,但是这个向量 ei 是由人工设定的,而不是神经网络学习出来的。每一个位置都有一个不同的 ei 。

RKNN Transformer模型_深度学习_17

这个式子的好处是:
(1)每个位置有一个唯一的positional encoding。
(2)使 PE 能够适应比训练集里面所有句子更长的句子,假设训练集里面最长的句子是有 20 个单词,突然来了一个长度为 21 的句子,则使用公式计算的方法可以计算出第 21 位的 Embedding。
(3)可以让模型容易地计算出相对位置,对于固定长度的间距 k ,任意位置的 pos+k位置 都可以被 pos位置 的线性函数表示,利用三角函数的特性即可计算:cos(a+b) = cosa x cosb - sina x sinb。

2、Transformer讲解

2.1 原理分析

RKNN Transformer模型_深度学习_18

2.1.1 Encoder

上图是一个seq2seq的model,左侧为 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,用于对每一层的激活值进行归一化。比如说在Encoder Input处的输入是机器学习,在Decoder Input处的输入是,输出是machine。再下一个时刻在Decoder Input处的输入是machine,输出是learning。不断重复知道输出是句点(.)代表翻译结束。

对于左半部分的Encoder来说,输入X,通过multihead-attention以及layer norm以及FFN层后,得到的是表示该sequence特征的一个张量。所以:

RKNN Transformer模型_python_19

2.1.2 Decoder

Decoder的工作时利用Encoder生成的序列特征,解码后得到另一串序列。

这里要特别注意一下,编码可以并行计算,一次性全部Encoding出来,但解码不是一次把所有序列解出来的,而是像 RNN 一样一个一个解出来的,因为要用上一个位置的输入当作attention的query。

因此,Decoder的 输出 是:对应 i 位置的输出词的概率分布。

输入 是:Encoder的输出以及 i -1 位置Decoder的输出。这里Encoder输出的序列特征被用于Decoder第二层的 self-Attention 的 Query和Key

明确了解码过程之后最上面的图就很好懂了,这里主要的不同就是Decoder的第一层attention多加了一个mask,因为训练时的output都是Ground Truth,这样可以确保预测第 i 个位置时不会接触到未来的信息。

因此,Decoder的结构是:

  • 包含两个 Multi-Head Attention 层。
  • 第一个 Multi-Head Attention 层采用了 Masked 操作。
  • 第二个 Multi-Head Attention 层的Key,Value矩阵使用 Encoder 生成序列特征 进行计算,而Query使用上一个 Decoder block 的输出计算。
  • 最后有一个 Softmax 层计算下一个翻译单词的概率。
Masked Self-Attention

RKNN Transformer模型_yolo_20


因为在翻译的过程中是顺序翻译的,即翻译完第 i 个单词,才可以翻译第 i+1 个单词。通过 Masked 操作可以防止第 i 个单词知道第 i+1 个单词之后的信息。下面以 “我有一只猫” 翻译成 “I have a cat” 为例,了解一下 Masked 操作。在 Decoder 的时候,是需要根据之前的翻译,求解当前最有可能的翻译,如下图所示。首先根据输入 “” 预测出第一个单词为 “I”,然后根据输入 " I" 预测下一个单词 “have”。

Decoder 可以在训练的过程中使用 Teacher Forcing 并且并行化训练 ,即将正确的单词序列 ( I have a cat) 和对应输出 (I have a cat ) 传递到 Decoder。那么在预测第 i 个输出时,就要将第 i+1 之后的单词掩盖住。

注意,上面是训练的流程 ,与测试不同,测试是没有真值的,测试的流程如下:
1、输入,解码器输出 I 。
2、输入前面已经解码的和 I,解码器输出have。
3、输入已经解码的,I, have, a, cat,解码器输出解码结束标志位,每次解码都会利用前面已经解码输出的所有单词嵌入信息。

训练时

不采用上述类似RNN的方法一个一个目标单词嵌入向量顺序输入训练 ,想采用类似编码器中的矩阵并行算法一步就把所有目标单词预测出来 。要实现这个功能就可以参考编码器的操作,把目标单词嵌入向量组成矩阵一次输入即可。即:并行化训练。

但是在解码have时候,不能利用到后面单词a和cat的目标单词嵌入向量信息,否则这就是作弊(测试时候不可能能未卜先知)。

它训练的具体操作如下所示:

RKNN Transformer模型_yolo_21


其中,Mask矩阵是一个下三角矩阵,在Pytorch实现中,是以bool为基本类型的。

因此,第一个Self-Attention层的Query, Key,Value均来自于decoder的输入第二个Self-Attention层的Query来自于第一层的输出,Key和Value来自于Encoder的输出。

Decoder的最后是Softmax 预测输出单词。因为 Mask 的存在,使得单词 0 的输出只包含单词 0 的信息。Softmax 根据输出矩阵的每一行预测下一个单词,如下图27所示。

RKNN Transformer模型_RKNN Transformer模型_22

预测 时,由于没有真实值,因此decoder输出时,是一个单词一个单词进行预测的, 首先输入[BOS]生成I, 然后输入[BOS, I] 生成have,再输入[BOS, I, have]…, 直到生成EOS结束。 因此,Decoder的输入特征的维度分别是:[1,1, 512] (seq, batch, feature), [2,1,512], [3,1,512],…

下图为Transformer的整体结构。

RKNN Transformer模型_深度学习_23