87.7%准确率!CvT:将卷积引入视觉Transformer

点击下方卡片,关注“CVer”公众号

AI/CV重磅干货,第一时间送达

本文转载自:AI人工智能初学者

CvT: Introducing Convolutions to Vision Transformers

论文:https://arxiv.org/abs/2103.15808

代码:https://github.com/leoxiaobin/CvT

本文将卷积引入视觉Transformer提出CvT,在ImageNet拿下87.7% Top-1准确率!(在ImageNet-22k上预训练)与其他视觉Transformer和ResNet相比,具有更少的参数和更低的FLOPs,在垂直任务应用中,也保持性能优势!代码即将开源!
作者单位:麦吉尔大学, 微软云+AI

1 简介

1.1 全文简述

在本文中介绍了一种称为卷积视觉Transformer(CvT)的新体系结构,该体系结构通过将卷积引入ViT中来产生两种设计结合的最佳效果,从而提高了视觉Transformer(ViT)的性能和效率。

CvT主要是通过2个主要改进完成的:包含卷积Token嵌入的Transformer层次结构,以及利用卷积映射的卷积Transformer Block。这些变化将卷积神经网络(CNN)的特性引入到ViT架构中(即平移、缩放和旋转不变性),同时保持了Transformers的优点(即动态注意力,全局Context和更好的泛化)。

图1 CvT在ImageNet实验对比图

通过进行广泛的实验来验证CvT的有效性,实验表明该方法与ImageNet-1k上的其他视觉Transformer和ResNet相比,具有更少的参数和更低的FLOPs,可实现最先进的性能。

此外,在较大的数据集(例如ImageNet-22k)上进行预训练并针对垂直任务进行微调时,可以保持性能提升。CvT-W24在ImageNet-22k上进行了预训练,在ImageNet-1k val集合上获得了87.7%的top-1精度。

最后,实验结果表明,位置编码是现有Vision Transformer的关键组成部分,可以在模型中删除进而简化了高分辨率视觉任务的设计。

1.2 相关总结

近几年,Transformer在自然语言处理(NLP)的任务领域中得到了广泛的应用。而Vision Transformer(ViT)则是近来第一个完全依赖于Transformer架构的计算机视觉模型,同时获得具有竞争力的图像分类性能。ViT设计通过对语言的理解,以最小的修改来适应Transformer架构。

首先,图像被分割成离散的不重叠的小块(例如16×16);

然后,将这些小块作为Token(类似于NLP中的Token),用一种特殊的位置编码来表示空间信息,然后输入到标准Transformer层中建模全局关系,进而进行分类。

尽管Vision Transformer在一定程度上取得了成功,但在较小的数据量上训练时,其性能仍然低于类似规模的卷积神经网络(如ResNets)。一个可能的原因可能是ViT缺乏CNN架构中固有的特性,而这些特性使CNN适合解决视觉任务

例如,图像具有很强的二维局部结构:空间相邻像素通常是高度相关的。CNN的架构通过使用局部感受野、共享权值和空间子采样来强制捕获这个局部结构,从而也实现了一定程度的平移、尺度和旋转不变性。此外,考虑到不同复杂程度的局部空间Context,卷积核的层次结构学习是从简单的低级边缘和纹理到高级语义的学习模式。

1.3 本文出发点

在本文中作者假设卷积可以有策略地引入到ViT结构之中以提高模型的性能和鲁棒性同时保持较高的计算和内存效率。为了验证假设作者提出了一种新的架构,称为Convolutional vision Transformer(CvT),它将卷积合并到Transformer中,在(FLOPs)和参数方面都是高效的。

CvT设计在ViT架构的2个核心部分引入了卷积:

首先,将Transformer划分为多个阶段,形成一个分层结构的Transformer。每个阶段的开始由一个卷积Token嵌入组成,该卷积Token嵌入在一个二维重塑的Token映射上进行卷积操作(即,将Flattened的Token序列重塑回空间网格),然后是Layer Normalization。这个操作使得模型不仅可以捕获局部信息,而且还可以逐步减少序列长度,同时在不同阶段增加Token特征的维数,实现空间下采样,同时增加特征映射的数量。

其次,将Transformer模块中每个Self-Attention Block之前的线性投影替换为卷积投影,该卷积投影在二维重塑的Token映射上采用 深度可分卷积。这使得该模型在注意力机制中能够进一步捕获局部空间语义信息,减少语义歧义。它还允许管理计算复杂度,因为卷积的Stride可以用于对键和值矩阵进行子采样,以提高4倍或更多的效率,同时最小化性能的损失。

2 相关工作

最近,基于Transformer的体系结构被认为是一个可替代卷积神经网络(CNNs)的架构,它可以被用到很多CV的垂直领域,如分类、目标检测、分割、图像增强、图像生成、视频处以及3D点云处理等。

2.1 ViT

ViT是第一个证明当数据足够大(如ImageNet-22k, JFT-300M)时,纯Transformer架构可以在图像分类方面达到最先进的性能(如ResNets, EfficientNet)。具体来说,ViT将每幅图像分解成一组固定长度的token序列(即非重叠patches),然后应用多个标准的Transformer(Multi-Head Self-Attention module, MHSA)和位置前馈模块(position-wise feedforward module, FFN)对这些token进行建模。

DeiT进一步探索了ViT的数据高效训练和蒸馏。在这项工作中,研究了如何结合CNN和Transformer,并以一种有效的方式建模局部和全局依赖的图像分类。

为了更好地模拟视觉Transformer的局部Context,一些并行工作也引入了设计变更。

条件位置编码视觉Transformer(CPVT)用条件位置编码(CPE)取代了ViT中预定义的位置嵌入,使Transformer能够处理任意大小的输入图像而无需插值;

Transformer In Transformer(TNT)既利用处理贴片嵌入的外部Transformer块,又利用模拟像素嵌入之间关系的内部Transformer,对贴片级和像素级表示进行建模;

Token To Token(T2T)主要通过将滑动窗口中的多个令牌连接为一个Token来改进ViT中的Token化。然而,该操作与卷积有根本的不同,尤其是在规范化细节方面,而且多个标记的连接大大增加了计算和内存方面的复杂性;

PVT为Transformer引入了一种多级设计(不含卷积),类似于CNNs中的多尺度,有利于密集预测任务。

表1 Vision Transformer对比

与以上的工作相比,本文工作的目标是通过引入卷积,在图像域特定的归纳偏差,以达到最好的Transformer结构。表1显示了上述具有代表性作品和本文CvT在位置编码的必要性、Token嵌入类型、映射类型和Backbone中的Transformer结构方面的主要区别。

2.2 向CNN引入Self-Attention

Self-Attention在cnn视觉任务中得到了广泛的应用。在这些工作中,Non-Local Network的设计是为了通过全局Attention来捕捉长期依赖关系。Local Relation Networks 根据local windows内像素/特征之间的组成关系(相似度)来进行权值聚合,而卷积层则在空间相邻的输入特征上采用固定的权值聚合。这种自适应权值聚合将几何先验引入到网络中,这对识别任务很重要。

最近,BoTNet提出了一种简单而强大的Backbone,它只是在一个ResNet的最后3个Bottleneck block中用全局的Self-Attention代替了空间卷积,在图像识别方面取得了不错的效果。

相反,本文的工作执行了一个相反的研究方向:将卷积引入到Transformer之中。

2.3 向Transformer引入CNN

在NLP和语音识别中,卷积被用来修改Transformer Block,或者用卷积层代替Multi-Head Attentions,亦或是以并行或顺序的方式增加额外的卷积层,以捕获局部关系。之前的其他工作提出通过残差连接将注意力映射传播到后续层,这首先通过卷积进行转换。

不同于前面的工作,本文推荐在Vision Transformer的2个主要部分引入卷积:

  • 首先,使用卷积投影操作取代现有的Position-wise线性投影;

  • 其次,类似于CNN,使用分层多级结构和不同分辨率的2D Reshaped Token Maps。

通过以上2个独特的网络设计相对于以前的工作有了显著的性能和效率的提升。

3 CvT 核心原理

图2 CvT架构的PipLine

CvT的整体Pipline如图2所示。在ViT架构中引入了2种基于卷积的操作,即卷积Token嵌入和卷积映射。如图2(a)所示,本文借鉴了CNN的多阶段层次设计,共采用了3个阶段:

  • 首先,输入图像经过卷积Token嵌入层,卷积层是将重构Token的重叠块卷积到二维空间网格作为输入(重叠程度可通过步长来控制)。对Token应用额外的LN(层归一化)。这允许每个阶段逐步减少Token的数量(即特征分辨率),同时增加Token的宽度(即特征维度),从而实现空间下采样和增加R的丰富度。与其他先前的基于变压器的架构不同,我们不将嵌入令牌的额外位置相加。

  • 然后,叠加一些卷积Transformer Block组成每个阶段的残差部分。图2(b)展示了卷积Transformer Block的架构,其中使用深度可分离的卷积运算,称为卷积映射,分别用于查询、键和值的嵌入,而不是ViT中标准的位置线性映射。此外,分类Token只在最后阶段添加。

  • 最后,在最后阶段输出的分类标记上使用MLP来预测结果。

3.1 卷积Token Embedding

CvT中的卷积操作旨在通过一种类似CNNs的多级层次方法从Low-level到High-Semantic模拟局部空间Context。

给定一个2D图像或者从第 阶段得到的2D-reshaped Token Map输出作为第 阶段的输入,这里通过学习一个函数 映射到一个新的通道大小为 的Token 的二维卷积核大小为 ,stride为 ,padding为p。

新的Token Map 的高度和宽度为:

然后将 平铺成大小为 ,并通过LN进行归一化,以便输入到第i stage的subsequent Transformer blocks中。

卷积Token嵌入层允许通过改变卷积运算的参数来调整每个阶段的Token特征维数和数量。通过这种方式,在每个阶段逐步减少Token序列长度,同时增加Token特征维数。这使得Token能够在越来越大的空间上表示越来越复杂的视觉模式,类似于CNN的特征层。

3.2 注意力的卷积映射

卷积投影层的目标是实现对局部空间Context的额外建模,并通过允许K和V矩阵的欠采样来提高效率。

从根本上说,提出的Transformer块具有卷积映射是对原Transformer块的推广。而之前的工作尝试在Transformer中添加额外的卷积模块对于语音识别和自然语言处理,它们导致更复杂的设计和额外的计算成本。相反,本文建议用具有深度可分离卷积的Multi-Head Self-Attention(MHSA)代替原来的位置线性映射进而形成卷积映射层

1 复现细节

图3(a) ViT中的线性映射

图3(a)显示了ViT中使用的原始位置线性映射

图3(b) 卷积映射

图3(c) 压缩卷积映射

图3(b)显示了本文提出的s×s卷积投影。如图3(b)所示,首先将Token重塑为2D Token Map。接下来,使用核大小为s的深度可分离卷积层来实现卷积映射。最后,映射后的Token被平展为1D以供后续处理。这可以表述为:

其中 是第 层Q/K/V矩阵的Token输入, 是卷积投影之前的未扰动Token,Conv2d是深度可分离卷积,其实现方式为:Depth-wise Conv2d—>BatchNorm2d—>Point-wise Conv2d,s为卷积核大小。新的卷积映射层Transformer块是对原有Transformer块设计的推广。原始的基于位置的线性映射层可以使用内核大小为1×1的卷积层来实现。

2 效率考虑

本文设计的卷积投影层有2个效率上的好处:

  • 首先,利用了有效的卷积。直接使用标准的 卷积进行卷积映射需要 个参数和 的FLOPs,其中C是Token通道维数,T是要处理的Token数量。相反,将标准的 卷积分解为深度可分离的卷积。这样,与原始的位置线性映射相比每个卷积映射只会引入额外的 个参数和 的FLOPs,相对于模型的总参数和FLOPs,这些都可以忽略。

  • 其次,利用提出的卷积投影来减少MHSA操作的计算成本。 卷积投影允许通过使用大于1的步长来减少Token的数量。图3(c)显示了卷积投影,其中的key和value投影是通过步长大于1的卷积进行下采样的,文章对key和value投影使用步长2,而对query保持不变使用步长1。这样,key和value的token数量减少了4倍,以后的MHSA操作计算成本减少了4倍。这带来了最小的性能损失,因为图像中的邻近像素/补丁往往在外观/语义上有冗余。另外,所提出的卷积投影的局部Context建模可以弥补分辨率降低所带来的信息损失。

3.3 方法的讨论

1 删除位置嵌入

对每个Transformer块引入卷积映射结合卷积Token嵌入能够通过网络建模局部空间关系。这个内置属性允许在不影响性能的情况下删除网络中嵌入的位置,从而简化了具有可变输入分辨率的视觉任务的设计。

2 与当前一些工作的关系

最近,另外两个相关的工作也提出通过将CNN的元素整合到Transformer中来改进ViT。Tokensto-Token ViT实现渐进的Token化,然后使用基于Transformer的Backbone,其中Token的长度是固定的。

相比之下CvT通过在每个阶段包含卷积Token嵌入和卷积Transformer块的多阶段过程来实现渐进的Token化。随着Token的长度在每一阶段的减少,Token的宽度(特征维度)可以增加,允许在每个特征空间分辨率上表示的丰富度增加。

此外,T2T将相邻的Token连接成一个新的Token,导致内存和计算的复杂性增加,而CvT使用卷积Token嵌入直接执行Context学习,而无需连接,同时提供了控制步长和特征维数的灵活性。为了管理复杂性,T2T必须考虑一个深度狭窄的架构设计,其隐藏维度和MLP规模小于后续主干中的ViT。相反,CvT通过用卷积投影替换位置相关的线性投影来更改先前的Transformer模块。

金字塔ViT(PVT)克服了将ViT移植到各种密集预测任务中的困难。在ViT中,输出的特征图只有一个尺度分辨率较低。此外,即使对于普通的输入图像大小,计算和存储成本也相对较高。为了解决这个问题,PVT和CvT从CNN到Transformer结构都采用了金字塔结构。PVT只对投影中的特征映射或key/value矩阵进行空间子样本,而CvT采用了带大步的卷积来实现这一目标。实验表明局部邻近信息的融合对性能有重要的影响。

4 实验结果

4.1 模型架构

表2 基于ImageNet分类的架构

输入的图像大小默认为224×224。Conv. Embed.:卷积Token嵌入。Conv. Proj.:卷积映射。 为第i个MHSA模块中Head的个数和嵌入特征维数。 是第i个MLP层的特征维度的扩展比。

表3 不同架构在ImageNet、ImageNet Real和ImageNet V2上的准确性

与基于CNN的模型相比,CvT进一步缩小了基于Transformer模型的性能差距。最小的模型cpt-13具有20M参数和4.5G FLOPs,在ImageNet top-1精度上比大型的ResNet-152模型高出3.2%,而ResNet-151的参数是cpt-13的3倍。

此外,当使用更多数据时,在ImageNet-22k上预训练的宽模型CvT-W24*达到在没有额外数据训练的情况下在ImageNet上获得了87.7%的Top-1精度,以相似的模型参数和FLOPs数量比最佳模型ViT-L/16高出2.5%。

论文PDF和代码下载

后台回复:CvT,即可下载上述论文PDF和代码

后台回复:CVPR2021,即可下载CVPR 2021论文和代码开源的论文合集

后台回复:Transformer综述,即可下载最新的两篇Transformer综述PDF

重磅!Transformer交流群成立

扫码添加CVer助手,可申请加入CVer-Transformer 微信交流群,方向已涵盖:目标检测、图像分割、目标跟踪、人脸检测&识别、OCR、姿态估计、超分辨率、SLAM、医疗影像、Re-ID、GAN、NAS、深度估计、自动驾驶、强化学习、车道线检测、模型剪枝&压缩、去噪、去雾、去雨、风格迁移、遥感图像、行为识别、视频理解、图像融合、图像检索、论文投稿&交流、PyTorch和TensorFlow等群。

一定要备注:研究方向+地点+学校/公司+昵称(如Transformer+上海+上交+卡卡),根据格式备注,可更快被通过且邀请进群

▲长按加小助手微信,进交流群

▲点击上方卡片,关注CVer公众号

整理不易,请给CVer点赞和在看

  • 8
    点赞
  • 81
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 要输出保留一位小数的百分比,可以使用Python的字符串格式化方法来实现。具体来说,可以使用“%”操作符和格式控制符“%.1f%%”来实现,其中“%.1f”表示要保留一位小数,后面的“%”表示要输出百分比符号。下面是一个示例代码: ```python num = 0.6789 percent = num * 100 print("百分比为:%.1f%%" % percent) ``` 这个代码将输出:百分比为:67.9% ### 回答2: 在Python中,我们可以使用字符串的格式化来输出百分比并只保留一位小数。 假设有一个变量x代表百分比的值,我们可以使用以下代码来格式化输出: percentage = 0.745 formatted_percentage = "{:.1%}".format(percentage) print(formatted_percentage) 上述代码中,"{:.1%}"中的"{}"表示要替换的值,".1"表示保留一位小数,"%"表示以百分比的形式输出。 执行上述代码,将会输出"74.5%",这样就只保留了一位小数的百分比值。 另外,如果我们需要将格式化后的百分比值作为字符串进行处理,我们也可以直接将其赋值给一个变量,例如: formatted_percentage = "{:.1%}".format(percentage) result = "百分比值为:" + formatted_percentage print(result) 上述代码中,我们使用变量result将格式化后的百分比值添加到字符串中,并进行输出。输出结果为"百分比值为:74.5%"。这样我们就可以对格式化后的百分比值进行进一步的处理。 总结起来,通过使用字符串的格式化功能,我们可以很方便地输出百分比并只保留一位小数。 ### 回答3: 在 Python 中,我们可以使用字符串的格式化方法 `format()` 或者 f-string 来输出百分比并保留一位小数。 方法一:使用 `format()` ```python percentage = 0.87654321 formatted_percentage = "{:.1%}".format(percentage) print(formatted_percentage) ``` 在这个例子中,通过 `"{:.1%}"` 这个格式字符串,我们指定了输出的百分比格式。其中,`{:.1}` 表示只保留一位小数,`%` 表示输出为百分比形式。最终输出结果为 `87.7%`。 方法二:使用 f-string ```python percentage = 0.87654321 formatted_percentage = f"{percentage:.1%}" print(formatted_percentage) ``` 通过在字符串前面加上 `f` 表示这个字符串是一个 f-string,我们可以直接在大括号中指定要格式化输出的变量和格式,最终结果与使用 `format()` 方法相同。 以上两种方法都可以用于输出百分比并保留一位小数。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值