搞懂 Vision Transformer 原理和代码,看这篇技术综述就够了(六)
极市导读
本文为详细解读Vision Transformer的第六篇,主要介绍了2种将卷积引入Transformer模型的方法:CvT和CeiT。>>加入极市CV技术交流群,走在计算机视觉的最前沿
考虑到每篇文章字数的限制,每一篇文章将按照目录的编排包含三个小节,而且这个系列会随着Vision Transformer的发展而长期更新。
本文目录
13 CvT: Introducing Convolutions to Vision Transformers
(来自麦吉尔大学, 微软云+AI)
13.1 CvT原理分析14 CeiT:将卷积设计整合到视觉Transformers中
(来自商汤)
14.1 CeiT原理分析
Transformer 是 Google 的团队在 2017 年提出的一种 NLP 经典模型,现在比较火热的 Bert 也是基于 Transformer。Transformer 模型使用了 Self-Attention 机制,不采用 RNN 的顺序结构,使得模型可以并行化训练,而且能够拥有全局信息。
本文介绍的两个工作都是将卷积CNN模型引入Transformer模型中来产生两种设计的最佳效果,从而提高了视觉Transformer(ViT)的性能和效率。
13 CvT: Introducing Convolutions to Vision Transformers
论文名称:CvT: Introducing Convolutions to Vision Transformers
论文地址:
https://arxiv.org/pdf/2103.15808.pdf
13.1 CvT原理分析:
Motivation
Transformer已经被证明在许多视觉任务上可以取得不错的性能。ViT是首创的把Transformer应用在分类任务的工作。但是,ViT的性能弱于具有相似的尺寸的CNN的性能,而且,ViT所需要的训练数据量要比同尺寸的CNN模型大很多。作者认为这是因为基于Transformer的ViT缺乏了一些CNN特有的 "desirable properties" ,而这些properties使得CNN模型很适合视觉任务。这句话应该如何理解呢?请参考我的下面这个回答:
CNN是不是一种局部self-attention?
https://www.zhihu.com/question/448924025/answer/1805511430
如图1,今天在使用self-attention去处理一张图片的时候,1的那个pixel产生query,其他的各个pixel产生key。在做inner-product的时候,考虑的不是一个小的范围,而是一整张图片。
但是在做CNN的时候是只考虑感受野红框里面的资讯,而不是图片的全局信息。所以CNN可以看作是一种简化版本的self-attention。
或者可以反过来说,self-attention是一种复杂化的CNN,在做CNN的时候是只考虑感受野红框里面的资讯,而感受野的范围和大小是由人决定的。但是self-attention由attention找到相关的pixel,就好像是感受野的范围和大小是自动被学出来的,所以CNN可以看做是self-attention的特例,如图2所示。
既然self-attention是更广义的CNN,则这个模型更加flexible。而我们认为,一个模型越flexible,训练它所需要的数据量就越多,所以在训练self-attention模型时就需要更多的数据,这一点在论文 ViT 中有印证,它需要的数据集是有3亿张图片的私有数据集 JFT-300,性能超越了CNN。而如果不使用这么多数据而只使用ImageNet,则性能不如CNN。
上面这个回答的意思是说:CNN是一种很特殊的Self-attention,它总是通过local receptive fields, shared weights, spatial subsampling等等的操作,考虑一张图片的空间上相邻的那些信息 (spatially neighboring pixels)。而正好这些信息是高度相关的 (highly correlated)。可是,基于Transformer的ViT模型就没有这种特性了,所以需要更多的数据来训练,这是第1个property。
另1个property是CNN的hierarchical structure可以考虑不同level的信息,不论是low-level的边缘特征还是high-level的语义特征。
那么一个自然而然的问题是:可否把CNN融入Transformer中,使得Transformer也具有CNN的这些适合图片的property呢?
其实从理论上来讲完全没必要这么做,因为从图2我们就知道Self-attention就是一种更复杂,更广泛的CNN。但是问题是要想把ViT训练得和CNN一样好需要很多的图片,甚至是JFT-300这样的私有数据集。所以,将CNN融入Transformer中的目的就是节约数据集。
以上就是CvT这个工作的motivation。
CvT具有CNN的一些优良的特征:局部感受野,共享卷积权重,空间下采样。
CvT具有Self-attention的一些优良的特征:动态的注意力机制,全局信息的融合。
作者通过实验声称:CvT在ImageNet-1k这个数据集上训练,达到了SOTA的性能,比ViT,DeiT的参数量和计算量更小,且比CNN的性能更好。
作者通过实验声称:CvT在ImageNet这个数据集(也就是ImageNet-22k)上训练,也达到了SOTA的性能。
CvT具体的结构如下图3所示。总的pipeline是一个multi-stage的hierarchical的结构。
作者在这个结构中引入了2个卷积操作,分别叫做Convolutional Token Embedding 和Convolutional Projection。
Convolutional Token Embedding
在每个stage中我们会进行下面的操作:输入的2D token map会先进入Convolutional Token Embedding这个层,相当于在2D reshaped token map上做一次卷积操作。这个层的输入是个reshape成2D的token。再通过一个Layer Normalization。卷积的目的是保证在每个阶段都减小token的数量,也就是减小feature resolution;在每个阶段都扩大token width,也就是扩大feature dimension。这样实现的效果就和CNN差不多,都是随着层数的加深而逐渐减小feature resolution和逐渐增加feature dimension。
按照上面的讲法,假设前一层的输出维度是 ,先通过Convolutional Token Embedding的常规的卷积操作得到 ,再把它flatten成一个 的张量并进行Layer Normalization操作,得到的结果进入下面的第 个stage的Transformer Block的操作。这些操作的目的是保证在每个阶段都减小token的数量,也就是减小feature resolution;在每个阶段都扩大token width,也就是扩大feature dimension。
在每个stage中,Convolutional Token Embedding的输出会再通过Convolutional Transformer Blocks,其结构如下图4所示。这个结构长得和普通Transformer的Block差不多,只是把普通Transformer的Block中的Linear Projection操作换成了Convolutional Projection操作,说白了就是用Depth-wise separable convolution 操作来代替了Linear Projection操作。
如下图5所示为ViT中使用的Linear projection操作,采用的是线性的映射。
如下图6所示为CvT中使用的Convolutional Projection操作,采用的是卷积变换。具体来讲,token首先reshape成2D的token map,再分别通过3个Depthwise-separable Convolution (kernel = )变成query,key和value值。最后再把这些query,key和value值通过flatten操作得到真正的query,key和value值。写成公式就是:
式中, 是个Depthwise-separable Convolution的复合操作:
。
为了使得模型进一步简化,作者又提出了如图7所示的Squeezed convolutional projection操作。对于常规的Convolution所需的参数量和计算量分别是 和 。式中 是token的channel dimension, 是token的数量。
如果是Depthwise-separable Convolution所需的参数量和计算量分别是 和 。
作者在计算query时,采用的Depthwise-separable Convolution的stride值为1。在计算key和value时,采用的Depthwise-separable Convolution的stride值为2。如下图7所示。按照这种方式,token的数量对于key和value来说可以减少4倍,性能只有很少的下降。
这种卷积操作可以补偿分辨率下降带来的损失。
还有2个其他的变化是:
不再使用位置编码。 class token只加在最后一个stage里面。
问:CvT为什么能够不用位置编码?
答: 因为CvT的Convolutional Projection操作,采用的是卷积变换,也就是说,CvT把传统Transformer的Linear Projection操作给换成了卷积操作。具体的方法上面也介绍了,就是先reshape成2D的,再做卷积,最后再reshape成sequence的形式。那么最重要的是卷积的zero-padding操作可以暗含位置信息,这一点已经被美团的CPVT方法所证明了。所以就不用再像ViT,DeiT一样使用显式的位置编码了。
Experiments:
数据集: ImageNet-1k (1.3M images),ImageNet (14M images,22k类),CIFAR-10/100,Oxford-IIIT-Pet,Oxford-IIIT-Flower。
不同尺寸模型: 如图8所示。图中的缩写Conv. Embed. 代表Convolutional Token Embedding,Conv. Proj. 代表 Convolutional Projection, 代表第 个stage的MHSA的head数量, 代表第 个stage的MHSA的embedding dimension, 代表第 个stage的MLP的expansion ratio值。CvT-13代表包括13个Transformer Block的CvT模型,CvT-W24代表一个加宽的CvT-24模型。
优化器: AdamW。CvT-13 weight decay = 0.05,CvT-24 weight decay = 0.1。
Fine-tuning: 微调的策略与ViT一致,优化器使用SGD,momentem取0.9。Fine-tune的办法是:都首先在分辨率224×224的数据上进行训练,后面在384×384的数据上finetune。batch size = 512,fine-tune的数据集有ImageNet-1k,CIFAR-10,CIFAR-100,Oxford-IIIT Pets,Oxford-IIIT Flowers-102。
与SOTA模型的对比:
作者比较了几个最近刚出来的基于Transformer的模型,包括我们组最新的TNT和早些的T2T。这个表格比较的数据集有ImageNet,ImageNet Real 和 ImageNet V2。
CvT模型可以以较低的参数量和计算量达到更好的性能,比如21层的CvT在ImageNet上可以达到82.5%的高性能,比DeiT-B的性能还要好,而参数量和计算量都有大幅地下降。
CvT模型也展示出了比最近刚出的新模型还要更优的性能:比如在相当的参数量和计算量的前提下性能优于TNT,T2T,PVT-small等等。
而且,CvT模型可以进一步通过NAS方法以提升性能。作者搜索了key和value的convolution projection的stride值,搜索空间是1或者2。也搜索MLP层的expansion ratio的值,搜索空间是2或者4。搜索出来的结构是第1个和最后一个stage的stride=2, ratio=2,其他的stage的大多数层都是stride=1,ratio=4。NAS的结果只有18M,精度能达到82.2%。
CvT系列最大的模型:CvT-W24可以在ImageNet上达到87.7%的性能,不需要JFT-300预训练,超过了ViT-L模型。
迁移学习性能:
CvT在小数据集上的结果如图10所示。
对比实验1:位置编码的影响
作者在CvT中没有使用位置编码,为了探究这么做到底会不会影响性能,作者设计了以下6个实验,发现DeiT在不使用位置编码时会掉点,但是CvT不使用位置编码则不会影响性能,与前述结论一致。根本原因还是CvT中的卷积操作自带了暗位置信息。
对比实验2:Convolutional Token Embedding的影响
为了说明Convolutional Token Embedding的作用,作者把它替换成了Patch embedding并做了如下4组实验。结果表明,当使用Convolutional Token Embedding并不使用位置编码时效果最佳,当使用Patch embedding并同时使用位置编码时效果次之。
对比实验3:Convolutional Projection对比实验
作者首先在图13中对比了Convolutional Projection的stride的影响,当把stride=1换成stride=2之后,计算量会有下降,但是精度也有相应的下降。
作者在图14中对比了把 Convolutional Projection 替换成传统的Position-wise 的 Linear Projection之后的性能变化。结果发现在3个stage中都使用 Convolutional Projection 时的性能是最优的,证明 Convolutional Projection 是一种很有效的建模策略。
总结:
CvT是如何将卷积操作引入Transformer的呢?
首先embedding的方式变成了卷积操作,在每个Multi-head self-attention之前都进行Convolutional Token Embedding。
其次在 Self-attention的Projection操作不再使用传统的Linear Projection,而是使用Convolutional Projection。
最后取消位置编码,因为卷积操作包含了暗位置信息。
CvT模型算是把模型从Transformer向着CNN的方向又拉了一把。
14 CeiT:将卷积设计整合到视觉Transformers中
论文名称:Incorporating Convolution Designs into Visual Transformers
论文地址:
https://arxiv.org/pdf/2103.11816.pdf
14.1 CeiT原理分析:
CeiT也是想借助CNN来提升Transformer的性能,作者给出的理由与CvT大致思路一致,二者几乎是同时提出的,所以解释这个问题的思路一致也很正常。作者认为CNN的最重要的特征是不变性 (invariance) 和局部性 (locality)。
不变性 (invariance) 是指卷积的权重共享机制,使得卷积能够捕获一个相邻区域的特征且具有平移不变性。
局部性 (locality) 是指在视觉任务中,相邻的pixel之间往往是相互关联的。
这两点和 CvT 中所强调的CNN特有的局部感受野,共享卷积权重,空间下采样如出一辙。
但是Transformer很难利用好这些特性,即:很难高效地提取low-level的特征,self-attention模块的长处是提炼token之间的 long-range 的信息之间的关系,往往会忽略空间信息。
基于此,作者想把CNN的特性融入进来以解决这些问题,使模型既具备CNN的提取low-level特征的能力,强化局部特征的提取,也具有Transformer的提炼token之间的 long-range 的信息之间的关系的能力。
具体来说:
为了有效地提取low-level feature,作者通过 Image-to-tokens 先使用卷积+Flatten操作把图片变为tokens,而不是通过直接分patch的方法。 为了强化局部特征的提取,作者把MLP层的Feed-Forwardnetwork 换成了 Locally-enhanced Feed-Forward layer,在空间维度上促进相邻token之间的相关性。 除此之外,在Transformer顶部使用 Layer-wise Class token Attention 进一步提升性能。
Image-to-tokens 模块
ViT采用的是直接把一张 的图片分成 个patch,每个patch的大小是 的,所以patch的数量 。但如上文所述,这么做会很难捕捉到low-level的信息,比如图片的边和角的信息。而且,self-attention建模的是全局的信息,所以相当于是使用了很大的kernel,这样的kernel由于参数量过多导致很难训练,需要大量的数据。
鉴于此作者提出了Image-to-tokens模块,如上图15所示。是一个轻量化的模块,有一个卷积操作加上一个Batch Normalization + Max-pooling构成,写成公式就是:
式中 , 是卷积操作的stride值, 是做完卷积操作以后的channel数。这步卷积得到的 会再分成patch,为了保持与ViT的patch数量的一致性,此时的patch的大小将有原来的 变为 ,其中的 。
I2T模块充分利用了 在提取low-level的特征方面的优势,通过缩小patch的大小来降低嵌入的训练难度。
注意:
其实这一步和CvT的 Convolutional Token Embedding 操作是几乎一模一样的,只是CeiT是在一开始进行的,而CvT是在
Locally-enhanced Feed-Forward layer
为了结合CNN提取局部信息的优势和Transformer建立远程依赖关系的能力,强化局部特征的提取,作者把MLP层的Feed-Forwardnetwork 换成了 Locally-enhanced Feed-Forward layer,在空间维度上促进相邻token之间的相关性。
具体的做法是:保持MSA模块不变, 保留捕获token之间全局相似性的能力。相反,原来的前馈网络层被Locally-enhanced Feed-Forward layer (LeFF)取代。结构如图16所示。
LeFF的具体流程是:首先,输入的token 由前面的MSA模块得到,然后分成2部分,第1部分是把class token 单独拿出来,剩下的第2部分是 。接着把第2部分通过linear projection把 拓展到高维的 ,其中 代表expand ratio。接着将其还原成2D的图片 ,再通过Depth-wise convolution得到 ,再Flatten成 的张量。最后通过Linear Projection映射回原来的维度 ,并与一开始的class token concat起来得到 。每个Linear Projection和convolution之后都会加上BatchNorm 和 GELU 操作。总的流程可以写成下式:
注意:
其实这一步和CvT的Convolutional Projection操作是几乎一模一样的,只是LeFF加入了升降维度以及GELU 操作。
Layer-wise Class token Attention
在CNN中,随着网络层数的加深,感受野在不断地变大。所以不同layer的feature representation是不同的。为了综合不同layer的信息,作者提出了Layer-wise Class token Attention模块,它把 个layer的class token都输入进去,并经过一次Multi-head Self-attention模块和一个FFN网络,得到最终的output,如下图17所示。它计算的是这 个layer的class token的相互关系。
复杂度分析
I2T模块和普通分patch方法的复杂度:
普通分patch方法采用的是torch.unfold操作,相当于是做个卷积来分patch,卷积的 ,所以计算量一共是:
I2T模块先进行一步卷积,卷积的 ,所以计算量是:
再进行一步MaxPool,池化层的 ,所以计算量是:
最后再分patch,采用的是torch.unfold操作,相当于是做个卷积来分patch,卷积的 ,所以计算量一共是:
I2T模块的总计算量是:
计算量相比于原来的ViT的分patch操作应该是其1.1倍,计算量上差不多。
以上FLOPs的计算和原论文有微小差别,我是按照自己的理解推的。若读者发现任何错误之处欢迎指正。
LeFF和FFN的复杂度:
假设FFN层的 ,FFN的计算量是 。LeFF所增加的是一个Depth-wise Convolution,其计算量为: 。相比于 的原计算量来讲可以忽略不计。
LCA模块的复杂度:
与原Transformer的 层encoder相比,LCA模块只计算 个class token的相关关系,这个计算只进行一次,所以也忽略了。
Experiments:
数据集: ImageNet-1k (1.2M images),Standford Cars,Oxford-102 Followers,Oxford-IIIT-Pet,Oxford-IIIT-Flower,CIFAR-10/100。
不同尺寸模型: 如图18所示,CeiT模型也是分为3种:Tiny,Small,Base,它们在embedding dimension,heads上面有差别。
超参数: 如图19所示为CeiT模型所使用的超参数。
常用的超参数的设置和DeiT一致,比如fine-tune时分辨率设为384,epoch数设置为30,learning rate减小等等。
ImageNet实验结果:
如下图20所示为ImageNet上的实验结果,首先来比较下CeiT和CNN模型。CeiT-T模型与ResNet-50的性能相当,但是参数量由25.6M下降为6.4M,计算量由4.1G下降为1.2G。CeiT-S模型与ResNet-50的大小相当,但是性能由76.7涨到了82.0,但是性能还是无法达到EfficientNet的标准。
我们再来比较下CeiT和ViT/DeiT。CeiT-T模型的性能与ViT-L/16很接近,一个是76.4,一个是76.5。但是CeiT-T模型大小只有后者的0.02倍。CeiT-T模型与DeiT-T的模型大小和计算量几乎一致,但是性能涨了4.2个点。
最后作者比较了CeiT与使用蒸馏方法训练的DeiT模型 (DeiT+Teacher),CeiT的Tiny模型和small模型也可以分别再涨1.9个点和0.8个点。
迁移学习性能:
CeiT在小数据集上的结果如图21所示。CeiT-S在大多数数据集上都超过了DeiT-B,并具有更小的参数量和计算量。在分辨率为384的数据集上fine-tune之后的CeiT-S模型的性能可以与EfficientNet-b7比较,展示出了将CNN与Transformer模型结合的潜力。
对比实验1:I2T模块的影响
作者对比了使用不同结构的I2T模块的影响,以第1行为例,意思是说不使用Maxpooling层,卷积操作换成 的卷积,不使用BN层,结果只有71.4,不如原来的直接分patch的方案。从下图中可以得出结论:当卷积使用 ,Maxpooling使用 ,同时使用BN时候效果最好,可以达到73.4。
对比实验2:LeFF模块LCA模块的影响
这里做这对比的是LeFF模块不同的kernel size的影响以及是否使用BN的影响。使用1×1的kernel size会掉点,使用更大的kernel size时,感受野变大,性能也会相应提升。BN层也会进一步提升性能。考虑到参数量和准确率的trade-off,作者最终选择了3×3的kernel size+BN。此外,加上LCA模块以后性能从72.2%涨到了72.8,说明不同level的信息对于最终的image representation都有贡献。
总结:
CeiT的思路和上一篇CvT极其相似,都是在图像分patch之前先通过一个卷积操作,提取low-level的信息,再进行后续的操作。只是CvT是每个stage来一次卷积,一共3次。CeiT是只在一开始分patch之前来一次这样的操作,一共就1次。另外,都是在Linear Projection操作中融入了卷积,方法都是先把 的特征reshape成2D的feature,再经过Depth-wise convolution操作,至于为什么是Depth-wise convolution而不是简单的卷积,很显然是为了节约计算量,否则卷积计算量太大导致作者不好讲故事。
但它们是由两家提出来的,这至少能够证明的是:
CNN和Transformer结合是一个涨点的方向,可以发挥2者的优势。 Linear Projection操作可以转化成卷积,模型照样会work,这一点2篇文章都已经证明了。 图片分patch之前可以先用卷积提特征,这一点2篇文章都已经证明了。 这个坑已经被填了,如果后面的研究者再想做个CNN + Transformer的工作,可能要考虑换个角度了。
Summary:
本文介绍了2种将卷积引入Transformer模型的方法。
CvT首先embedding的方式变成了卷积操作,在每个Multi-head self-attention之前都进行Convolutional Token Embedding。其次在 Self-attention的Projection操作不再使用传统的Linear Projection,而是使用Convolutional Projection。最后取消位置编码,因为卷积操作包含了暗位置信息。
CeiT的思路和上一篇CvT极其相似,都是在图像分patch之前先通过一个卷积操作,提取low-level的信息,再进行后续的操作。只是CvT是每个stage来一次卷积,一共3次。CeiT是只在一开始分patch之前来一次这样的操作,一共就1次。另外,都是在Linear Projection操作中融入了卷积,方法都是先把 的特征reshape成2D的feature,再经过Depth-wise convolution操作。
总之,之间人们使用纯Transformer模型完成视觉任务,这个坑被填过之后,把CNN与Transformer结合也势必会成为新的坑可填。Motivation其实也很直接,就是说Transformer不具备CNN的某些特性,比如2篇文章中讲到的 局部感受野 locality,共享卷积权重 invariance,空间下采样 等等。所以要结合,然后每家使用一些不同的结合手段,使得模型达到一个不错的效果。