Visual Attention Network

[Submitted on 20 Feb 2022 (v1), last revised 11 Jul 2022 (this version, v5)]

Computer Vision and Pattern Recognition

https://github.com/Visual-Attention-Network

关键词:Attention, Vision Backbone, Deep Learning, ConvNets

0摘要:

虽然最初是为自然语言处理任务而设计的,但自注意机制最近已经席卷了各种计算机视觉领域。然而,图像的2D特性给在计算机视觉中应用自注意机制带来了三个挑战。

(1) 将图像处理为1D序列忽略了它们的2D结构。

(2) 二次复杂度对于高分辨率图像来说太昂贵了。

(3) 它只捕捉空间适应性,而忽略了通道适应性。

【视觉的注意力可以被分为四个类别: 通道注意力、空间注意力、时间注意力和分支注意力。】

在本文中,提出了一种新的线性注意力,称为大核注意力(LKA)模块,以在自注意力中实现自适应和长程相关性(long-range correlations,所以长程依赖可以理解为:当你想使用语言模型,并有效利用较早时间步的信息,最终产生预测的时候,那么你就要和较长路程前的信息建立一种依赖关系,这就是长程依赖。),同时避免其缺点。此外,还提出了一种基于LKA的神经网络,即视觉注意网络(VAN)。尽管极为简单,但VAN在各种任务(包括图像分类、对象检测、语义分割、全景分割、姿态估计等)中都超过了类似尺寸的视觉transformer(ViT)和卷积神经网络(CNN)。

1简介

本文的贡献总结如下:

  • 为计算机视觉设计了一种新的线性注意力机制LKA,它考虑了卷积和自注意力的优点,同时避免了它们的缺点。基于LKA, 进一步介绍了一种简单的 vision backbone,称为VAN。

  • 本文表明,在各种任务(包括图像分类、对象检测、语义分割、实例分割、姿势估计等)的广泛实验中,VANs优于相似级别的ViT和CNN。

2相关工作

2.1CNN

2.2Visual Attention Methods

2.3Vision MLPs

3方法

3.1 LKA

注意机制可以看作是一种自适应选择过程,它可以根据输入特征选择有区别的特征并自动忽略噪声响应。注意机制的关键步骤是生成注意图(attention map),它指示不同部分的重要性。为此,我们应该学习不同特征之间的关系。

在不同部分之间建立关系有两种众所周知的方法。

  • 第一种是采用自注意力机制来捕获长程依赖。在计算机视觉中应用自注意力有三个明显的缺点(摘要部分的三个)。

  • 第二种是使用大核卷积来构建相关性并生成注意图。这种方式仍有明显的缺点。大的核卷积带来了大量的计算开销和参数。

【作者的工作与MobileNet有相似之处,MobileNet将标准卷积解耦为两部分,即深度卷积和逐点卷积】

为了克服上面列出的缺点,并利用自注意和大核卷积的优点,本文建议分解大核卷积操作以捕获长距离关系。如图2所示,大核卷积可以分为三个部分:局部空间卷积(depthwise conv)、空间长程卷积(depthwise dilation conv)和通道卷积(1×1 conv)。

图2.大核卷积的分解图。标准卷积可以分解为三个部分:深度卷积(DW-Conv)、深度扩展卷积(DW-D-Conv)和点卷积(1×1 Conv)。彩色网格表示卷积核的位置,黄色网格表示中心点。13*13卷积分解为5*5深度卷积,5*5深度空洞卷积(膨胀速率为3),和1*1卷积;注:上图中省略了零填充。

通过上面的分解,可以用少量的计算成本和参数来捕获长程关系。在获得长程关系后,可以估计一个点的重要性并生成注意力图。如图3(a)所示,LKA模块可以写为

F∈RC×H×WF ∈R^{C×H×W}FRC×H×W:input features;

Attention∈RC×H×WAttention ∈R_{C×H×W}AttentionRC×H×W:attention map;

图3.不同模块的结构:(a)提出的大核注意力(LKA);(b) 非注意模块;(c) 用加法代替LKA中的乘法;(d) 自我关注。值得注意的是,(d)设计用于1D序列。

注意力图中的值表示每个特征的重要性。⊗指元素乘积。

源代码:

# LKA
class AttentionModule(nn.Module):def __init__(self, dim):super().__init__()# 深度卷积self.conv0 = nn.Conv2d(dim, dim, 5, padding=2, groups=dim)# 深度空洞卷积self.conv_spatial = nn.Conv2d(dim, dim, 7, stride=1, padding=9, groups=dim, dilation=3)# 逐点卷积self.conv1 = nn.Conv2d(dim, dim, 1)def forward(self, x):u = x.clone()attn = self.conv0(x)attn = self.conv_spatial(attn)attn = self.conv1(attn)# 注意力操作return u * attn

与常见的注意方法不同,LKA不需要额外的标准化函数,如sigmoid和softmax,如表3所示(VAN-B0 Acc最高)。

w/o:without

w/:with

本文还认为,注意力方法的关键特征是基于输入特征自适应调整输出,而不是归一化注意力图。如表1所示,本文提出的LKA结合了卷积和自注意力机制的优点。它考虑了局部上下文信息、大的感受野、线性复杂性和动态过程。此外,LKA不仅在空间维度上实现了适应性,而且在通道维度上也实现了适应性。值得注意的是,不同的通道通常代表深度神经网络中的不同对象,通道维度的适应性对于视觉任务也很重要。

LKA的优点总结:

3.2 VAN

VAN具有简单的分层结构,即输出空间分辨率降低的四个阶段序列,即分别为H/4×W/4、H/8×W/8、H/16×W/16和H/32×W/32。这里,H和W表示输入图像的高度和宽度。随着分辨率的降低,输出通道的数量也在增加。输出通道Ci的变化如表5所示。

对于图4所示的每个阶段,首先对输入进行下采样,并使用步幅数来控制下采样率。在下采样之后,阶段中的所有其他层保持相同的输出大小,即空间分辨率和通道数。然后,依次堆叠L组归一化,1×1 Conv、GELU激活、大核关注和前馈网络(FFN)以提取特征。

图4. VAN的一个阶段。d表示深度卷积。k×k表示k×k卷积。

根据参数和计算成本,本文设计了七种架构VAN-B0、VAN-B1、VAN-B2、VAN-B3、VAN-B4、VAN-B5、VAN-B6。整个网络的详细信息如表5所示。

源代码:

# attention
class SpatialAttention(nn.Module):def __init__(self, d_model):super().__init__()# 1*1self.proj_1 = nn.Conv2d(d_model, d_model, 1)# 激活函数self.activation = nn.GELU()# LKAself.spatial_gating_unit = AttentionModule(d_model)# 1*1self.proj_2 = nn.Conv2d(d_model, d_model, 1)def forward(self, x):# resshorcut = x.clone()x = self.proj_1(x)x = self.activation(x)x = self.spatial_gating_unit(x)x = self.proj_2(x)x = x + shorcutreturn x
class Block(nn.Module):def __init__(self, dim, mlp_ratio=4., drop=0., drop_path=0., act_layer=nn.GELU):super().__init__()# BNself.norm1 = nn.BatchNorm2d(dim)# attentionself.attn = SpatialAttention(dim)# 正则化 随机删除分支# identity模块不改变输入,直接return input# 一种编码技巧吧,比如我们要加深网络,有些层是不改变输入数据的维度的,# 在增减网络的过程中我们就可以用identity占个位置,这样网络整体层数永远不变# van_small drop_path=0.1# 结合drop_path的调用,若x为输入的张量,其通道为[B,C,H,W]# 那么drop_path的含义为在一个Batch_size中# 随机有drop_prob的样本,不经过主干,而直接由分支进行恒等映射。self.drop_path = DropPath(drop_path) if drop_path > 0. else nn.Identity()# BN2self.norm2 = nn.BatchNorm2d(dim)mlp_hidden_dim = int(dim * mlp_ratio)# FFNself.mlp = Mlp(in_features=dim, hidden_features=mlp_hidden_dim,act_layer=act_layer, drop=drop)layer_scale_init_value = 1e-2self.layer_scale_1 = nn.Parameter(layer_scale_init_value * torch.ones((dim)), requires_grad=True)self.layer_scale_2 = nn.Parameter(layer_scale_init_value * torch.ones((dim)), requires_grad=True)self.apply(self._init_weights)def _init_weights(self, m):if isinstance(m, nn.Linear):# trunc_normal_函数:截断正太分布# 截断分布是指,限制变量xx 取值范围(scope)的一种分布trunc_normal_(m.weight, std=.02)if isinstance(m, nn.Linear) and m.bias is not None:# 使用val的值来填充输入的Tensornn.init.constant_(m.bias, 0)elif isinstance(m, nn.LayerNorm):nn.init.constant_(m.bias, 0)nn.init.constant_(m.weight, 1.0)elif isinstance(m, nn.Conv2d):fan_out = m.kernel_size[0] * m.kernel_size[1] * m.out_channels# groups = 1 时就是标准的卷积运算# groups = input_channels的情况是这样的# 当输入通道数等于输出通道数时,就是深度可分离卷积的depthwise conv# 可查看mobilenet的论文理解该卷积fan_out //= m.groupsm.weight.data.normal_(0, math.sqrt(2.0 / fan_out))if m.bias is not None:# bias初始化为0m.bias.data.zero_()def forward(self, x):x = x + self.drop_path(self.layer_scale_1.unsqueeze(-1).unsqueeze(-1)* self.attn(self.norm1(x)))x = x + \self.drop_path(self.layer_scale_2.unsqueeze(-1).unsqueeze(-1) * self.mlp(self.norm2(x)))return x

复杂度分析

假设输入和输出的特征都具有相同的大小 HxWxC,则参数和FLOPs可以被写成如下

参数P和FLOPs的数量可以表示为:

d表示膨胀率,K表示核大小。根据FLOP和参数的公式,FLOP与参数的预算节省率相同。

实现细节

默认采用K=21。对于K=21。公式(3)当d=3时取最小值,这对应于5×5深度卷积和7×7深度卷积与扩张3。

4实验

4.1图像分类

4.1.1 ImageNet-1K Experiments

设置

消融实验

本文进行了消融研究,以证明LKA的每个组成部分都至关重要。为了快速获得实验结果, 选择VAN-B0作为 的基线模型。表3中的实验结果表明,LKA中的所有组件对于提高性能是必不可少的。

  • DW-Conv. 可以利用图像的局部上下文信息。没有它,分类性能将下降0.5%(74.9%对75.4%),这表明了局部结构信息在图像处理中的重要性。

  • DW-D-Conv. 表示深度空洞卷积,其在捕获LKA中的长程依赖性中起作用。没有它,分类性能将下降1.3%(74.1%对75.4%),这证实了本文的观点,即长程依赖对视觉任务至关重要。

  • Attention Mechanism. 注意力机制的引入可以被视为使网络具有自适应特性。受益于此,VAN-B0实现了约1.1%(74.3%对75.4%)的改进。

  • 1 × 1 Conv. 这里,1×1 Conv捕获了通道维度中的关系。结合注意力机制,引入了通道维度的适应性。它带来了0.8%(74.6%对75.4%)的改善,这证明了通道维度适应性的必要性。

  • Sigmoid function. Sigmoid函数是将注意力图从0归一化为1的常用归一化函数。然而, 发现LKA模块在 的实验中没有必要。没有sigmoid的VAN-B0实现了0.2%(75.4%对75.2%)的改善和更少的计算。

此外, 还进行了消融研究,以分解表6中不同大小的卷积核。 可以发现,分解21×21卷积比分解7×7卷积效果更好,这表明大核对视觉任务至关重要。分解更大的28×28卷积, 发现与分解21×21卷积相比,增益并不明显。

因此, 默认选择分解21×21卷积。

4.1.2 Visualization

4.1.3 Pretraining on ImageNet-22K

4.2目标检测

4.3图像分割

4.4全景分割

4.5姿态评估

4.6细颗粒分类

4.7显著性检测

5讨论

最近,基于transformer的模型迅速征服了各种视觉排行榜。正如 所知,自注意力只是一种特殊的注意机制。然而,人们逐渐默认采用自注意,而忽略了潜在的关注方法。本文提出了一种新的注意力模块LKA和基于CNN的网络VAN。它超越了用于视觉任务的最先进的基于transformer的方法。希望这篇论文能促使人们重新思考自注意力是否不可替代,以及哪种注意力更适合视觉任务。

6 future work

未来,将在以下方面继续完善VAN:

  • 继续改进它的结构。在本文中,只展示了一个直观的结构,还存在很多潜在的改进点,例如:应用大核、引入多尺度结构和使用多分支结构。

  • 大规模的自监督学习和迁移学习。VAN 自然地结合了CNN和ViT的优点。一方面VAN利用了图像的2D结构。另一方面 VAN可以基于输入图片动态的调整输出,它很适合自监督学习和迁移学习。结合了这两点,作者认为VAN可以在这两个领域有更好的性能。

  • 更多的应用场景。由于资源有限,作者只展示了它在视觉任务中的优秀性能。作者期待VAN在各个领域都展示优秀性能并变成一个通用的模型。

7 conclusion

在本文中, 提出了一种新的视觉注意LKA,它结合了卷积和自我注意的优点。基于LKA, 构建了一个 vision backbone VAN,在一些视觉任务中实现了最先进的性能,包括图像分类、对象检测、语义分割等。未来,将从第6节中提到的方向继续改进该框架。

# 四阶段模型
class VAN(nn.Module):#def __init__(self, img_size=224, in_chans=3, num_classes=3, embed_dims=[64, 128, 256, 512],mlp_ratios=[4, 4, 4, 4], drop_rate=0., drop_path_rate=0., norm_layer=nn.LayerNorm,depths=[3, 4, 6, 3], num_stages=4, flag=False, pretrained_cfg=None):super().__init__()if flag == False:self.num_classes = num_classesself.depths = depthsself.num_stages = num_stages# 返回一个一维的tensor(张量),这个张量包含了从start到end(包括端点)的等距的steps个数据点dpr = [x.item() for x in torch.linspace(0, drop_path_rate,sum(depths))]  # stochastic depth decay rulecur = 0for i in range(num_stages):# 这里还下采样了# 提取特征patch_embed = OverlapPatchEmbed(img_size=img_size if i == 0 else img_size // (2 ** (i + 1)),patch_size=7 if i == 0 else 3,stride=4 if i == 0 else 2,in_chans=in_chans if i == 0 else embed_dims[i - 1],embed_dim=embed_dims[i])block = nn.ModuleList([Block(dim=embed_dims[i], mlp_ratio=mlp_ratios[i], drop=drop_rate, drop_path=dpr[cur + j])for j in range(depths[i])])# LayerNorm也是归一化的一种方法norm = norm_layer(embed_dims[i])cur += depths[i]# setattr() 函数对应函数 getattr(),用于设置属性值,该属性不一定是存在的。setattr(self, f"patch_embed{i + 1}", patch_embed)setattr(self, f"block{i + 1}", block)setattr(self, f"norm{i + 1}", norm)# classification headself.head = nn.Linear(embed_dims[3], num_classes) if num_classes > 0 else nn.Identity()self.apply(self._init_weights)def _init_weights(self, m):if isinstance(m, nn.Linear):trunc_normal_(m.weight, std=.02)if isinstance(m, nn.Linear) and m.bias is not None:nn.init.constant_(m.bias, 0)elif isinstance(m, nn.LayerNorm):nn.init.constant_(m.bias, 0)nn.init.constant_(m.weight, 1.0)elif isinstance(m, nn.Conv2d):fan_out = m.kernel_size[0] * m.kernel_size[1] * m.out_channelsfan_out //= m.groupsm.weight.data.normal_(0, math.sqrt(2.0 / fan_out))if m.bias is not None:m.bias.data.zero_()# 冻结def freeze_patch_emb(self):self.patch_embed1.requires_grad = False@torch.jit.ignoredef no_weight_decay(self):# has pos_embed may be betterreturn {'pos_embed1', 'pos_embed2', 'pos_embed3', 'pos_embed4', 'cls_token'}def get_classifier(self):return self.headdef reset_classifier(self, num_classes, global_pool=''):self.num_classes = num_classesself.head = nn.Linear(self.embed_dim, num_classes) if num_classes > 0 else nn.Identity()def forward_features(self, x):B = x.shape[0]x, H, W = self.patch_embed1(x)for blk in self.block1:x = blk(x)x = x.flatten(2).transpose(1, 2)x = self.norm1(x)x = x.reshape(B, H, W, -1).permute(0, 3, 1, 2).contiguous()x, H, W = self.patch_embed2(x)for blk in self.block2:x = blk(x)x = x.flatten(2).transpose(1, 2)x = self.norm2(x)x = x.reshape(B, H, W, -1).permute(0, 3, 1, 2).contiguous()x, H, W = self.patch_embed3(x)for blk in self.block3:x = blk(x)x = x.flatten(2).transpose(1, 2)x = self.norm3(x)x = x.reshape(B, H, W, -1).permute(0, 3, 1, 2).contiguous()x, H, W = self.patch_embed4(x)for blk in self.block4:x = blk(x)x = x.flatten(2).transpose(1, 2)x = self.norm4(x)return x.mean(dim=1)def forward(self, x):x = self.forward_features(x)x = self.head(x)return x

网络架构

VAN((patch_embed1): OverlapPatchEmbed((proj): Conv2d(3, 32, kernel_size=(7, 7), stride=(4, 4), padding=(3, 3))(norm): BatchNorm2d(32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True))(block1): ModuleList((0): Block((norm1): BatchNorm2d(32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(attn): Attention((proj_1): Conv2d(32, 32, kernel_size=(1, 1), stride=(1, 1))(activation): GELU()(spatial_gating_unit): LKA((conv0): Conv2d(32, 32, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2), groups=32)(conv_spatial): Conv2d(32, 32, kernel_size=(7, 7), stride=(1, 1), padding=(9, 9), dilation=(3, 3), groups=32)(conv1): Conv2d(32, 32, kernel_size=(1, 1), stride=(1, 1)))(proj_2): Conv2d(32, 32, kernel_size=(1, 1), stride=(1, 1)))(drop_path): Identity()(norm2): BatchNorm2d(32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(mlp): Mlp((fc1): Conv2d(32, 256, kernel_size=(1, 1), stride=(1, 1))(dwconv): DWConv((dwconv): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), groups=256))(act): GELU()(fc2): Conv2d(256, 32, kernel_size=(1, 1), stride=(1, 1))(drop): Dropout(p=0.0, inplace=False)))(1): Block((norm1): BatchNorm2d(32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(attn): Attention((proj_1): Conv2d(32, 32, kernel_size=(1, 1), stride=(1, 1))(activation): GELU()(spatial_gating_unit): LKA((conv0): Conv2d(32, 32, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2), groups=32)(conv_spatial): Conv2d(32, 32, kernel_size=(7, 7), stride=(1, 1), padding=(9, 9), dilation=(3, 3), groups=32)(conv1): Conv2d(32, 32, kernel_size=(1, 1), stride=(1, 1)))(proj_2): Conv2d(32, 32, kernel_size=(1, 1), stride=(1, 1)))(drop_path): DropPath(drop_prob=0.008)(norm2): BatchNorm2d(32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(mlp): Mlp((fc1): Conv2d(32, 256, kernel_size=(1, 1), stride=(1, 1))(dwconv): DWConv((dwconv): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), groups=256))(act): GELU()(fc2): Conv2d(256, 32, kernel_size=(1, 1), stride=(1, 1))(drop): Dropout(p=0.0, inplace=False)))(2): Block((norm1): BatchNorm2d(32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(attn): Attention((proj_1): Conv2d(32, 32, kernel_size=(1, 1), stride=(1, 1))(activation): GELU()(spatial_gating_unit): LKA((conv0): Conv2d(32, 32, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2), groups=32)(conv_spatial): Conv2d(32, 32, kernel_size=(7, 7), stride=(1, 1), padding=(9, 9), dilation=(3, 3), groups=32)(conv1): Conv2d(32, 32, kernel_size=(1, 1), stride=(1, 1)))(proj_2): Conv2d(32, 32, kernel_size=(1, 1), stride=(1, 1)))(drop_path): DropPath(drop_prob=0.017)(norm2): BatchNorm2d(32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(mlp): Mlp((fc1): Conv2d(32, 256, kernel_size=(1, 1), stride=(1, 1))(dwconv): DWConv((dwconv): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), groups=256))(act): GELU()(fc2): Conv2d(256, 32, kernel_size=(1, 1), stride=(1, 1))(drop): Dropout(p=0.0, inplace=False))))(norm1): LayerNorm((32,), eps=1e-06, elementwise_affine=True)(patch_embed2): OverlapPatchEmbed((proj): Conv2d(32, 64, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1))(norm): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True))(block2): ModuleList((0): Block((norm1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(attn): Attention((proj_1): Conv2d(64, 64, kernel_size=(1, 1), stride=(1, 1))(activation): GELU()(spatial_gating_unit): LKA((conv0): Conv2d(64, 64, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2), groups=64)(conv_spatial): Conv2d(64, 64, kernel_size=(7, 7), stride=(1, 1), padding=(9, 9), dilation=(3, 3), groups=64)(conv1): Conv2d(64, 64, kernel_size=(1, 1), stride=(1, 1)))(proj_2): Conv2d(64, 64, kernel_size=(1, 1), stride=(1, 1)))(drop_path): DropPath(drop_prob=0.025)(norm2): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(mlp): Mlp((fc1): Conv2d(64, 512, kernel_size=(1, 1), stride=(1, 1))(dwconv): DWConv((dwconv): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), groups=512))(act): GELU()(fc2): Conv2d(512, 64, kernel_size=(1, 1), stride=(1, 1))(drop): Dropout(p=0.0, inplace=False)))(1): Block((norm1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(attn): Attention((proj_1): Conv2d(64, 64, kernel_size=(1, 1), stride=(1, 1))(activation): GELU()(spatial_gating_unit): LKA((conv0): Conv2d(64, 64, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2), groups=64)(conv_spatial): Conv2d(64, 64, kernel_size=(7, 7), stride=(1, 1), padding=(9, 9), dilation=(3, 3), groups=64)(conv1): Conv2d(64, 64, kernel_size=(1, 1), stride=(1, 1)))(proj_2): Conv2d(64, 64, kernel_size=(1, 1), stride=(1, 1)))(drop_path): DropPath(drop_prob=0.033)(norm2): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(mlp): Mlp((fc1): Conv2d(64, 512, kernel_size=(1, 1), stride=(1, 1))(dwconv): DWConv((dwconv): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), groups=512))(act): GELU()(fc2): Conv2d(512, 64, kernel_size=(1, 1), stride=(1, 1))(drop): Dropout(p=0.0, inplace=False)))(2): Block((norm1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(attn): Attention((proj_1): Conv2d(64, 64, kernel_size=(1, 1), stride=(1, 1))(activation): GELU()(spatial_gating_unit): LKA((conv0): Conv2d(64, 64, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2), groups=64)(conv_spatial): Conv2d(64, 64, kernel_size=(7, 7), stride=(1, 1), padding=(9, 9), dilation=(3, 3), groups=64)(conv1): Conv2d(64, 64, kernel_size=(1, 1), stride=(1, 1)))(proj_2): Conv2d(64, 64, kernel_size=(1, 1), stride=(1, 1)))(drop_path): DropPath(drop_prob=0.042)(norm2): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(mlp): Mlp((fc1): Conv2d(64, 512, kernel_size=(1, 1), stride=(1, 1))(dwconv): DWConv((dwconv): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), groups=512))(act): GELU()(fc2): Conv2d(512, 64, kernel_size=(1, 1), stride=(1, 1))(drop): Dropout(p=0.0, inplace=False))))(norm2): LayerNorm((64,), eps=1e-06, elementwise_affine=True)(patch_embed3): OverlapPatchEmbed((proj): Conv2d(64, 160, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1))(norm): BatchNorm2d(160, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True))(block3): ModuleList((0): Block((norm1): BatchNorm2d(160, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(attn): Attention((proj_1): Conv2d(160, 160, kernel_size=(1, 1), stride=(1, 1))(activation): GELU()(spatial_gating_unit): LKA((conv0): Conv2d(160, 160, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2), groups=160)(conv_spatial): Conv2d(160, 160, kernel_size=(7, 7), stride=(1, 1), padding=(9, 9), dilation=(3, 3), groups=160)(conv1): Conv2d(160, 160, kernel_size=(1, 1), stride=(1, 1)))(proj_2): Conv2d(160, 160, kernel_size=(1, 1), stride=(1, 1)))(drop_path): DropPath(drop_prob=0.050)(norm2): BatchNorm2d(160, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(mlp): Mlp((fc1): Conv2d(160, 640, kernel_size=(1, 1), stride=(1, 1))(dwconv): DWConv((dwconv): Conv2d(640, 640, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), groups=640))(act): GELU()(fc2): Conv2d(640, 160, kernel_size=(1, 1), stride=(1, 1))(drop): Dropout(p=0.0, inplace=False)))(1): Block((norm1): BatchNorm2d(160, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(attn): Attention((proj_1): Conv2d(160, 160, kernel_size=(1, 1), stride=(1, 1))(activation): GELU()(spatial_gating_unit): LKA((conv0): Conv2d(160, 160, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2), groups=160)(conv_spatial): Conv2d(160, 160, kernel_size=(7, 7), stride=(1, 1), padding=(9, 9), dilation=(3, 3), groups=160)(conv1): Conv2d(160, 160, kernel_size=(1, 1), stride=(1, 1)))(proj_2): Conv2d(160, 160, kernel_size=(1, 1), stride=(1, 1)))(drop_path): DropPath(drop_prob=0.058)(norm2): BatchNorm2d(160, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(mlp): Mlp((fc1): Conv2d(160, 640, kernel_size=(1, 1), stride=(1, 1))(dwconv): DWConv((dwconv): Conv2d(640, 640, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), groups=640))(act): GELU()(fc2): Conv2d(640, 160, kernel_size=(1, 1), stride=(1, 1))(drop): Dropout(p=0.0, inplace=False)))(2): Block((norm1): BatchNorm2d(160, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(attn): Attention((proj_1): Conv2d(160, 160, kernel_size=(1, 1), stride=(1, 1))(activation): GELU()(spatial_gating_unit): LKA((conv0): Conv2d(160, 160, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2), groups=160)(conv_spatial): Conv2d(160, 160, kernel_size=(7, 7), stride=(1, 1), padding=(9, 9), dilation=(3, 3), groups=160)(conv1): Conv2d(160, 160, kernel_size=(1, 1), stride=(1, 1)))(proj_2): Conv2d(160, 160, kernel_size=(1, 1), stride=(1, 1)))(drop_path): DropPath(drop_prob=0.067)(norm2): BatchNorm2d(160, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(mlp): Mlp((fc1): Conv2d(160, 640, kernel_size=(1, 1), stride=(1, 1))(dwconv): DWConv((dwconv): Conv2d(640, 640, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), groups=640))(act): GELU()(fc2): Conv2d(640, 160, kernel_size=(1, 1), stride=(1, 1))(drop): Dropout(p=0.0, inplace=False)))(3): Block((norm1): BatchNorm2d(160, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(attn): Attention((proj_1): Conv2d(160, 160, kernel_size=(1, 1), stride=(1, 1))(activation): GELU()(spatial_gating_unit): LKA((conv0): Conv2d(160, 160, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2), groups=160)(conv_spatial): Conv2d(160, 160, kernel_size=(7, 7), stride=(1, 1), padding=(9, 9), dilation=(3, 3), groups=160)(conv1): Conv2d(160, 160, kernel_size=(1, 1), stride=(1, 1)))(proj_2): Conv2d(160, 160, kernel_size=(1, 1), stride=(1, 1)))(drop_path): DropPath(drop_prob=0.075)(norm2): BatchNorm2d(160, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(mlp): Mlp((fc1): Conv2d(160, 640, kernel_size=(1, 1), stride=(1, 1))(dwconv): DWConv((dwconv): Conv2d(640, 640, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), groups=640))(act): GELU()(fc2): Conv2d(640, 160, kernel_size=(1, 1), stride=(1, 1))(drop): Dropout(p=0.0, inplace=False)))(4): Block((norm1): BatchNorm2d(160, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(attn): Attention((proj_1): Conv2d(160, 160, kernel_size=(1, 1), stride=(1, 1))(activation): GELU()(spatial_gating_unit): LKA((conv0): Conv2d(160, 160, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2), groups=160)(conv_spatial): Conv2d(160, 160, kernel_size=(7, 7), stride=(1, 1), padding=(9, 9), dilation=(3, 3), groups=160)(conv1): Conv2d(160, 160, kernel_size=(1, 1), stride=(1, 1)))(proj_2): Conv2d(160, 160, kernel_size=(1, 1), stride=(1, 1)))(drop_path): DropPath(drop_prob=0.083)(norm2): BatchNorm2d(160, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(mlp): Mlp((fc1): Conv2d(160, 640, kernel_size=(1, 1), stride=(1, 1))(dwconv): DWConv((dwconv): Conv2d(640, 640, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), groups=640))(act): GELU()(fc2): Conv2d(640, 160, kernel_size=(1, 1), stride=(1, 1))(drop): Dropout(p=0.0, inplace=False))))(norm3): LayerNorm((160,), eps=1e-06, elementwise_affine=True)(patch_embed4): OverlapPatchEmbed((proj): Conv2d(160, 256, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1))(norm): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True))(block4): ModuleList((0): Block((norm1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(attn): Attention((proj_1): Conv2d(256, 256, kernel_size=(1, 1), stride=(1, 1))(activation): GELU()(spatial_gating_unit): LKA((conv0): Conv2d(256, 256, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2), groups=256)(conv_spatial): Conv2d(256, 256, kernel_size=(7, 7), stride=(1, 1), padding=(9, 9), dilation=(3, 3), groups=256)(conv1): Conv2d(256, 256, kernel_size=(1, 1), stride=(1, 1)))(proj_2): Conv2d(256, 256, kernel_size=(1, 1), stride=(1, 1)))(drop_path): DropPath(drop_prob=0.092)(norm2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(mlp): Mlp((fc1): Conv2d(256, 1024, kernel_size=(1, 1), stride=(1, 1))(dwconv): DWConv((dwconv): Conv2d(1024, 1024, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), groups=1024))(act): GELU()(fc2): Conv2d(1024, 256, kernel_size=(1, 1), stride=(1, 1))(drop): Dropout(p=0.0, inplace=False)))(1): Block((norm1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(attn): Attention((proj_1): Conv2d(256, 256, kernel_size=(1, 1), stride=(1, 1))(activation): GELU()(spatial_gating_unit): LKA((conv0): Conv2d(256, 256, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2), groups=256)(conv_spatial): Conv2d(256, 256, kernel_size=(7, 7), stride=(1, 1), padding=(9, 9), dilation=(3, 3), groups=256)(conv1): Conv2d(256, 256, kernel_size=(1, 1), stride=(1, 1)))(proj_2): Conv2d(256, 256, kernel_size=(1, 1), stride=(1, 1)))(drop_path): DropPath(drop_prob=0.100)(norm2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(mlp): Mlp((fc1): Conv2d(256, 1024, kernel_size=(1, 1), stride=(1, 1))(dwconv): DWConv((dwconv): Conv2d(1024, 1024, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), groups=1024))(act): GELU()(fc2): Conv2d(1024, 256, kernel_size=(1, 1), stride=(1, 1))(drop): Dropout(p=0.0, inplace=False))))(norm4): LayerNorm((256,), eps=1e-06, elementwise_affine=True)(head): Linear(in_features=256, out_features=3, bias=True)
)

VAN:Visual Attention Network相关推荐

  1. 深度网络设计技巧(五)之VAN:Visual Attention Network#超越Swin的纯CNN#

    单位:清华,南开(程明明团队) ArXiv:https://arxiv.org/abs/2202.09741 Github: https://github.com/Visual-Attention-N ...

  2. 新的 self-attention 网络结构,Visual Attention Network

    随着现在大家把transformer 的各种结构玩成花以后,后面也没有出什么比较经典的结构了.然后研究者们就开始挖掘以前的网络结构特点,加上各种技巧提高网络准确度.比如前段时间的ConvNeXt,各种 ...

  3. 【Attention】Visual Attention Network

    文章目录 一.背景 二.动机 三.方法 3.1 Large Kernel Attention 3.2 VAN 四.效果 4.1 分类 4.2 目标检测 4.3 语义分割 论文链接:https://ar ...

  4. 【ARXIV2202】Visual Attention Network

    [ARXIV2202]Visual Attention Network 论文地址:https://arxiv.org/abs/2202.09741 代码地址:https://github.com/Vi ...

  5. 文章阅读:Dual Attention Network for Scene Segmentation

    原文地址:Dual Attention Network for Scene Segmentation 概述 多尺度上下文融合的问题: 虽然上下文融合有助于捕获不同比例的对象,但它无法利用全局视图中对象 ...

  6. Face Paper:Face Attention Network: An Effective Face Detector for the Occluded Faces

    人脸检测的性能近期由于深度学习的发展大幅度提高, 然而对于人脸的遮挡问题一直是人脸检测中一个比较有挑战的问题, 这种场景多出现于佩戴口罩.太阳镜和其他人的遮挡等. 这篇文章提出了Face Attent ...

  7. 论文翻译:Residual Attention Network for Image Classification

    摘要 在这项工作中,我们提出了"残余注意力网络",这是一种使用注意力机制的卷积神经网络,可以以端到端的训练方式与最新的前馈网络体系结构结合.我们的剩余注意力网络是通过堆叠注意力模块 ...

  8. 跨模态检索论文阅读:Context-Aware Attention Network for Image-Text Retrieval

    Context-Aware Attention Network for Image-Text Retrieval基于上下文感知的图文检索注意网络 Motivation: 以前的方法没有考虑到单模态中模 ...

  9. Graph Attention Network (GAT) 的Tensorflow版代码解析

    文章目录 代码结构 参数设置 数据加载 特征预处理 模型定义 GAT核心定义:layers.py gat.py base_gattn.py 关于GAT的基本原理解析可查看另一篇博客: Graph At ...

最新文章

  1. 一学长毕业临走前和我说的话
  2. python接口测试声音,python接口测试-登录
  3. 运维自动化------ansible搭建
  4. 张亚勤:领导者的3种能力
  5. Leetcode 105. 从前序与中序遍历序列构造二叉树 解题思路及C++实现
  6. UI 设计:如何做到理性?
  7. EasyUI中layout布局的简单使用
  8. 还没掌握Linux文件权限与目录配置命令?就这还不点进来看看干货
  9. python3类的继承详解_python3中类的继承以及self和super的区别详解
  10. Ubuntu 安装 chrome
  11. 第一:Pytest简介和环境准备
  12. 教你使用squid搭配dante做代理
  13. 第 7 章 Neutron - 069 - 理解 Neutron Server 分层模型
  14. C++黑客编程——初识(1)
  15. Linux操作系统原理— 进程与线程管理
  16. 构建LALR(1)项目集族
  17. 35岁没成高管被优化了.... 网友炸了!!!
  18. 解决editormd不能显示emoji问题
  19. r语言boxcox异方差_R教程-15:线性回归中的异方差
  20. 川外计算机课什么时候截止,四川外国语大学留学生学习期限及课程设置

热门文章

  1. 单反、微单、卡片相机的区别
  2. oracle明文显示密码,通过PL/SQL获取密码明文
  3. 通过慕课网学习Python
  4. 邓宁-克鲁格效应的理解
  5. itchat自动回复
  6. UE4三维游戏毕设制作与学习过程中的所思所想01
  7. VS2022软件C语言安装
  8. Win10家庭版账户名变更方法
  9. 微信账户零钱冻结提取
  10. 需求规格说明书和软件概要设计文档最终版上线~