ViT-Adapter:Vision Transformer Adapter for Dense Predictions

ViT-Adapter:Vision Transformer Adapter for Dense Predictions

请添加图片描述

论文地址:https://arxiv.org/abs/2205.0853

在这里插入图片描述

SL是监督学习,SSL是自监督学习

之前是使用的针对特定任务进行设计的Vision-Specific Transformer,先对图像形态进行预训练,然后在不同的下游任务中进行微调。而作者提出的是使用ViT预训练,并使用image、video、text等多个信息进行学习,在微调时,对原有ViT添加了Adapter,从而引入图像的先验信息,并且该模型引入了视觉特定的感应偏差,从而提高了ViT在密集分类任务中的性能。其最终在实验中取得了较好的效果,并在语义分割方向,在ADE20K val上建立了60.5mIOU的新纪录,比SwinV2-G高了0.6个百分点。

1.模型架构

模型架构大体分为两个部分:分别为Vision Transformer部分和ViT-Adapter部分。

ViT主干部分,分为Patch Embedding和N个Block模块(N为自己确定把ViT分为几块)。

ViT-Adapter部分,分为Spatial Prior部分和N个Injector(注射器)和Extractor(提取器),对应N个Block。其中Spatial Prior模块用来捕捉输入图像的空间特征。Spatial Feature Injector来为ViT提供空间先验,Multi-Scale Feature Extracor从ViT中提取层次结构特征。

1.Spatial Prior使用一个主干层次模块获取不同分辨率大小的特征图F1,F2,F3,并对它们进行Flatten和Concat操作生成一个序列特征Fsp1

2.对于Injector注射器,将Fspi作为key和value,来自ViT的序列特征Fviti作为query,进行注意力运算得到的序列新特征,并返回给ViT。

3.对于Extractor提取器,将Fvisi经过ViT的block后得到的Fvisi+1作为key和value,将空间特征Fspi作为query,进行注意力运算得到新的序列特征进行更新Fspi。并引入了CFFN进行弥补固定尺寸位置嵌入的陷缺,得到Fspi+1

2.ViT-Adapter的具体操作

**Spatial Prior Module:**这个模块是为了构建输入图像局部空间上下文信息。

输入图像经过maxpool和三个卷积操作来获取不同分辨率大小的特征图。其中卷积操作的卷积核大小为3x3,步长为2,并且通道数每次x2,最后经过1x1的卷积核,将三个特征图的通道数都投影到D维(D等于ViT中的P2xC,其中的P是patch的图像大小,P=16,C=3,所以D=768),得到的F1,F2,F3的大小分别为H/8xW/8xD,H/16xW/16xD,H/32xW/32xD,然后使用flatten和concatenate操作得到Fsp1的大小为(HW/82+HW/162+HW/322)x D。

在这里插入图片描述

Spatial Feature Injector:这个模块是用来给ViT主干传递空间先验特征(使用ViT-Adapter获取到的信息)。

对于ViT的第i个block,其输入的主干网络的特征为Fviti,其大小为(HW/162)x D,并作为query,而空间特征为Fspi,其大小为(HW/82+HW/162+HW/322)xD作为key和value,用multi-head cross-attention将空间特征Fspi输入到Fviti中,其中公式为:
F v i t i = F v i t i + γ i A t t e n t i o n ( n o r m ( F v i t i ) , n o r m ( F s p i ) ) F_{vit}^{i} = F_{vit}^{i} +\gamma ^{i} Attention(norm(F_{vit}^{i}),norm(F_{sp}^{i})) Fviti=Fviti+γiAttention(norm(Fviti),norm(Fspi))
得到的Fvit才是真正输入到block中的特征,并且为了减小计算量,论文使用的是deformable attention,一种离线注意力算法,具有线性复杂度。并且yi是一个可学习的向量,用于调整比例。
在这里插入图片描述

**Multi-Scale Feature Extractor:**在Fvit经过block之后,得到Fviti+1,然后将空间特征Fspi作为query,其大小为(HW/82+HW/162+HW/322) x D,将时输入特征设为Fviti+1,其大小为(HW/162 x D),并作为key和value,使用multi-head cross-attention,其计算公式为:
F ^ s p i = F s p i + A t t e n t i o n ( n o r m ( F s p i ) , n o r m ( F v i t i + 1 ) ) \hat{F}_{sp}^{i}=F_{sp}^{i}+Attention(norm(F_{sp}^{i}),norm(F_{vit}^{i+1})) F^spi=Fspi+Attention(norm(Fspi),norm(Fviti+1))
此外,为了弥补固定尺寸位置嵌入的缺陷,作者又引入了一个convolutional feed-forward network(CFFN),CFFN层通过具有零填充的depthwise卷积来增强特征的局部连续性,考虑到效率并将CFFN的比率设为1/4,其计算公式为:
F ^ s p i + 1 = F s p i + C F F N ( n o r m ( F s p i ) ) \hat{F}_{sp}^{i+1}=F_{sp}^{i}+CFFN(norm(F_{sp}^{i})) F^spi+1=Fspi+CFFN(norm(Fspi))
最终得到下一层的空间特征Fspi+1

在这里插入图片描述

3.总结

作者将原使用特定的模型进行预训练并微调的训练方式,更改为了用ViT进行预训练,在微调阶段加入了Adapter,其中ViT-Adapter相当于先使用FPN学习多尺度的先验信息,并加入了Injector和Extractor,用来给ViT主干传递空间先验特征和从ViT中得到新的先验特征,最终该模型在语义分割方向取得了不错的效果。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
在 Swin Transformer 中添加 Adapter 的过程如下: 1. 定义 Adapter 定义一个 Adapter 类,该类包含输入和输出的维度大小以及 Adapter 的前向计算逻辑。例如,一个简单的 Adapter 可以定义如下: ```python import torch.nn as nn class Adapter(nn.Module): def __init__(self, input_dim, output_dim): super(Adapter, self).__init__() self.fc = nn.Sequential( nn.Linear(input_dim, output_dim), nn.ReLU(inplace=True), nn.Linear(output_dim, output_dim), ) def forward(self, x): return self.fc(x) ``` 在这个例子中,我们定义了一个包含两个线性层和一个 ReLU 激活函数的简单的 Adapter。输入和输出的维度大小分别由 `input_dim` 和 `output_dim` 参数指定。 2. 添加 Adapter 到 Swin Transformer Block 在 Swin Transformer Block 的构造函数中,我们可以添加 Adapter。例如,下面是一个包含 Adapter 的基本 Swin Transformer Block: ```python import torch.nn as nn class SwinTransformerBlock(nn.Module): def __init__(self, dim, num_heads, window_size, shift_size, mlp_ratio, qkv_bias=False, qk_scale=None, drop=0., attn_drop=0., drop_path=0., norm_layer=None, input_dim=None, output_dim=None): super().__init__() self.norm1 = norm_layer(dim) self.attn = Attention( dim, num_heads=num_heads, qkv_bias=qkv_bias, qk_scale=qk_scale, attn_drop=attn_drop, proj_drop=drop) self.drop_path = DropPath(drop_path) if drop_path > 0. else nn.Identity() self.norm2 = norm_layer(dim) self.mlp = Mlp(in_features=dim, hidden_features=int(dim * mlp_ratio), out_features=dim, act_layer=nn.GELU, drop=drop) # Add adapter if input_dim is not None and output_dim is not None: self.adapter = Adapter(input_dim=input_dim, output_dim=output_dim) else: self.adapter = None def forward(self, x): if self.adapter is not None: x = x + self.adapter(x) x = x + self.drop_path(self.attn(self.norm1(x))) x = x + self.drop_path(self.mlp(self.norm2(x))) return x ``` 在这个例子中,我们通过 `input_dim` 和 `output_dim` 参数指定了 Adapter 的输入和输出维度大小。在 `forward` 方法中,我们首先应用 Adapter,然后应用注意力机制和 MLP。 3. 多个 Adapter 的情况 如果我们需要添加多个 Adapter,我们可以为每个 Adapter 定义不同的输入和输出维度大小,并将它们添加到 Swin Transformer Block 中。例如,下面是一个包含两个 Adapter 的 Swin Transformer Block: ```python import torch.nn as nn class SwinTransformerBlock(nn.Module): def __init__(self, dim, num_heads, window_size, shift_size, mlp_ratio, qkv_bias=False, qk_scale=None, drop=0., attn_drop=0., drop_path=0., norm_layer=None, input_dims=None, output_dims=None): super().__init__() self.norm1 = norm_layer(dim) self.attn = Attention( dim, num_heads=num_heads, qkv_bias=qkv_bias, qk_scale=qk_scale, attn_drop=attn_drop, proj_drop=drop) self.drop_path = DropPath(drop_path) if drop_path > 0. else nn.Identity() self.norm2 = norm_layer(dim) self.mlp = Mlp(in_features=dim, hidden_features=int(dim * mlp_ratio), out_features=dim, act_layer=nn.GELU, drop=drop) # Add adapters self.adapters = nn.ModuleList() if input_dims is not None and output_dims is not None: for input_dim, output_dim in zip(input_dims, output_dims): self.adapters.append(Adapter(input_dim=input_dim, output_dim=output_dim)) def forward(self, x): for adapter in self.adapters: x = x + adapter(x) x = x + self.drop_path(self.attn(self.norm1(x))) x = x + self.drop_path(self.mlp(self.norm2(x))) return x ``` 在这个例子中,我们使用列表 `input_dims` 和 `output_dims` 指定每个 Adapter 的输入和输出的维度大小,并将它们添加到 `nn.ModuleList()` 中。在 `forward` 方法中,我们首先应用所有的 Adapter,然后应用注意力机制和 MLP。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值