首页 » 常识 » 预防 » 搞懂VisionTransforme
TUhjnbcbe - 2021/6/19 14:58:00

作者丨科技猛兽

编辑丨极市平台

本文对VisionTransformer的原理和代码进行了非常全面详细的解读,一切从Self-attention开始、Transformer的实现和代码以及Transformer+Detection:引入视觉领域的首创DETR。

Transformer是Google的团队在年提出的一种NLP经典模型,现在比较火热的Bert也是基于Transformer。Transformer模型使用了Self-Attention机制,不采用RNN顺序结构,使得模型可以并行化训练,而且能够拥有全局信息。本文将对VisionTransformer的原理和代码进行非常全面的解读。考虑到每篇文章字数的限制,每一篇文章将按照目录的编排包含三个小节,而且这个系列会随着VisionTransformer的发展而长期更新。

目录

(每篇文章对应一个Section,目录持续更新。)

Section1

1一切从Self-attention开始1.1处理Sequence数据的模型1.2Self-attention1.3Multi-headSelf-attention1.4PositionalEncoding

2Transformer的实现和代码解读(NIPS)(来自GoogleResearch,BrainTeam)2.1Transformer原理分析2.2Transformer代码解读

3Transformer+Detection:引入视觉领域的首创DETR(ECCV)(来自FacebookAI)3.1DETR原理分析3.2DETR代码解读

Section2

4Transformer+Detection:DeformableDETR:可变形的Transformer(ICLR)(来自商汤代季峰老师组)4.1DeformableDETR原理分析4.2DeformableDETR代码解读

5Transformer+Classification:用于分类任务的Transformer(ICLR)(来自GoogleResearch,BrainTeam)5.1ViT原理分析5.2ViT代码解读

6Transformer+ImageProcessing:IPT:用于底层视觉任务的Transformer(来自北京华为诺亚方舟实验室)6.1IPT原理分析

Section3

7Transformer+Segmentation:SETR:基于Transformer的语义分割(来自复旦大学,腾讯优图等)7.1SETR原理分析

8Transformer+GAN:VQGAN:实现高分辨率的图像生成(来自德国海德堡大学)8.1VQGAN原理分析8.2VQGAN代码解读

9Transformer+Distillation:DeiT:高效图像Transformer(来自FacebookAI)9.1DeiT原理分析

1一切从Self-attention开始1.1处理Sequence数据的模型:

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

要处理一个Sequence,最常想到的就是使用RNN,它的输入是一串vectorsequence,输出是另一串vectorsequence,如下图1左所示。

如果假设是一个singledirectional的RNN,那当输出

时,默认

都已经看过了。如果假设是一个bi-directional的RNN,那当输出

任意时,默认

都已经看过了。RNN非常擅长于处理input是一个sequence的状况。

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

为什么说RNN很不容易并行化呢?假设在singledirectional的RNN的情形下,你今天要算出

,就必须要先看

再看

再看

再看

,所以这个过程很难平行处理。

所以今天就有人提出把CNN拿来取代RNN,如下图1右所示。其中,橘色的三角形表示一个filter,每次扫过3个向量

,扫过一轮以后,就输出了一排结果,使用橘色的小圆点表示。

这是第一个橘色的filter的过程,还有其他的filter,比如图2中的黄色的filter,它经历着与橘色的filter相似的过程,又输出一排结果,使用黄色的小圆点表示。

图1:处理Sequence数据的模型图2:处理Sequence数据的模型

所以,用CNN,你确实也可以做到跟RNN的输入输出类似的关系,也可以做到输入是一个sequence,输出是另外一个sequence。

但是,表面上CNN和RNN可以做到相同的输入和输出,但是CNN只能考虑非常有限的内容。比如在我们右侧的图中CNN的filter只考虑了3个vector,不像RNN可以考虑之前的所有vector。但是CNN也不是没有办法考虑很长时间的dependency的,你只需要堆叠filter,多堆叠几层,上层的filter就可以考虑比较多的资讯,比如,第二层的filter(蓝色的三角形)看了6个vector,所以,只要叠很多层,就能够看很长时间的资讯。

而CNN的一个好处是:它是可以并行化的(canparallel),不需要等待红色的filter算完,再算黄色的filter。但是必须要叠很多层filter,才可以看到长时的资讯。所以今天有一个想法:self-attention,如下图3所示,目的是使用self-attentionlayer取代RNN所做的事情。

图3:YoucantrytoreplaceanythingthathasbeendonebyRNNwithselfattention

所以重点是:我们有一种新的layer,叫self-attention,它的输入和输出和RNN是一模一样的,输入一个sequence,输出一个sequence,它的每一个输出

都看过了整个的输入sequence,这一点与bi-directionalRNN相同。但是神奇的地方是:它的每一个输出

可以并行化计算。

1.2Self-attention:

那么self-attention具体是怎么做的呢?

图4:self-attention具体是怎么做的?

首先假设我们的input是图4的

,是一个sequence,每一个input(vector)先乘上一个矩阵

得到embedding,即向量

。接着这个embedding进入self-attention层,每一个向量

分别乘上3个不同的transformationmatrix

,以向量

为例,分别得到3个不同的向量

图5:self-attention具体是怎么做的?

接下来使用每个query

去对每个key

做attention,attention就是匹配这2个向量有多接近,比如我现在要对

做attention,我就可以把这2个向量做scaledinnerproduct,得到

。接下来你再拿

做attention,得到

,你再拿

做attention,得到

,你再拿

做attention,得到

。那这个scaledinnerproduct具体是怎么计算的呢?

式中,

的维度。因为

的数值会随着dimension的增大而增大,所以要除以

的值,相当于归一化的效果。

接下来要做的事如图6所示,把计算得到的所有

值取

操作。

图6:self-attention具体是怎么做的?

取完

操作以后,我们得到了

,我们用它和所有的

值进行相乘。具体来讲,把

乘上

,把

乘上

,把

乘上

,把

乘上

,把结果通通加起来得到

,所以,今天在产生

的过程中用了整个sequence的资讯(Consideringthewholesequence)。如果要考虑local的information,则只需要学习出相应的

就不再带有那个对应分支的信息了;如果要考虑global的information,则只需要学习出相应的

就带有全部的对应分支的信息了。

图7:self-attention具体是怎么做的?

同样的方法,也可以计算出

,如下图8所示,

就是拿query

去对其他的

做attention,得到

,再与value值

相乘取weightedsum得到的。

图8:self-attention具体是怎么做的?

经过了以上一连串计算,self-attentionlayer做的事情跟RNN是一样的,只是它可以并行的得到layer输出的结果,如图9所示。现在我们要用矩阵表示上述的计算过程。

图9:self-attention的效果

首先输入的embedding是

,然后用

乘以transformationmatrix

得到

,它的每一列代表着一个vector

。同理,用

乘以transformationmatrix

得到

,它的每一列代表着一个vector

。用

乘以transformationmatrix

得到

,它的每一列代表着一个vector

图10:self-attention的矩阵计算过程

接下来是

的attention过程,我们可以把vector

横过来变成行向量,与列向量

做内积,这里省略了

。这样,

就成为了

的矩阵,它由4个行向量拼成的矩阵和4个列向量拼成的矩阵做内积得到,如图11所示。

在得到

以后,如上文所述,要得到

,就要使用

分别与

相乘再求和得到,所以

要再左乘

矩阵。

图11:self-attention的矩阵计算过程

到这里你会发现这个过程可以被表示为,如图12所示:输入矩阵

分别乘上3个不同的矩阵

得到3个中间矩阵

。它们的维度是相同的。把

转置之后与

相乘得到Attention矩阵

,代表每一个位置两两之间的attention。再将它取

操作得到

,最后将它乘以

矩阵得到输出vector

图12:self-attention就是一堆矩阵乘法,可以实现GPU加速1.3Multi-headSelf-attention:

还有一种multi-head的self-attention,以2个head的情况为例:由

生成的

进一步乘以2个转移矩阵变为

,同理由

生成的

进一步乘以2个转移矩阵变为

,由

生成的

进一步乘以2个转移矩阵变为

。接下来

再与

做attention,得到weightedsum的权重

,再与

做weightedsum得到最终的

。同理得到

。现在我们有了

,可以把它们concat起来,再通过一个transformationmatrix调整维度,使之与刚才的

维度一致(这步如图13所示)。

图13:multi-headself-attention图13:调整b的维度

从下图14可以看到Multi-HeadAttention包含多个Self-Attention层,首先将输入

分别传递到2个不同的Self-Attention中,计算得到2个输出结果。得到2个输出矩阵之后,Multi-HeadAttention将它们拼接在一起(Concat),然后传入一个Linear层,得到Multi-HeadAttention最终的输出

。可以看到Multi-HeadAttention输出的矩阵

与其输入的矩阵

的维度是一样的。

图14:multi-headself-attention

这里有一组Multi-headSelf-attention的解果,其中绿色部分是一组query和key,红色部分是另外一组query和key,可以发现绿色部分其实更

1
查看完整版本: 搞懂VisionTransforme