- 论文链接: https://arxiv.org/abs/2010.11929
- 论文原文代码:https://github.com/google-research/vision_transformer
- timm链接:https://github.com/rwightman/pytorch-image-models
作者团队证明了脱离神经网络,使用一个纯的transformer结构也能在图像分类任务上表现的很好。甚至当我们在大规模数据集(google 的JTF300M或者Imagenet21K)上进行预训练然后在小数据集上进行微调时,它的表达效果甚至超过了传统的卷积神经网络。并且随着数据集的扩大vision transformer还没有出现过饱和的现象。
作者将transformer结构去除掉decoder部分后经过改进将其运用到视觉领域。vision transformer模型结构主要包括三部分
patch embeding 部分
transformer encoder部分
MLP head部分
论文中的模型框架图:
先了解, 熟悉一下训练流程(后面会对每一个部分进行解释):
patch embeding将一个CHW
格式的图片数据处理成transformer所需要的num_patchs x embed_dim
格式的序列,首先将一张图片拆分为若干个p x p x 3
大小的图像块(p为patch size),再对每个图象块经过线性映射层产生transformer所需要的序列,以ViT-B/16
为例看下图(自己画的)
在代码中则是直接采用kernelsize为p(ViT-B/16中为16),stride为也为p,outchannel为pxpx3
的卷积来进行图像切分和线性映射的实现,卷积后输出的结果形状为(n, embed_dim, HW/p^2, HW/p^2)
, 在VIT-B/16中为14,再对卷积产生的结果进行拉直,换位。再concate
上cls token
后与position embeding对应元素相加得到patch embeding最后的结果。过程中的cls token
和position embeding
请看下文。
对于一个标准的transformer需要的输入是一个二维的序列,而我们的图片则是一个由像素组成的三维向量,那么如何将一张图片的数据转化为transformer中的序列呢?
作者在论文中提到:
224x224
,所需要的计算时间开销过大vision transformer使用了第四种方式,第2,3种方式由于操作的特殊性无法在现代硬件技术上进行加速计算,无法构建大的网络模型来解决问题。
作者参照标准的transformer,采用与卷积不同的方式,对图片切分后产生的图像块进行编码,通过构建一个可学习的position embeding向量来表示图片的空间信息并与原有的数据逐元素相加,这里作者分别实验了几种不同的编码方式和不采用position embeding分别进行对比:
作者还实验了分在进入Encoder前加入position embeding, 在每层Encoder前都加入position embeding, 添加一个可学习的position embeding到每层网络的开始。
最终效果如图:
从中可以看出不同的编码方式产生的效果差别不大,而不采用位置编码则效果不好,同时作者推测造成这种不同的编码方式产生近乎相同的效果的原因是:ViT将图片划分成了图象块,这些图像块的数量相对与原来图像中的像素点的数量来说很少,所以他们之间的位置信息很容易学习得到。甚至对于不同的超参数产生的学习产生的效果也很相似(如下图)
作者为了尽量与原来的transformer保持一致,也构造了一个cls token向量,与原来的patch embeding堆叠到一起(concate)用来表示网络学习得到的结果,最后只将cls token 送入MLP Head来产生分类结果,同时还实验了不采用cls token,直接对最后一层输出的token 进行全局平均池化产生的效果也都差不多。
由于每个encoder layer并没有改变每个序列(token)的长度,所以直接由多个encoder layer堆叠起来组成了transformer encoder部分,而encoder layer部分主要由MSA(Multi-Head-Attention ), LN(Layer-Norm)和MLP组成。
一个MSA是由多个self-Attention多用在同一个token上组成,这里给出百度飞桨朱欤老师所画的图来解释说明课程链接
对每一个图像块形成的image token分别由三个线性层得到q, k, v 三个部分其中:
k:表示token的key值
q:query分别对其他的image token产生的key值进行对应元素相乘来得到s,在经过scale归一化和softmax之后得到Attention的权重矩阵(Attention Weight)
V:表示token经过线性层后提取出来的信息,与Attention Weight相乘后得到self-Attention的结果
个人对于self-Attention的理解:
通过产生的q和k相乘后进行scale和softmax归一化来计算不同位置图片块之间的相似度从而构建了Mask(掩码)的方式给予一个特征权重,相似度大的部分权重越大,相似度小的部分权重则越小
再使用这个特征的权重矩阵与原来的token经过线性层后提取出来的特征对应元素相乘,增加模型对相似度高的部分的表征能力(也叫做注意力)
而MSA则是分别使用多个self-Attention对token进行处理(注意:每个self-Attention作用在token的不同地方没有重叠,就是将输入的token平均分成了若干个部分给self-Attention来处理), 再对每一个self-Attention处理完成后的结果按顺序组合拼接即可。
这部分没理解的,具体可以看另外一位大佬写的博客:链接
Layer Norm相比于Batch Norm不同的地方在于Batch Norm是对卷积神经网络中间的特征图每一层做归一化,而Layer Norm则是对整个token(相当与卷积神经网络特征图的整体)做归一化,在框架中都有相应的api来实现
MLP层实际上是由前后两层线性层中间加上GELU激活函数和DropOut层组成,这里需要注意的是中间的两个线性层中的第一个将token的长度放大为原来的4倍,后一个线性层则将长度重新恢复。
前面所述ViT为了参照标准的transformer只将cls token作为模型最终的处理结果来送入MLPHead中。而MLP Head中包含了两种结构,当进行预训练的时候,MLPHead部分有两个线性层,而在中小型数据集上微调时则为一个线性层。
注意:在经过transformer encoder之后的token先进行了一次Layer Norm最后才送入MLP Head, 在论文框架图中并未给出
作者经过实验发现transformer在中小型数据集上的表现效果实际上是不如卷积神经网络的,但是如果将transformer在大规模数据集上进行预训练然后在中小数据集进行微调时效果超过了卷积神经网络。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hLkID8Oe-1642319897818)(/home/shier/Pictures/ViT/Inductive.png)]
论文中表示造成这种结果的原因是卷积神经网络存在归纳偏置(Inductive Bias),这种归纳偏置具有平移等变性(translation equivariance)、局部性(locality)
translation equviriance : 无论是先做卷积还是先做平移最终将产生相同的结果
locality:图片在做卷积时,因为步长的原因,中间存在有重叠的部分,相邻的区域会有相同的特征
个人理解(仅供参考,可能存在错误):
当存在两张图片,图片中物体相同而处于图片不同位置时,卷积神经网络因为归纳偏置产生的效果相似,而transformer需要学习不同patch之间的位置信息,学习的困难程度将会增加。
由于transformer中缺乏卷积神经网络中的归纳偏置, 作者提出可以选择一个卷积神经网络模型来当作transformer的特征提取器,对卷积神经网络模型产生的特征图进行patch embeding。论文中选择了resnet50进行实验,此时的resnet50是进行了修改之后的resnet50。将模型中的Batch Norm层替换成了Group Norm, 传统的卷积替换成了stdconv, 并且去除了resnet50中的stage4,将stage4中的结构添加到了stage3中来当作ViT的特征提取器。
由于vision transformer中图片的分辨率大小和patch size的大小会影响patch embeding之后的序列长度,就是说如果想直接在中小型数据集上进行微调时扩大输入图片的像素来增加训练效果是不行的,这会增大原有的序列长度,导致预训练的成果失效,不过我们可以在原有的序列上进行2D的线性插值来应对这个问题,不过这种解决方式还是会造成效果降低。
参考:
csdn霹雳吧啦_wz:https://blog.csdn.net/qq_37541097/article/details/118242600
csdn霹雳吧啦_wz:https://blog.csdn.net/qq_37541097/article/details/117691873
知乎:https://zhuanlan.zhihu.com/p/356155277
飞桨:https://aistudio.baidu.com/aistudio/education/group/info/25102
官方论文: https://arxiv.org/abs/2010.11929
论文代码:https://github.com/google-research/vision_transformer
哔哩哔哩视频:https://www.bilibili.com/video/BV15P4y137jb?spm_id_from=333.1007.top_right_bar_window_custom_collection.content.click
本贴写于:2022年1月16日。完。