**
1. 相关链接
:**
原文链接:An Image is Worth 16x16 Words: Transformers for Image Recognition at Scale (arxiv.org)
原文开源代码:GitHub - google-research/vision_transformer
Pytorch版本代码:GitHub - lucidrains/vit-pytorch: Implementation of Vision Transformer, a simple way to achieve SOTA in vision classification with only a single transformer encoder, in Pytorch
2. 参考
2.1 B站视频:ViT论文逐段精读【论文精读】
2.2 B站视频笔记
3. 前言
过去一年在计算机视觉领域影响力最大的工作:
- 挑战了自从2012年AlexNet提出以来卷积神经网络在计算机视觉里绝对统治的地位;
- 结论:如果在足够多的数据上做预训练,也可以不需要卷积神经网路,直接使用标准的Transformer也能够把视觉问题解决的很好;
- 打破了CV和NLP在模型上的壁垒,开启了CV的一个新时代
- 目前Transformer才刚刚开始应用到计算机视觉领域,还有很大的进步空间,未来的效果可能会更佳。
paperswithcode网站:
-
可以查询现在某个领域或者说某个数据集表现最好的一些方法有哪些
-
图像分类在ImageNet数据集上排名靠前的全是基于Vision Transformer
-
对于目标检测任务在COCO数据集上,排名靠前都都是基于Swin Transformer(Swin Transformer是ICCV 21的最佳论文,可以把它想象成一个多尺度的ViT(Vision Transformer))
- 在其他领域(语义分割、实例分割、视频、医疗、遥感),基本上可以说Vision Transformer将整个视觉领域中所有的任务都刷了个遍
作者介绍的另一篇论文:Intriguing Properties of Vision Transformer(Vision Transformer的一些有趣特性)
如下图所示:
- 图a表示的是遮挡,在这么严重的遮挡情况下,不管是卷积神经网络,人眼也很难观察出图中所示的是一只鸟
- 图b表示数据分布上有所偏移,这里对图片做了一次纹理去除的操作,所以图片看起来比较魔幻
- 图c表示在鸟头的位置加了一个对抗性的patch
- 图d表示将图片打散了之后做排列组合
上述例子中,卷积神经网络很难判断到底是一个什么物体,但是对于所有的这些例子Vision Transformer都能够处理的很好。
4. 标题+作者
4.1 An Image is Worth 16x16 Words:
- 一张图片等价于很多16×16大小的单词(比如下图,可以将图片分成4×5=20个小块,每个小块称为一个Patch,每一个Patch又是16×16像素的)
- 为什么是16×16的单词?将图片看成是很多的patch,假如把图片分割成很多方格的形式,每一个方格的大小都是16×16,那么这张图片就相当于是很多16×16的patch组成的整体。
4.2 Transformers for Image Recognition at Scale
4.3 作者
- 作者团队来自于google research和google brain team
5. 摘要 Abstract
虽然说transformer已经是NLP(自然语言处理)领域的一个标准:BERT模型、GPT3或者是T5模型,但是用transformer来做CV还是很有限的
在视觉领域,自注意力要么是跟卷积神经网络一起使用,要么用来把某一些卷积神经网络中的卷积替换成自注意力,但是还是保持整体的结构不变
- 这里的整体结构是指:比如说对于一个残差网络(Res50),它有4个stage:res2、res3、res4、res5,上面说的整体结构不变指的就是这个stage是不变的,它只是去取代每一个stage、每一个block的操作
这篇文章证明了这种对于卷积神经网络的依赖是完全不必要的,一个纯的Vision Transformer直接作用于一系列图像块的时候,也是可以在图像分类任务上表现得非常好的,尤其是当在大规模的数据上面做预训练然后迁移到中小型数据集上面使用的时候,Vision Transformer能够获得跟最好的卷积神经网络相媲美的结果
这里将ImageNet、CIFAR-100、VATB当作中小型数据集
- 其实ImageNet对于很多人来说都已经是很大的数据集了
Transformer的另外一个好处:它只需要更少的训练资源,而且表现还特别好
- 作者这里指的少的训练资源是指2500天TPUv3的天数
- 这里的少只是跟更耗卡的模型去做对比(类似于先挣一个亿的小目标)
6. 引言
自注意力机制的网络,尤其是Transformer,已经是自然语言中的必选模型了,现在比较主流的方式,就是先去一个大规模的数据集上去做预训练,然后再在一些特定领域的小数据集上面做微调(这个是在BERT的文章中提出来的)
得益于transformer的计算高效性和可扩展性,现在已经可以训练超过1000亿参数的模型了,比如说GPT3
随着模型和数据集的增长,目前还没有发现任何性能饱和的现象
- 很多时候不是一味地扩大数据集或者说扩大模型就能够获得更好的效果的,尤其是当扩大模型的时候很容易碰到过拟合的问题,但是对于transformer来说目前还没有观测到这个瓶颈
- 最近微软和英伟达又联合推出了一个超级大的语言生成模型Megatron-Turing,它已经有5300亿参数了,还能在各个任务上继续大幅度提升性能,没有任何性能饱和的现象
6.1 回顾Transformer:
- transformer中最主要的操作就是自注意力操作,自注意力操作就是每个元素都要跟每个元素进行互动,两两互相的,然后算得一个attention(自注意力的图),用这个自注意力的图去做加权平均,最后得到输出
- 因为在做自注意力的时候是两两互相的,这个计算复杂度是跟序列的长度呈平方倍的。O(n2)
- 目前一般在自然语言处理中,硬件能支持的序列长度一般也就是几百或者是上千(比如说BERT的序列长度也就是512)
6.2 把Transformer用到视觉问题上的难处:
首先要解决的是如何把一个2D的图片变成一个1D的序列(或者说变成一个集合)。最直观的方式就是把每个像素点当成元素,将图片拉直放进transformer里,看起来比较简单,但是实现起来复杂度较高。
一般来说在视觉中训练分类任务的时候图片的输入大小大概是224×224,如果将图片中的每一个像素点都直接当成元素来看待的话,他的序列长度就是224×224=50176个像素点,也就是序列的长度,这个大小就相当于是BERT序列长度的100倍(上面说到BERT的序列长度是512),这还仅仅是分类任务,对于检测和分割,现在很多模型的输入都已经变成600×600或者800×800或者更大,计算复杂度更高,所以在视觉领域,卷积神经网络还是占主导地位的,比如AlexNet或者是ResNet。
所以现在很多工作就是在研究如何将自注意力用到机器视觉中:一些工作是说把卷积神经网络和自注意力混到一起用;另外一些工作就是整个将卷积神经网络换掉,全部用自注意力。这些方法其实都是在干一个事情:因为序列长度太长,所以导致没有办法将transformer用到视觉中,所以就想办法降低序列长度。
例1:Wang et al.,2018 (Xiaolong Wang, Ross Girshick, Abhinav Gupta, and Kaiming He. Non-local neural networks. In
CVPR, 2018.):既然用像素点当输入导致序列长度太长,就可以不用图片当transformer的直接输入,可以把网络中间的特征图当作transformer的输入。
- 假如用残差网络Res50,其实在它的最后一个stage,到res4的时候的featuremap的size其实就只有14×14了,再把它拉平其实就只有196个元素了,即这个序列元素就只有196了,这就在一个可以接受的范围内了。所以就通过用特征图当作transformer输入的方式来降低序列的长度。
例2:Ramachandran et al., 2019(Prajit Ramachandran, Niki Parmar, Ashish Vaswani, Irwan Bello, Anselm Levskaya, and Jon Shlens.Stand-alone self-attention in vision models. In NeurIPS, 2019.)孤立自注意力
孤立自注意力:之所以视觉计算的复杂度高是来源于使用整张图,所以不使用整张图,就用一个local window(局部的小窗口),这里的复杂度是可以控制的(通过控制这个窗口的大小,来让计算复杂度在可接受的范围之内)。这就类似于卷积操作(卷积也是在一个局部的窗口中操作的)
例3:Wang et al., 2020a(Huiyu Wang, Yukun Zhu, Bradley Green, Hartwig Adam, Alan Yuille, and Liang-Chieh Chen.Axial-deeplab: Stand-alone axial-attention for panoptic segmentation. In ECCV, 2020a.)轴自注意力
轴自注意力:之所以视觉计算的复杂度高是因为序列长度N=H×W,是一个2D的矩阵,将图片的这个2D的矩阵想办法拆成2个1D的向量,所以先在高度的维度上做一次self-attention(自注意力),然后再在宽度的维度上再去做一次自注意力,相当于把一个在2D矩阵上进行的自注意力操作变成了两个1D的顺序的操作,这样大幅度降低了计算的复杂度。
最近的一些模型,这种方式虽然理论上是非常高效的,但事实上因为这个自注意力操作都是一些比较特殊的自注意力操作,所以说无法在现在的硬件上进行加速,所以就导致很难训练出一个大模型,所以截止到目前为止,孤立自注意力和轴自注意力的模型都还没有做到很大,跟百亿、千亿级别的大transformer模型比还是差的很远,因此在大规模的图像识别上,传统的残差网络还是效果最好的
所以,自注意力早已经在计算机视觉里有所应用,而且已经有完全用自注意力去取代卷积操作的工作了,所以本文换了一个角度来讲故事。
本文是被transformer在NLP领域的可扩展性所启发,本文想要做的就是直接应用一个标准的transformer直接作用于图片,尽量做少的修改(不做任何针对视觉任务的特定改变),看看这样的transformer能不能在视觉领域中扩展得很大很好。
但是如果直接使用transformer,还是要解决序列长度的问题
- vision transformer将一张图片打成了很多的patch,每一个patch是16*16
- 假如图片的大小是224×224,则sequence lenth(序列长度)就是N=224×224=50176,如果换成patch,一个patch相当于一个元素的话,有效的长宽就变成了224/16=14,所以最后的序列长度就变成了N=14×14=196,所以现在图片就只有196个元素了,196对于普通的transformer来说是可以接受的。
- 然后将每一个patch当作一个元素,通过一个fc layer(全连接层)就会得到一个linear embedding,这些就会当作输入传给transformer,这时候一张图片就变成了一个一个的图片块了,可以将这些图片块当成是NLP中的单词,一个句子中有多少单词就相当于是一张图片中有多少个patch,这就是题目中所提到的一张图片等价于很多16×16的单词。
本文训练vision transformer使用的是有监督的训练
- 为什么要突出有监督?因为对于NLP来说,transformer基本上都是用无监督的方式训练的,要么是用language modeling,要么是用mask language modeling,都是用的无监督的训练方式。但是对于视觉来说,大部分的基线(baseline)网络还都是用的有监督的训练方式去训练的。
到此可以发现,本文确实是把视觉当成自然语言处理的任务去做的,尤其是中间的模型就是使用的transformer encoder,跟BERT完全一样,这篇文章的目的是说使用一套简洁的框架,transformer也能在视觉中起到很好的效果。
这么简单的想法,之前其实也有人想到去做,本文在相关工作中已经做了介绍,跟本文的工作最像的是一篇ICLR 2020的paper(Jean-Baptiste Cordonnier, Andreas Loukas, and Martin Jaggi. On the relationship between selfattention and convolutional layers. In ICLR, 2020.)
- 这篇论文是从输入图片中抽取2×2的图片patch
- 为什么是2×2?因为这篇论文的作者只在CIFAR-10数据集上做了实验,而CIFAR-10这个数据集上的图片都是32×32的,所以只需要抽取2×2的patch就足够了,16×16的patch就太大了
- 在抽取好patch之后,就在上面做self-attention
从技术上而言他就是Vision Transformer,但是本文的作者认为二者的区别在于本文的工作证明了如果在大规模的数据集上做预训练的话(和NLP一样,在大规模的语料库上做预训练),那么就能让一个标准的Transformer,不用在视觉上做任何的更改或者特殊的改动,就能取得比现在最好的卷积神经网络差不多或者还好的结果,同时本文的作者还指出之前的ICLR的这篇论文用的是很小的2×2的patch,所以让他们的模型只能处理那些小的图片,而Vision Transformer是能够处理224×224这种图片的
所以这篇文章的主要目的就是说,Transformer在Vision领域能够扩展的有多好,就是在超级大数据集和超级大模型两方的加持下,Transformer到底能不能取代卷积神经网络的地位。
一般引言的最后就是将最想说的结论或者最想表示的结果放出来,这样读者不用看完整篇论文就能知道文章的贡献有多大
本文在引言的最后说在中型大小的数据集上(比如说ImageNet)上训练的时候,如果不加比较强的约束,Vit的模型其实跟同等大小的残差网络相比要弱一点
- 作者对此的解释是:这个看起来不太好的结果其实是可以预期的,因为transformer跟卷积神经网路相比,它缺少了一些卷积神经网络所带有的归纳偏置
- 这里的归纳偏置其实是指一种先验知识或者说是一种提前做好的假设
对于卷积神经网络来说,常说的有两个inductive bias(归纳偏置):
- locality:因为卷积神经网络是以滑动窗口的形式一点一点地在图片上进行卷积的,所以假设图片上相邻的区域会有相邻的特征,靠得越近的东西相关性越强
- translation equivariance(平移等变性或平移同变性):f(g(x))=g(f(x)),就是说不论是先做 g 这个函数,还是先做 f 这个函数,最后的结果是不变的。这里可以把f理解成卷积,把g理解成平移操作,意思是说无论是先做平移还是先做卷积,最后的结果都是一样的(因为在卷积神经网络中,卷积核就相当于是一个模板,不论图片中同样的物体移动到哪里,只要是同样的输入进来,然后遇到同样的卷积核,那么输出永远是一样的)
一旦神经网络有了这两个归纳偏置之后,他就拥有了很多的先验信息,所以只需要相对较少的数据来学习一个相对比较好的模型,但是对于transformer来说,它没有这些先验信息,所以它对视觉的感知全部需要从这些数据中自己学习
- 为了验证这个假设,作者在更大的数据集(14M-300M)上做了预训练,这里的14M是ImageNet
22k数据集,300M是google自己的JFT 300M数据集,然后发现大规模的预训练要比归纳偏置好
Vision Transformer只要在有足够的数据做预训练的情况下,就能在下游任务上取得很好的迁移学习效果。具体来说,就是当在ImageNet 21k上或者在JFT 300M上训练,ViT能够获得跟现在最好的残差神经网络相近或者说更好的结果,如下图所示:
- VTAB也是作者团队所提出来的一个数据集,融合了19个数据集,主要是用来检测模型的稳健性,从侧面也反映出了Vision
Transformer的稳健性也是相当不错的
总的来说,引言写的简洁明了
- 第一段先说因为Transformer在NLP中扩展的很好,越大的数据或者越大的模型,最后performance会一直上升,没有饱和的现象,然后提出:如果将Transformer使用到视觉中,会不会产生同样的效果;
- 第二段开始讲前人的工作,讲清楚了自己的工作和前人工作的区别:之前的工作要么就是把卷积神经网络和自注意力结合起来,要么就是用自注意力去取代卷积神经网络,但是从来没有工作直接将transformer用到视觉领域中来,而且也都没有获得很好的扩展效果;
- 第三段讲Vision Transformer就是用了一个标准的Transformer模型,只需要对图片进行预处理(把图片打成块),然后送到transformer中就可以了,而不需要做其他的改动,这样可以彻底地把一个视觉问题理解成是一个NLP问题,就打破了CV和NLP领域的壁垒;
- 最后两段展示了结果,只要在足够多的数据做预训练的情况下,Vision Transformer能够在很多数据集上取得很好的效果。
7. 结论
这篇论文的工作是直接拿NLP领域中标准的Transformer来做计算机视觉的问题,跟之前用自注意力的那些工作的区别在于:
- 除了在刚开始抽图像块的时候,还有位置编码用了一些图像特有的归纳偏置
除此之外就再也没有引入任何图像特有的归纳偏置了,这样的好处就是不需要对Vision领域有多少了解,可以直接把图片理解成一个序列的图像块,就跟一个句子中有很多单词一样,然后就可以直接拿NLP中一个标准的Transformer来做图像分类了
当这个简单而且扩展性很好的策略和大规模预训练结合起来的时候效果出奇的好:Vision Transformer在很多图像分类的benchmark上超过了之前最好的方法,而且训练起来还相对便宜
目前还没有解决的问题(对未来的展望)
如何用transformer来做cv
第一个问题:Vi不能只做分类,还有检测和分割
- DETR:去年目标检测的一个力作,相当于是改变了整个目标检测之前的框架
鉴于ViT和DETR良好的表现,所以作者说拿Vision Transformer做视觉的其他问题应该是没有问题的
- 事实上,在ViT出现短短的一个半月之后,2020年12月检测这块就出来了一个叫ViT-FRCNN的工作,就已经将ViT用到检测上面了
- 图像分割这一块也是一样的,同年12月就有一篇SETR的paper将Vit用到分割里了
- 紧接着3个月之后Swin-Transformer横空出世,它将多尺度的设计融合到了Transformer中,更加适合做视觉的问题了,真正证明了Transformer是能够当成一个视觉领域的通用骨干网络
另外一个未来的工作方向就是说要去探索一下自监督的预训练方案,因为在NLP领域,所有的大的transformer全都是用自监督的方式训练的,Vit这篇paper也做了一些初始实验,证明了用这种自监督的训练方式也是可行的,但是跟有监督的训练比起来还是有不小的差距的。
最后作者说,继续将Vision Transformer变得更大,有可能会带来更好的结果
- 过了半年,同样的作者团队又出了一篇paper叫做Scaling Vision Transformer,就是将Transformer变得很大,提出了一个ViT-G,将ImageNet图像分类的准确率提高到了90以上了。
8. 相关工作
transformer在NLP领域的应用
- 自从2017年transformer提出做机器翻译以后,基本上transformer就是很多NLP任务中表现最好的方法。
- 现在大规模的transformer模型一般都是先在一个大规模的语料库上做预训练,然后再在目标任务上做一些细小的微调,这当中有两系列比较出名的工作:BERT和GPT。BERT是用一个denoising的自监督方式(其实就是完形填空,将一个句子中某些词划掉,再将这些词预测出来);GPT用的是language modeling(已经有一个句子,然后去预测下一个词是什么,也就是next word prediction,预测下一个词)做自监督。这两个任务其实都是人为定的,语料是固定的,句子也是完整的,只是人为的去划掉其中的某些部分或者把最后的词拿掉,然后去做完形填空或者是预测下一个词,所以这叫自监督的训练方式。
自注意力在视觉中的应用
- 视觉中如果想简单地在图片上使用自注意力,最简单的方式就是将每一个像素点当成是一个元素,让他们两两做自注意力就好了,但是这个是平方复杂度,所以很难应用到真实的图片输入尺寸上。像现在分类任务的224×224,一个transformer都很难处理,更不用提人眼看的比较清晰的图片了,一般是1k或者4k的画质,它们的序列长度都是上百万,直接在像素层面使用transformer的话不太现实,所以如果想用transformer就一定得做一些近似;
- 复杂度高是因为用了整张图,所以序列长度长,那么可以不用整张图,就用local neighborhood(一个小窗口)来做自注意力,那么序列长度就大大降低了,最后的计算复杂度也就降低了;
- 另外也可以使用Sparse(稀疏) Transformer,就是只对一些稀疏的点去做自注意力,所以只是一个全局注意力的近似;
- 还有一些方法就是将自注意力用到大小不同的block上,或者说在极端的情况下使用轴注意力(先在横轴上做自注意力,然后再在纵轴上做自注意力),序列长度也是大大减小的;
- 这些特制的自注意力结构其实在计算机视觉上的结果都不错,表现都是没问题的,但是它们需要很复杂的工程去加速算子,虽然在CPU或者GPU上跑得很快或者说让训练一个大模型成为可能。
跟本文工作最相似的是一篇ICLR2020的论文,区别在于Vision Transformer使用了更大的patch更大的数据集
在计算机视觉领域还有很多工作是把卷积神经网络和自注意力结合起来的,这类工作相当多,而且基本涵盖了视觉里的很多任务(检测、分类、视频、多模态等)
还有一个工作和本文的工作很相近,叫image GPT
- GPT是用在NLP中的,是一个生成性的模型
- image GPT也是一个生成性模型,也是用无监督的方式去训练的,它和Vit相近的地方在于它也用了transformer
- image GPT最终所能达到的效果:如果将训练好的模型做微调或者就把它当成一个特征提取器,它在ImageNet上的最高的分类准确率也只能到72,Vit最终的结果已经有88.5了,远高于72
- 但是这个结果也是最近一篇paper叫做MAE爆火的原因。因为在BEiT和MAE这类工作之前生成式网络在视觉领域很多任务上是没有办法跟判别式网络相比的,判别式网络往往要比生成式网络的结果高很多,但是MAE做到了,它在ImageNet-1k数据集上训练,用一个生成式的模型,比之前判别式的模型效果好很多,而且不光是在分类任务上,最近发现在目标检测上的迁移学习的效果也非常好
Vit其实还跟另外一系列工作是有关系的,用比ImageNet更大的数据集去做预训练,这种使用额外数据的方式,一般有助于达到特别好的效果
- 比如2017年介绍JFT 300数据集的那篇paper研究了卷积神经网络的效果是怎么随着数据集的增大而提高的
- 还有一些论文是研究了在更大的数据集(比如说ImageNet-21k和JFT
300M)上做预训练的时候迁移学习的效果会怎样,就是迁移到ImageNet或者CIFAR-100上的效果如何
这篇论文也是聚焦于ImageNet-21k和JFT 300M,但是训练的并不是一个残差网络,而失去训练transformer
本文的相关工作写的非常彻底,而且列举了很多跟本文工作最相近的,比如说ICLR 2020的论文、iGPT还有之前研究大数据集的BiT等
写相关工作这个章节的目的就是让读者知道在你的工作之前别人做了哪些工作,你和他们的区别在哪里。写清楚之后其实对论文本身是非常有利的,并不会降低论文的创新性,反而让整个文章变得更加简单易懂
9. ViT模型
在模型的设计上是尽可能按照最原始的transformer来做的,这样做的好处就是可以直接把NLP中比较成功的Transformer架构拿过来用,而不用再去对模型进行改动,而且因为transformer因为在NLP领域已经火了很久了,它有一些写的非常高效的实现,同样ViT也可以直接拿来使用。
9.1 ViT
下图是模型的总览图,模型的总览图对论文来说是非常重要的,画的好的模型总览图能够让读者在不读论文的情况下,仅仅通过看图就能够知道整篇论文的大致内容。
- 首先给定一张图,先将这张图打成了很多的patch(如上图左下角所示),这里是将图打成了九宫格
- 然后再将这些patch变成了一个序列,每个patch通过线性投射层(相当于一个全连接层)的操作得到一个特征(就是本文中提到的patch embedding)
- 自注意力是所有元素之间两两做交互,所以本身并不存在顺序的问题,但是对于图片来说,图片本身是一个整体,这个九宫格是有自己的顺序的,如果顺序颠倒了就不是原来的图片了。所以类似于NLP,给patch embedding加上了一个position embedding,等价于加上了一个位置编码
- 在加上这个位置编码信息之后,整体的token就既包含了图片块原本有的图像信息,又包含了这个图片块的所在位置信息
- 在得到了这个token之后,接下来就跟NLP中完全一样了,直接将它们输入进一个Transformer encoder,然后Transformer encoder就会得到很多输出
- 这么多输出,应该拿哪个输出去做分类?这里借鉴了BERT,BERT中有一个extra learnable embedding,它是一个特殊字符CLS(分类字符),所以这里也添加了一个特殊的字符,用 * 代替,而且它也是有position embedding,它的位置信息永远是0。
- 因为所有的token都在跟其它token做交互信息,所以作者相信,class embedding能够从别的序列后面的embedding中学到有用的信息,从而只需要根据class embedding的输出做最后的判断就可以了
- MLP Head其实就是一个通用的分类头
- 最后用交叉熵函数进行模型的训练
模型中的Transformer encoder是一个标准的Transformer,具体的结构如下图中右部分所示:
- Transformer的输入是一些patch
- 一个Transformer block叠加了L次
- 整体上来看Vision Transformer的架构还是相当简洁的,它的特殊之处就在于如何把一个图片变成一系列的token
具体的模型的前向过程:
- 假如说有一个224×224×3的图片,如果使用16×16的patch size大小,就会得到196个图像块,每一个图像块的维度就是16×16×3=768,到此就把原先224×224×3的图片变成了196个patch,每个patch的维度是768
- 接下来就要将这些patch输入一个线性投射层,这个线性投射层其实就是一个全连接层(在文章中使用E表示),这个全连接层的维度是768×768,第二个768就是文章中的D,D是可以变的,如果transformer变得更大了,D也可以相应的变得更大,第一个768是从前面图像的patch算来的(16×16×3),它是不变的。
- 经过了线性投射就得到了patch embedding(X×E),它是一个196×768的矩阵(X是196×768,E是768×768),意思就是现在有196个token,每个token向量的维度是768
- 到目前为止就已经成功地将一个vision的问题变成了一个NLP的问题了,输入就是一系列1d的token,而不再是一张2d的图片了
- 除了图片本身带来的token以外,这里面加了一个额外的cls token,它是一个特殊的字符,只有一个token,它的维度也是768,这样可以方便和后面图像的信息直接进行拼接。所以最后整体进入Transformer的序列的长度是197×768(196+1:196个图像块对应的token和一个特殊字符cls token)
- 最后还要加上图像块的位置编码信息,这里是将图片打成了九宫格,所以位置编码信息是1到9,但是这只是一个序号,并不是真正使用的位置编码,具体的做法是通过一个表(表中的每一行就代表了这些1到9的序号,每一行就是一个向量,向量的维度是768,这个向量也是可以学的)得到位置信息,然后将这些位置信息加到所有的token中(注意这里是加,而不是拼接,序号1到9也只是示意一下,实际上应该是1到196),所以加上位置编码信息之后,这个序列还是197×768
- 到此就做完了整个图片的预处理,包括加上特殊的字符cls和位置编码信息,也就是说transformer输入的embedded
patches就是一个197×768的tensor
- 这个tensor先过一个layer norm,出来之后还是197×768
- 然后做多头自注意力,这里就变成了三份:k、q、v,每一个都是197×768,这里因为做的是多头自注意力,所以其实最后的维度并不是768,假设现在使用的是VIsion Transformer的base版本,即多头使用了12个头,那么最后的维度就变成了768/12=64,也就是说这里的k、q、v变成了197×64,但是有12个头,有12个对应的k、q、v做自注意力操作,最后再将12个头的输出直接拼接起来,这样64拼接出来之后又变成了768,所以多头自注意力出来的结果经过拼接还是197×768
- 然后再过一层layer norm,还是197×768
- 然后再过一层MLP,这里会把维度先对应地放大,一般是放大4倍,所以就是197×3072
- 然后再缩小投射回去,再变成197×768,就输出了
- 以上就是一个Transformer block的前向传播的过程,进去之前是197×768,出来还是197×768,这个序列的长度和每个token对应的维度大小都是一样的,所以就可以在一个Transformer block上不停地往上叠加Transformer block,最后有L层Transformer block的模型就构成了Transformer encoder
- Transformer从头到尾都是使用D当作向量的长度的,都是768,这个维度是不变的
- 对于位置编码信息,本文用的是标准的可以学习的1d position embedding,它也是BERT使用的位置编码。作者也尝试了了别的编码形式,比如说2d aware(它是一个能处理2d信息的位置编码),但是最后发现结果其实都差不多,没有什么区别。
9.2 消融实验(附录)
针对特殊的class token还有位置编码,作者还做了详细的消融实验,因为对于Vision Transformer来说,怎么对图片进行预处理以及怎样对图片最后的输出进行后处理是很关键的,因为毕竟中间的模型就是一个标准的Transformer
1、class token
因为在本文中,想要跟原始的Transformer尽可能地保持一致,所以也使用了class token,因为class token在NLP的分类任务中也有用到(也是当作一个全局的对句子的理解的特征),本文中的class token是将它当作一个图像的整体特征,拿到这个token的输出以后,就在后面接一个MLP(MLP中是用tanh当作非线性的激活函数来做分类的预测)
- 这个class token的设计是完全从NLP借鉴过来的,之前在视觉领域不是这么做的,比如说有一个残差网络Res50,在最后一个stage出来的是一个14×14的feature map,然后在这个feature map之上其实是做了一个叫做gap(global average pooling,全局平均池化)的操作,池化以后的特征其实就已经拉直了,就是一个向量了,这个时候就可以把这个向量理解成一个全局的图片特征,然后再拿这个特征去做分类
对于Transformer来说,如果有一个Transformer模型,进去有n个元素,出来也有n个元素,为什么不能直接在n个输出上做全局平均池化得到一个最后的特征,而非要在前面加上一个class token,最后用class token的输出做分类?
- 通过实验,作者最后的结论是:这两种方式都可以,就是说可以通过全局平均池化得到一个全局特征然后去做分类,也可以用一个class token去做。本文所有的实验都是用class token去做的,主要的目的是跟原始的Transformer尽可能地保持一致(stay as close as possible),作者不想人觉得某些效果好可能是因为某些trick或者某些针对cv的改动而带来的,作者就是想证明,一个标准的Transformer照样可以做视觉。
两种方法的效果对比如下图所示:
- 绿线表示全局平均池化
- 蓝线表示class token
- 可以发现到最后绿线和蓝线的效果是差不多的,但是作者指出绿线和蓝线所使用的学习率(lr, Learning rate)是不一样的,如果直接将蓝线的学习率拿过来使用得到的效果可能如橙线所示,也就是说需要进行好好调参。
2、位置编码
作者也做了很多的消融实验,主要是三种
- 1d:就是NLP中常用的位置编码,也就是本文从头到尾都在使用的位置编码
- 2d:比如1d中是把一个图片打成九宫格,用的是1到9的数来表示图像块,2d就是使用11、12、13、21等来表示图像块,这样就跟视觉问题更加贴近,因为它有了整体的结构信息。具体的做法就是,原有的1d的位置编码的维度是d,现在因为横坐标、纵坐标都需要去表示,横坐标有D/2的维度,纵坐标也有D/2的维度,就是说分别有一个D/2的向量去表述横坐标和纵坐标,最后将这两个D/2的向量拼接到一起就又得到了一个长度为D的向量,把这个向量叫做2d的位置编码
- relative positional embedding(相对位置编码):在1d的位置编码中,两个patch之间的距离既可以用绝对的距离来表示,又可以用它们之间的相对距离来表示(文中所提到的offset),这样也可以认为是一种表示图像块之间位置信息的方式
但是这个消融实验最后的结果也是:三种表示方法的效果差不多,如下图所示:
- No Pos表示不加任何的位置编码,效果不太好,但也不算特别差。transformer根本没有感知图片位置的能力,在没有位置编码的情况下,还能够达到61的效果其实已经相当不错了
- 对比以上三种位置编码的形式发现,所有的performance都是64,没有任何区别
- 对此作者给出了他认为合理的解释,他所做的Vision Transformer是直接在图像块上做的,而不是在原来的像素块上做的,因为图像块很小,14×14,而不是全局的那种224×224,所以在排列组合这种小块或者想要知道这些小块之间相对位置信息的时候还是相对比较容易的,所以使用任意的位置编码都无所谓
通过以上的消融实验可以看出,class token也可以使用全局平均池化替换,最后1d的位置信息编码方式也可以用2d或者相对位置编码去替换,但是为了尽可能对标准的transformer不做太多改动,所以本文中的vision transformer还是使用的是class token和1d的位置信息编码方式
transformer encoder
transformer在现在看来是一个比较标准的操作了,作者对于transformer(或者说多头注意力机制)的解释放在附录中了。
作者用整体的公式将整个过程总结了一下,如下图中的公式所示:
- X p X_{p} Xp表示图像块的patch,一共有n个patch,所以有 X p 1 X_{p}^{1} Xp1到 X p N X_{p}^{N} XpN
- E E E表示线性投影的全连接层,得到一些patch embedding
- 得到patch embedding之后,在它前面拼接一个class embedding(Xclass),因为需要用它做最后的输出
- 一旦得到所有的tokens,就需要对这些token进行位置编码,所以将位置编码信息 E p o s E_{pos} Epos也加进去
- Z 0 Z_0 Z0就是整个transformer的输入
- 接下来就是一个循环,对于每个transformer block来说,里面都有两个操作:一个是多头自注意力(MSA,Multi head self attention),一个是MLP。在做这两个操作之前,都要先经过layer norm(也就是公式中的LN),每一层出来的结果都要再去用一个残差连接
- Z l ′ Z_{l}^{'} Zl′就是每一个多头自注意力出来的结果
- Z l Z_{l} Zl就是每一个transformer block整体做完之后出来的结果
- L层循环结束之后将 Z L Z_{L} ZL(最后一层的输出)的第一个位置上的 Z l 0 Z_{l}^{0} Zl0,也就是class token所对应的输出当作整体图像的特征,然后去做最后的分类任务。
归纳偏置
vision transformer相比于CNN而言要少很多图像特有的归纳偏置,比如在CNN中,locality(局部性)和translate equivariance(平移等变性)是在模型的每一层中都有体现的,这个先验知识相当于贯穿整个模型的始终
但是对于ViT来说,只有MLP layer是局部而且平移等变性的,但是自注意力层是全局的,这种图片的2d信息ViT基本上没怎么使用(就只有刚开始将图片切成patch的时候和加位置编码的时候用到了,除此之外,就再也没有用任何针对视觉问题的归纳偏置了)
而且位置编码其实也是刚开始随机初始化的,并没有携带任何2d的信息,所有关于图像块之间的距离信息、场景信息等,都需要从头开始学习
这里也是对后面的结果做了一个铺垫:vision transformer没有用太多的归纳偏置,所以说在中小数据集上做预训练的时候效果不如卷积神经网络是可以理解的
混合模型
既然transformer全局建模的能力比较强,卷积神经网络又比较data efficient(不需要太多的训练数据),所以搞出了一个混合的网络,前面是卷积神经网络,后面是transformer
作者对此做了实验:
- 原先是假设有一个图片,将它打成16×16的patch,得到了196个元素,这196个元素和全连接层做一次操作,最后得到patch
embedding
- 现在不将图片打成块了,就按照卷积神经网络的方式去进行处理,将一整张图输入一个CNN,比如说Res50,最后出来一个14×14的特征图,这个特征图拉直了以后恰好也是196个元素,然后用新的到的196个元素去和全连接层做操作得到新的patch embedding
以上就是两种不同的对图片进行预处理的方式
- 一种是将图片打成patch,然后直接经过全连接层
- 另外一种就是经过一个CNN
因为这两种方式得到的序列的长度都是196,所以后续的操作都是一样的,都是直接输入一个transformer,最后再做分类
遇到更大尺寸图片的时候如何做微调:
之前有工作说如果在微调的时候,能用比较大的图像尺寸(不是用224×224,而是用256×256,甚至更大的320×320,就会得到更好的结果)就能够得到更好的效果
vision transformer也想在更大的尺寸上做微调,但是用一个预训练好的vision transformer其实是不太好去调整输入尺寸的。当使用更大尺寸的图片的时候,如果将patch size保持一致,但是图片扩大了,那么序列长度就增加了,所以transformer从理论上来讲是可以处理任意长度的,只要硬件允许,任意长度都可以。
但是提前预训练好的位置编码有可能就没用了,因为原来的位置编码是有明确的位置信息的意义在里面的,现在图片变大了,如果保持patch size不变的话,patch增多了,比如图片由224×224变成320×320,patch由2242/162变成了3202/162,那么由196变成了400,原来的位置编码也就没用了。
- 这个时候位置编码该如何使用?作者发现其实做一个简单的2d的插值就可以了(使用torch官方自带的interpolate函数就可以完成了)。
- 但是这里的插值也不是想插多长就插多长,当从一个很短的序列变成一个很长的序列时,简单的插值操作会导致最终的效果下降,所以说这里的插值只是一种临时的解决方案,这也算是vision transformer在微调的时候的一个局限性
- 因为使用了图片的位置信息进行插值,所以这块的尺寸改变和抽图像块是vision transformer里唯一用到2d信息的归纳偏置的地方
10. 实验
主要是对比了残差网络、ViT和它们混合模型的表征学习能力
为了了解训练好每个模型到底需要多少数据,在不同大小的数据集上做预训练,然后在很多的数据集上做测试
当考虑到预训练的时间代价(预训练的时间长短)的时候,vision transformer表现得非常好,能在大多数数据集上取得最好的结果,同时需要更少的时间进行训练
最后作者还做了一个自监督的实验,自监督实验的结果虽然没有最好,但是还是可以,还是比较有潜力
- 时隔一年之后,MAE就证明了自监督的方式去训练ViT确实效果很好
数据集的使用方面主要是用了
ImageNet的数据集:
- ImageNet-1k(最常用的有1K个类别、1.3M张图片)
- ImageNet-21k(有21K个类别、14M张图片)
JFT数据集:Google自己的数据集(有3亿张图片)
下游任务全部是做的分类,用的也是比较常用的数据集
- CIFAR
- Oxford Pets
- Oxford Flowers
模型的变体
一共有三种模型,参数如下图所示:
transformer的序列长度其实是跟patch size成反比的,因为patch size越小,切成的块就越多,patch size越大,切成的块就越少,所以当模型用了更小的patch size的时候计算起来就会更贵,因为序列长度增加了
结果:
结果如下图所示,下表是说当它已经在大规模的数据上进行过预训练之后,在左边这一列的数据集上去做fine-tune(微调)的时候得到的表现
- 上表对比了几个ViT的变体和卷积神经网络(BiT和Noisy Student)
- 和BiT做对比的原因是因为bit确实是之前卷积神经网络里做得比较大的,而且也是因为他是作者团队自己本身的工作,所以正好可以拿来对比
- 和noisy student做对比是因为它是ImageNet之前表现最好的方法,它所采用的方法是用pseudo-label(伪标签)去进行self training,也就是常说的用伪标签也取得了很好的效果
- 从上表中可以看出,ViT Huge用比较小的patch 14×14能取得所有数据集上最好的结果。
但是因为这些数值都太接近了,仅仅相差零点几个点或者一点几个点,没有特别大的差距,所以作者觉得没有展示出vision transformer的威力,所以作者就得从另外一个角度来体现vit的优点:因为训练起来更便宜
- 作者所说的更便宜是指最大的vit huge这个模型也只需要训练2500天TPUv3天数,正好bit和noisy student也都是google的工作,也都是用TPUv3训练的,所以刚好可以拿来比较,BiT用了9900天,noisy student用了一万多天,所以从这个角度上来说,ViT不仅比之前BiT和Noisy Student要训练的快,而且效果要好,所以通过这两点可以得出vit真的是比卷积神经网络要好的结论
分析
vision trasformer到底需要多少数据才能训练的比较好?
下图中图三是整个vision trasformer论文最重要的take home message,是作者最想让读者知道的,这张图基本上把所有的实验都快概括了
- 图三表示当时用不同大小的数据集的时候,比如说ImageNet是1.2m,而ImageNet-21k是14m,JFT是300m,当数据集不断增大的时候,resnet和vit到底在ImageNet的fine-tune的时候效果如何
- 图三的主要意思是说,灰色代表bit,也就是各种大小的resnet,最下面表示50,最上面表示152,他所想要展示的是在中间的灰色区域就是resnet能达到的效果范围,剩下的圆点就是各种大小不一的vision transformer
- 在最小的ImageNet上做预训练时,vision transformer是完全不如resnet,vision transformer基本上所有的点都在灰色区域的下面。这说明vision transformer在中小型数据集上做预训练的时候的效果是远不如残差网络的,原因就是因为vision transformer没有使用先验知识(归纳偏置),所以它需要更大的数据去让网络学得更好
- 在ImageNet-21k上做预训练的时候,vision transformer和resnet已经是差不多了,vision transformer基本上所有的点都落在灰色区域内
- 只有当用特别大的数据集JFT-300M时,vision transformer是比bit对应的res152还要高的
总之这个图所要表达的是两个信息:
- 如果想用vision transformer,那么得至少准备差不多和ImageNet-21k差不多大小的数据集,如果只有很小的数据集,还是选择使用卷积神经网络比较好
- 当已经拥有了比ImageNet-21k更大的数据集的时候,用vision transformer就能得到更好的结果,它的扩展性更好一些
其实整篇论文所讲的就是这个scaling(规模大就nb)
图四如下图右图所示,因为作者在图三中要用vision transformer跟resnet做比较,所以在训练的时候用了一些强约束(比如说dropout、weight decay、label smoothing),所以就不太好分析vision transformer模型本身的特性,所以在图四中做了linear few-shot evaluation(在拿到预训练的模型之后,直接把它当成一个特征提取器,不去fine-tune,而是直接拿这些特征做了一个just take a regression就可以了),同时作者选择了few-shot,图示中标出了5-shot,就是在ImageNet上做linear evaluation的时候,每一类随机选取了5个sample,所以这个evaluation做起来是很快的,作者用这种方式做了大量的消融实验
- 图四中横轴表示预训练数据集的大小,这里就使用了JFT,没有用别的数据集,但是他取了一些JFT的子集:10M、30M、100M、300M,这样因为所有的数据都是从一个数据集里面得来的,就没有那么大的distribution gap,这样比较起来模型的效果就更加能体现出模型本身的特质
- 图四中的结果其实跟图三差不多,图中浅灰色的线是res50,深灰色的线是res152,当用很小的预训练的数据集的时候vision transformer是完全比不过resnet的
- 本文给出的解释是因为缺少归纳偏置和约束方法(weight decay、label smoothing等),所以就导致在10M数据集的情况下vision transformer容易过拟合,导致最后学到的特征不适合做其他任务,但是随着预训练数据集的增大,vision transformer的稳健性就提升上来了
- 但是因为这里的提升也不是很明显,作者也在最后一段写了如何用vision transformer去做这种小样本的学习是一个非常有前途的方向
由于vision transformer这篇论文之前说了,它的预训练比用卷积神经网络便宜,所以这里就需要做更多的实验来支持它的论断,因为大家对transformer的印象都是又大又贵,很难训练,下图图五中画了两个表
- 左图的average-5就是他在五个数据集(ImageNet real、pets、flowers、CIFAR-10、CIFAR-100)上做了evaluation,然后把这个数字平均了
- 因为ImageNet太重要了,所以作者将ImageNet单独拎出来又画了一张表,如右图所示
- 但是其实这两张表的结果都差不多
- 蓝色的圆点表示vit
- 灰色的圆点表示resnet
- 橙色的加号表示混合模型(前面是卷积神经网络,后面是transformer)
- 图中大大小小的点就是各种配置下大小不一样的vision transformer的变体,或者说是resnet的变体
- 左右两张图中所有的模型都是在JFT 300M数据集上训练的,作者这样训练的目的不想让模型的能力受限于数据集的大小,所以说所有的模型都在最大的数据集上做预训练
上图中几个比较有意思的现象:
- 如果拿蓝色的圆圈所表示的vit去跟灰色圆圈的resnet作比较,就会发现,在同等计算复杂度的情况下,一般transformer都是比resnet要好的,这就证明了:训练一个transformer是要比训练一个卷积神经网络要便宜的
- 在比较小的模型上面,混合模型的精度是非常高的,它比对应的vision transformer和resnet都要高,按道理来讲,混合模型都应该是吸收了双方的优点:既不需要太多的数据去做预训练,同时又能达到跟vision transformer一样的效果
- 但是当随着模型越来越大的时候,混合模型就慢慢的跟vision transformer差不多了,甚至还不如在同等计算条件下的vision transformer,为什么卷积神经网络抽出来的特征没有帮助vision transformer更好的去学习?这里作者对此也没有做过多的解释,其实怎么预处理一个图像,怎么做tokenization是个非常重要的点,之后很多论文都去研究了这个问题
- 如果看整体趋势的话,随着模型的不断增加,vision transformer的效果也在不停地增加,并没有饱和的现象(饱和的话一般就是增加到一个平台就不增加了),还是在不停的往上走的。但是但从这个图中来看的话,其实卷积神经网络的效果也没有饱和
可视化
分析完训练成本以后,作者也做了一些可视化,希望通过这些可视化能够分析一下vit内部的表征
- vision transformer的第一层(linear projection layer,E),下图展示了E是如何embed rgb value,这里主要展示了头28个主成分,其实vision transformer学到了跟卷积神经网络很像,都是这种看起来像gabor filter,有颜色和纹理,所以作者说这些成分是可以当作基函数的,也就是说,它们可以用来描述每一个图像块的底层的结构
位置编码是如何工作的?
如下图所示,这张图描述的是位置编码的相似性,数字越大相似性越高(-1到1,cosine similarity),横纵坐标分别是对应的patch,如果是同一个坐标,自己和自己相比,相似性肯定是最高的。从图中可以发现,学到的位置编码是可以表示一些距离信息的,同时它还学习到了一些行和列的规则,每一个图像块都是同行同列的相似性更高,也就意味着虽然它是一个1d的位置编码,但是它已经学到了2d图像的距离概念,这也可以解释为什么在换成2d的位置编码以后,并没有得到效果上的提升,是因为1d已经够用了
- 最后作者想看一下自注意力是否起作用了,之所以想用transformer,就是因为自注意力的操作能够模拟长距离的关系。在NLP中,一个很长的句子里开头的一个词和结尾的一个词也能互相有关联,类比在图像里很远的两个像素点也能够做自注意力,所以作者就是想看一下自注意力到底是不是像期待的一样去工作的。下图展示的是vit large 16这个模型,vit large有24层,所以横坐标所表示的网络深度就是从0到24,图中五颜六色的点就是每一层的transformer block中多头自注意力的头,对于vit large来说一共有16个头,所以每一列其实有16个点。纵轴所表示的是mean attention distance(平均注意力的距离:假如说图上有两个点,平均注意力距离表示的就是这两个点真正的像素之间差的距离乘以他们之间的attention weights,因为自注意力是全局都在做,所以说每个像素点跟每个像素点都会有一个自注意力权重,平均注意力的距离就能反映模型到底能不能注意到两个很远的像素)。图中的规律还是比较明显的:前几层中,有的自注意力中的头注意的距离还是挺近的,能达到20个像素,但是有的头能达到120个像素,这也就证明了自注意力真的能够在网络最底层,也就是刚开始的时候就已经能够注意到全局上的信息了,而不是像卷神经网络一样,刚开始第一层的receptive field(感受野)非常小,只能看到附近的一些像素;随着网络越来越深,网络学到的特征也会变得越来越高级,越来越具有语义信息;大概在网络的后半部分,模型的自注意力的距离已经非常远了,也就是说它已经学到了带有语义性的概念,而不是靠邻近的像素点去进行判断
- 为了验证上面所得到的结论,作者又画了另外一个图,如下图所示。图中是用网络中最后一层的out token所作的图,从图中可以发现,如果用输出的token的自注意力折射回原来的输入图片,可以发现模型确实是学习到了这些概念。对于全局来说,因为输出的token是融合了所有的信息(全局的特征),模型已经可以关注到与最后分类有关的图像区域
在文章的最后,作者还做了如何用自监督的方式去训练vision transformer的测试
这篇论文算上附录22页,在这么多的结果中,作者把别的结果都放到了附录里,而把自监督放到了正文中,可见它的重要性。它之所重要主要是因为在nlp领域,transformer这个模型确实起到了很大的推动作用,但另外一个真正让transformer火起来的原因其实是大规模的自监督训练,二者缺一不可。NLP中的自监督无非就是完形填空或者是预测下一个词,但是因为这篇论文主要仿照的是BERT,所以作者就想能不能也借鉴BERT这个目标函数去创建一个专属于vision的目标函数,BERT使用的就是完形填空(mask language modeling,给定一个句子,然后将一些词mask掉,然后通过一个模型,最后将它预测出来),同理,本文就仿造了一个mask patch prediction,意思就是给定一张图片,将它打成很多patch,然后将某些patch随机抹掉,通过这个模型以后,再将这些patch重建出来。
但是最后vit base 16在ImageNet只能达到80的左右的准确率,虽然相对于从头来训练vision transformer已经提高了两个点,但是跟最好的有监督的训练方式比差了4个点,所以作者将跟对比学习的结果当作是未来的工作(对比学习是20年CV圈最火的人们话题,是所有自监督学习中表现最好的,所以紧接着vit MoCo v3和DINO就出现了,这两篇论文都是用对比学习的方式去训练了一个vision transformer)
11. 评价
这篇论文写的还是相当简洁明了的,在有这么多内容和结果的情况下,做到了有轻有重,把最重要的结果都放到了论文里,图和表也都做的一目了然
从内容上来说,可以从各个角度来进行分析、提高或者推广vision transformer
如果从任务角度来说,vision transformer只是做了分类,所以还可以拿他去做检测、分割甚至别的领域的任务
如果从改变结构的角度来讲,可以去改变刚开始的tokenization,也可以改中间的transformer block,后来就已经有人将自注意力换成了MLP,而且还是可以工作得很好(甚至有一篇论文叫做mataformer,他认为transformer真正工作的原因是transformer这个架构而不是因为某些算子,所以他就将自注意力直接换成了池化操作然后发现,用一个甚至不能学习的池化操作(文中提出了一个pool former模型)也能在视觉领域取得很好的效果),所以在模型的改进上也大有可为
如果从目标函数来讲,可以继续采用有监督,也可以尝试很多不同的自监督训练的方式
最重要的是vit打破了NLP和CV之间的鸿沟,挖了一个更大的多模态的坑,可以用它去做视频、音频,甚至还可以去做一些基于touch的信号,也就是说各种modality的信号都可以拿来使用