【目标检测】61、Dynamic Head Unifying Object Detection Heads with Attentions

news2024/9/22 3:33:21

文章目录

    • 一、背景
    • 二、方法
      • 2.1 scale-aware attention
      • 2.2 spatial-aware attention
      • 2.3 task-aware attention
      • 2.4 总体过程
      • 2.5 和现有的检测器适配
      • 2.6 和其他注意力机制的关联
    • 三、效果
    • 四、代码

在这里插入图片描述
论文链接: https://arxiv.org/pdf/2106.08322.pdf

代码链接:https://github.com/microsoft/DynamicHead

出处: CVPR 2021

一、背景

将目标检测中的定位和分类头统一起来一直是一个引人关注的问题,之前的工作尝试了很多方法,但是一直没有得来一个一致的形式。所以,如何提升目标检测头的性能也是一个重要的问题。

主要难点在于:

  • head 应该 scale-aware,因为一个图像中会出现多个不同尺度的目标
  • head 应该 spatial-aware,因为目标都是在不同视角下的,会有不同形状、角度、位置
  • head 应该 task-aware,因为目标可以有多种不同的表达,如bbox、center、corner points,其目标函数和优化方法都是不同的

所以本文中,作者提出了一种新的检测头——dynamic head,来将 scale-awareness, spatial-awareness, task-awareness 进行统一。

假设从 backbone 输出的特征图为 l e v e l × s p a c e × c h n n e l level \times space \times chnnel level×space×chnnel,则统一的检测头可以看成一个 attention learning 问题。如果直接使用 self-attention 的话,计算复杂度很高。

所以,作者将注意力进行了拆分:

  • level-wise:scale-aware attention module 在该维度使用,能够学习语义层面的相对重要程度,可以基于尺度来加强每个目标的特征
  • spatial-wise:spatial-aware attention module 在该维度使用( h e i g h t × w i d t h height \times width height×width),能够在空间位置上学习有区分力的特征表达
  • channel-wise:task-aware attention module 在该维度使用,能够指导不同通道的特征为不同的任务出力(分类、回归、中心点等)。

二、方法

作者针对 detection head 提出了一种统一的 attention mechanism,在 COCO 上提升了1.2%~3.2% 的 AP 。

从 backbone 输出的 L 层多尺度特征图为: F i n = { F i } i = 1 L F_{in}=\{F_i\}_{i=1}^L Fin={Fi}i=1L

  • 将这些特征图全都 resize 到中间尺度特征图大小
  • 得到四维特征图: F ∈ R L × H × W × C F \in R^{L \times H \times W \times C} FRL×H×W×C
  • 将上面的四维特征图 reshape 成三维的: F ∈ R L × S × C F \in R^{L \times S \times C} FRL×S×C

这三个维度分别有如下表示:

  • 不同的 level L L L:不同尺度的目标其实是和不同尺度的层相对应的,根据不同尺度来提升特征学习表达,有利于目标检测的 scale-awareness。
  • 不同的空间位置 S S S:提升特征图中不同位置的特征学习,能够提升目标检测的 spatial-awareness
  • 不同的任务 C C C:不同的任务其实和不同的 channel 是挂钩的,提升不同 channel 的特征表达能力能够提升目标检测的 task-awareness

三维特征为 F ∈ R L × S × C F \in R^{L \times S \times C} FRL×S×C,则通用 self-attention 的形式如下:

在这里插入图片描述

  • 其中 pai 为 attention 函数,但传统的方法计算量和显存占用都很大

所以,作者将其拆分为3个串行的 attention,每个子 attention 仅关注单个维度:

在这里插入图片描述

2.1 scale-aware attention

作者首先使用 scale-aware attention 来动态的聚合不同尺度的特征,基于其语义重要性:

在这里插入图片描述

  • f ( . ) f(.) f(.) 是线性函数,使用 1x1 卷积实现
  • σ ( x ) = m a x ( 0 , m i n ( 1 , x + 1 2 ) ) \sigma(x)=max(0,min(1, \frac{x+1}{2})) σ(x)=max(0,min(1,2x+1)),是一个 hard-sigmoid 函数

2.2 spatial-aware attention

作者基于融合的特征来使用 spatial-aware attention,来让网络更关注于共现于空间位置和特征层级上的突变区域。

考虑到 S 的维度很大,作者分解为了两个步骤:

  • 首先,使用可变形卷积,让 attention 学习稀疏特征
  • 然后,将不同尺度特征图上的相同位置的特征进行聚合

在这里插入图片描述

  • K 是 sparse sampling location 的数量
  • p k + Δ p k p_k+\Delta p_k pk+Δpk 是自学习的空间偏移 Δ p k \Delta p_k Δpk ,注意到突变区域
  • Δ m k \Delta m_k Δmk 是位置 p k p_k pk 上的自学习得到的重要性标量

2.3 task-aware attention

为了联合学习,并且归纳不同目标的表达方式,作者在最后使用了 task-aware attention,能够动态的针对不同 task 来控制每个 channel 的开关。

在这里插入图片描述

  • F c F_c Fc 是第 c 个 channel 上的切片
  • [ α 1 , α 2 , β 1 , β 2 ] = θ ( . ) [\alpha^1, \alpha^2, \beta^1, \beta^2]=\theta(.) [α1,α2,β1,β2]=θ(.) 是超参数,学习控制激活阈值, θ ( . ) \theta(.) θ(.) 首先在 L × S L\times S L×S 使用全局平均池化降低维度,然后使用两个全连接层、一个归一化层、一个sigmoid,归一化到 [-1,1]。

2.4 总体过程

因为上述三个步骤是串联进行的,所以,能够多次使用公式二,来堆叠多个 attention blocks,如图 2a 所示。

在这里插入图片描述
整个方法的总体框架如图 1 所示,可以使用任何 backbone 来生成多尺度金字塔特征图,然后resize,生成 3 维特征图,输入本文提出的 dynamic head。

然后,使用多个 block 进行特征提取。

dynamic head 的输出可以用于不同任务。

如图 1 所示,从 backbone 输出的特征图有很多噪声,由于和预训练的 ImageNet 的域不同,经过 scale-aware attention module 后,特征图对不同尺度的前景有更好的响应。经过 spatial-aware attention module 后,特征图更加稀疏,并且能聚焦于前景目标的突变区域。经过 task-aware attention module 后,特征图会基于不同的下游任务来被重新调整。

在这里插入图片描述

2.5 和现有的检测器适配

1、单阶段检测器

单阶段检测器中,一般都是使用 backbone 来抽取密集特征,然后使用多个子网络头来实现不同的任务。

但是,目标分类子网络和位置回归子网络其实有很大不同

所以,使用本文作者提出的动态 attention module,能够灵活的适用于不同任务,如图2b所示。

2、两阶段检测器

量阶段检测器会使用 ROI-pooling 来抽取提议区域,所以首先在 ROI-pooling 之前使用 scale 和 spatial attention,然后使用 task attention 来代替全连接层,如图 2c 所示。

2.6 和其他注意力机制的关联

1、Deformable

可变形卷积能够通过引入 sparse sampling 来提高效果,大多应用于 backbone 中来提高特征的表达能力,很少用于检测头。

2、Non-local

Non-local 一般被用来建立长距离依赖关系,可以看做是建立本文中 L × S L \times S L×S 的关系

3、Transformer

Transformer 类似于建立 S × C S \times C S×C 的关系

也就是说,这三个 attention 机制都建立了局部的 attention,所以,本文相当于高效的实现了将多个不同的维度结合的事情。

三、效果

1、消融实验验证每个维度 attention 的效果

在这里插入图片描述

  • 单独使用 level、spatial、channel attention,分别能带来 0.9、2.4、1.3 AP 的提升。
  • 联合使用 L+S ,提升了 2.9 AP
  • 联合使用三个 attention,共提升了 3.6 AP。

2、消融实验验证每个维度 attention 学习到的东西

在这里插入图片描述

图 3 展示了 scale-aware module 的不同 level 的 scale ratio 的趋势,scale ratio 是使用高分辨率图的学习权重除以低分辨率图的学习权重得到的,数据集为 coco val2017。

可以看出,scale-aware attention 模块会调节高分辨率图向低分辨率图,低分辨率图向高分辨率图,来平滑尺度的不同。这足以证明 scale-aware attention 的学习能力。

在这里插入图片描述

图 4 展示了使用不同数量的 attention 模块的效果,使用 attention 模块之前,特征图有更多的噪声,且难以注意到前景目标。使用 attention 模块之后,网络会更加注意到前景目标上和突变区域位置,这足以证明 spatial-aware attention 的学习能力。

3、Head 深度的探索

作者验证了不同 dynamic head 深度的效果,并且对比了其效果和计算量,如表 2 所示。

head 效果可以提升,直到数量上升到 8,并且增加的计算量可以忽略不计。

在这里插入图片描述

4、和现有目标检测器的适配

作者将其应用到了 RCNN、RetinaNet、ATSS、FCOS、ReoPoints,普遍带来了 1.2~3.2 AP 的提升。

在这里插入图片描述

5、和 SOTA 的比较

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

四、代码

以 ATSS 代码为例

  • 输入图像假设为: [4, 3, 896, 1152]
  • 经过 backbone 得到金字塔特征图,取 p3-p7:[4, 256, 112, 160], [4, 256, 56, 80], [4, 256, 28, 40], [4, 256, 14, 20], [4, 256, 7, 10]
  • 将该金字塔特征图输入 dynamic head:
import torch
import torch.nn.functional as F
from torch import nn

from detectron2.modeling.backbone import Backbone

from .deform import ModulatedDeformConv
from .dyrelu import h_sigmoid, DYReLU


class Conv3x3Norm(torch.nn.Module):
    def __init__(self, in_channels, out_channels, stride):
        super(Conv3x3Norm, self).__init__()

        self.conv = ModulatedDeformConv(in_channels, out_channels, kernel_size=3, stride=stride, padding=1)
        self.bn = nn.GroupNorm(num_groups=16, num_channels=out_channels)

    def forward(self, input, **kwargs):
        x = self.conv(input.contiguous(), **kwargs)
        x = self.bn(x)
        return x


class DyConv(nn.Module):
    def __init__(self, in_channels=256, out_channels=256, conv_func=Conv3x3Norm):
        super(DyConv, self).__init__()

        self.DyConv = nn.ModuleList()
        self.DyConv.append(conv_func(in_channels, out_channels, 1))
        self.DyConv.append(conv_func(in_channels, out_channels, 1))
        self.DyConv.append(conv_func(in_channels, out_channels, 2))

        self.AttnConv = nn.Sequential(
            nn.AdaptiveAvgPool2d(1),
            nn.Conv2d(in_channels, 1, kernel_size=1),
            nn.ReLU(inplace=True))

        self.h_sigmoid = h_sigmoid()
        self.relu = DYReLU(in_channels, out_channels)
        self.offset = nn.Conv2d(in_channels, 27, kernel_size=3, stride=1, padding=1)
        self.init_weights()

    def init_weights(self):
        for m in self.DyConv.modules():
            if isinstance(m, nn.Conv2d):
                nn.init.normal_(m.weight.data, 0, 0.01)
                if m.bias is not None:
                    m.bias.data.zero_()
        for m in self.AttnConv.modules():
            if isinstance(m, nn.Conv2d):
                nn.init.normal_(m.weight.data, 0, 0.01)
                if m.bias is not None:
                    m.bias.data.zero_()

    def forward(self, x):
        next_x = {}
        feature_names = list(x.keys()) # ['p3', 'p4', 'p5', 'p6', 'p7']
        # [4, 256, 112, 160], [4, 256, 56, 80], [4, 256, 28, 40], [4, 256, 14, 20], [4, 256, 7, 10]
        for level, name in enumerate(feature_names):

            feature = x[name]

            offset_mask = self.offset(feature) # [4, 27, 112, 160]
            offset = offset_mask[:, :18, :, :] # [4, 18, 112, 160]
            mask = offset_mask[:, 18:, :, :].sigmoid() # [4, 9, 112, 160]
            conv_args = dict(offset=offset, mask=mask)

            temp_fea = [self.DyConv[1](feature, **conv_args)] # [4, 256, 112, 160]
            # level=0: len(temp_fea)=2, temp_fea 是 level 0、level 1 特征组合得到的
            # level=1: len(temp_fea)=3, temp_fea 是 level 0、level 1 和 level 2 特征组合得到的
            # level=2: len(temp_fea)=3, temp_fea 是 level 1、level 2 和 level 3 特征组合得到的
            # level=3: len(temp_fea)=3, temp_fea 是 level 2、level 3 和 level 4 特征组合得到的
            # level=4: len(temp_fea)=2, temp_fea 是 level 3、level 4 特征组合得到的
            if level > 0:
                temp_fea.append(self.DyConv[2](x[feature_names[level - 1]], **conv_args))
            if level < len(x) - 1:
                temp_fea.append(F.upsample_bilinear(self.DyConv[0](x[feature_names[level + 1]], **conv_args),
                                                    size=[feature.size(2), feature.size(3)])) # len(temp_fea)=2, temp_fea[0]=temp_fea[1]=[4, 256, 112, 160]
            attn_fea = []
            res_fea = []
            for fea in temp_fea:
                res_fea.append(fea) # len=2, res_fea[0] = [4, 256, 112, 160]
                attn_fea.append(self.AttnConv(fea)) # attn_fea[0] =[4, 1, 1, 1]

            res_fea = torch.stack(res_fea) # level=0: [2, 4, 256, 112, 160], level=1: [3, 4, 256, 56, 80],
            spa_pyr_attn = self.h_sigmoid(torch.stack(attn_fea)) # [2, 4, 1, 1, 1]
            mean_fea = torch.mean(res_fea * spa_pyr_attn, dim=0, keepdim=False) # [4, 256, 112, 160]
            next_x[name] = self.relu(mean_fea)

        return next_x # [4, 256, 112, 160], [4, 256, 56, 80], [4, 256, 28, 40], [4, 256, 14, 20], [4, 256, 7, 10]


class DyHead(Backbone):
    def __init__(self, cfg, backbone):
        super(DyHead, self).__init__()
        self.cfg = cfg
        self.backbone = backbone
        in_channels = cfg.MODEL.FPN.OUT_CHANNELS
        channels = cfg.MODEL.DYHEAD.CHANNELS

        dyhead_tower = []
        for i in range(cfg.MODEL.DYHEAD.NUM_CONVS):
            dyhead_tower.append(
                DyConv(
                    in_channels if i == 0 else channels,
                    channels,
                    conv_func=Conv3x3Norm,
                )
            )

        self.add_module('dyhead_tower', nn.Sequential(*dyhead_tower))

        self._out_feature_strides = self.backbone._out_feature_strides
        self._out_features = list(self._out_feature_strides.keys())
        self._out_feature_channels = {k: channels for k in self._out_features}
        self._size_divisibility = list(self._out_feature_strides.values())[-1]

    @property
    def size_divisibility(self):
        return self._size_divisibility

    def forward(self, x):
        x = self.backbone(x)
        dyhead_tower = self.dyhead_tower(x)
        return dyhead_tower
 (dyhead_tower): Sequential(
    (0): DyConv(
      (DyConv): ModuleList(
        (0): Conv3x3Norm(
          (conv): ModulatedDeformConv(in_channels=256, out_channels=256, kernel_size=(3, 3), stride=1, dilation=1, padding=1, groups=1, deformable_groups=1, bias=True)
          (bn): GroupNorm(16, 256, eps=1e-05, affine=True)
        )
        (1): Conv3x3Norm(
          (conv): ModulatedDeformConv(in_channels=256, out_channels=256, kernel_size=(3, 3), stride=1, dilation=1, padding=1, groups=1, deformable_groups=1, bias=True)
          (bn): GroupNorm(16, 256, eps=1e-05, affine=True)
        )
        (2): Conv3x3Norm(
          (conv): ModulatedDeformConv(in_channels=256, out_channels=256, kernel_size=(3, 3), stride=2, dilation=1, padding=1, groups=1, deformable_groups=1, bias=True)
          (bn): GroupNorm(16, 256, eps=1e-05, affine=True)
        )
      )
      (AttnConv): Sequential(
        (0): AdaptiveAvgPool2d(output_size=1)
        (1): Conv2d(256, 1, kernel_size=(1, 1), stride=(1, 1))
        (2): ReLU(inplace=True)
      )
      (h_sigmoid): h_sigmoid(
        (relu): ReLU6(inplace=True)
      )
      (relu): DYReLU(
        (avg_pool): AdaptiveAvgPool2d(output_size=1)
        (fc): Sequential(
          (0): Linear(in_features=256, out_features=64, bias=True)
          (1): ReLU(inplace=True)
          (2): Linear(in_features=64, out_features=1024, bias=True)
          (3): h_sigmoid(
            (relu): ReLU6(inplace=True)
          )
        )
      )
      (offset): Conv2d(256, 27, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    )
    (1): DyConv(
      (DyConv): ModuleList(
        (0): Conv3x3Norm(
          (conv): ModulatedDeformConv(in_channels=256, out_channels=256, kernel_size=(3, 3), stride=1, dilation=1, padding=1, groups=1, deformable_groups=1, bias=True)
          (bn): GroupNorm(16, 256, eps=1e-05, affine=True)
        )
        (1): Conv3x3Norm(
          (conv): ModulatedDeformConv(in_channels=256, out_channels=256, kernel_size=(3, 3), stride=1, dilation=1, padding=1, groups=1, deformable_groups=1, bias=True)
          (bn): GroupNorm(16, 256, eps=1e-05, affine=True)
        )
        (2): Conv3x3Norm(
          (conv): ModulatedDeformConv(in_channels=256, out_channels=256, kernel_size=(3, 3), stride=2, dilation=1, padding=1, groups=1, deformable_groups=1, bias=True)
          (bn): GroupNorm(16, 256, eps=1e-05, affine=True)
        )
      )
      (AttnConv): Sequential(
        (0): AdaptiveAvgPool2d(output_size=1)
        (1): Conv2d(256, 1, kernel_size=(1, 1), stride=(1, 1))
        (2): ReLU(inplace=True)
      )
      (h_sigmoid): h_sigmoid(
        (relu): ReLU6(inplace=True)
      )
      (relu): DYReLU(
        (avg_pool): AdaptiveAvgPool2d(output_size=1)
        (fc): Sequential(
          (0): Linear(in_features=256, out_features=64, bias=True)
          (1): ReLU(inplace=True)
          (2): Linear(in_features=64, out_features=1024, bias=True)
          (3): h_sigmoid(
            (relu): ReLU6(inplace=True)
          )
        )
      )
      (offset): Conv2d(256, 27, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    )
    (2): DyConv(
      (DyConv): ModuleList(
        (0): Conv3x3Norm(
          (conv): ModulatedDeformConv(in_channels=256, out_channels=256, kernel_size=(3, 3), stride=1, dilation=1, padding=1, groups=1, deformable_groups=1, bias=True)
          (bn): GroupNorm(16, 256, eps=1e-05, affine=True)
        )
        (1): Conv3x3Norm(
          (conv): ModulatedDeformConv(in_channels=256, out_channels=256, kernel_size=(3, 3), stride=1, dilation=1, padding=1, groups=1, deformable_groups=1, bias=True)
          (bn): GroupNorm(16, 256, eps=1e-05, affine=True)
        )
        (2): Conv3x3Norm(
          (conv): ModulatedDeformConv(in_channels=256, out_channels=256, kernel_size=(3, 3), stride=2, dilation=1, padding=1, groups=1, deformable_groups=1, bias=True)
          (bn): GroupNorm(16, 256, eps=1e-05, affine=True)
        )
      )
      (AttnConv): Sequential(
        (0): AdaptiveAvgPool2d(output_size=1)
        (1): Conv2d(256, 1, kernel_size=(1, 1), stride=(1, 1))
        (2): ReLU(inplace=True)
      )
      (h_sigmoid): h_sigmoid(
        (relu): ReLU6(inplace=True)
      )
      (relu): DYReLU(
        (avg_pool): AdaptiveAvgPool2d(output_size=1)
        (fc): Sequential(
          (0): Linear(in_features=256, out_features=64, bias=True)
          (1): ReLU(inplace=True)
          (2): Linear(in_features=64, out_features=1024, bias=True)
          (3): h_sigmoid(
            (relu): ReLU6(inplace=True)
          )
        )
      )
      (offset): Conv2d(256, 27, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    )
    (3): DyConv(
      (DyConv): ModuleList(
        (0): Conv3x3Norm(
          (conv): ModulatedDeformConv(in_channels=256, out_channels=256, kernel_size=(3, 3), stride=1, dilation=1, padding=1, groups=1, deformable_groups=1, bias=True)
          (bn): GroupNorm(16, 256, eps=1e-05, affine=True)
        )
        (1): Conv3x3Norm(
          (conv): ModulatedDeformConv(in_channels=256, out_channels=256, kernel_size=(3, 3), stride=1, dilation=1, padding=1, groups=1, deformable_groups=1, bias=True)
          (bn): GroupNorm(16, 256, eps=1e-05, affine=True)
        )
        (2): Conv3x3Norm(
          (conv): ModulatedDeformConv(in_channels=256, out_channels=256, kernel_size=(3, 3), stride=2, dilation=1, padding=1, groups=1, deformable_groups=1, bias=True)
          (bn): GroupNorm(16, 256, eps=1e-05, affine=True)
        )
      )
      (AttnConv): Sequential(
        (0): AdaptiveAvgPool2d(output_size=1)
        (1): Conv2d(256, 1, kernel_size=(1, 1), stride=(1, 1))
        (2): ReLU(inplace=True)
      )
      (h_sigmoid): h_sigmoid(
        (relu): ReLU6(inplace=True)
      )
      (relu): DYReLU(
        (avg_pool): AdaptiveAvgPool2d(output_size=1)
        (fc): Sequential(
          (0): Linear(in_features=256, out_features=64, bias=True)
          (1): ReLU(inplace=True)
          (2): Linear(in_features=64, out_features=1024, bias=True)
          (3): h_sigmoid(
            (relu): ReLU6(inplace=True)
          )
        )
      )
      (offset): Conv2d(256, 27, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    )
    (4): DyConv(
      (DyConv): ModuleList(
        (0): Conv3x3Norm(
          (conv): ModulatedDeformConv(in_channels=256, out_channels=256, kernel_size=(3, 3), stride=1, dilation=1, padding=1, groups=1, deformable_groups=1, bias=True)
          (bn): GroupNorm(16, 256, eps=1e-05, affine=True)
        )
        (1): Conv3x3Norm(
          (conv): ModulatedDeformConv(in_channels=256, out_channels=256, kernel_size=(3, 3), stride=1, dilation=1, padding=1, groups=1, deformable_groups=1, bias=True)
          (bn): GroupNorm(16, 256, eps=1e-05, affine=True)
        )
        (2): Conv3x3Norm(
          (conv): ModulatedDeformConv(in_channels=256, out_channels=256, kernel_size=(3, 3), stride=2, dilation=1, padding=1, groups=1, deformable_groups=1, bias=True)
          (bn): GroupNorm(16, 256, eps=1e-05, affine=True)
        )
      )
      (AttnConv): Sequential(
        (0): AdaptiveAvgPool2d(output_size=1)
        (1): Conv2d(256, 1, kernel_size=(1, 1), stride=(1, 1))
        (2): ReLU(inplace=True)
      )
      (h_sigmoid): h_sigmoid(
        (relu): ReLU6(inplace=True)
      )
      (relu): DYReLU(
        (avg_pool): AdaptiveAvgPool2d(output_size=1)
        (fc): Sequential(
          (0): Linear(in_features=256, out_features=64, bias=True)
          (1): ReLU(inplace=True)
          (2): Linear(in_features=64, out_features=1024, bias=True)
          (3): h_sigmoid(
            (relu): ReLU6(inplace=True)
          )
        )
      )
      (offset): Conv2d(256, 27, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    )
    (5): DyConv(
      (DyConv): ModuleList(
        (0): Conv3x3Norm(
          (conv): ModulatedDeformConv(in_channels=256, out_channels=256, kernel_size=(3, 3), stride=1, dilation=1, padding=1, groups=1, deformable_groups=1, bias=True)
          (bn): GroupNorm(16, 256, eps=1e-05, affine=True)
        )
        (1): Conv3x3Norm(
          (conv): ModulatedDeformConv(in_channels=256, out_channels=256, kernel_size=(3, 3), stride=1, dilation=1, padding=1, groups=1, deformable_groups=1, bias=True)
          (bn): GroupNorm(16, 256, eps=1e-05, affine=True)
        )
        (2): Conv3x3Norm(
          (conv): ModulatedDeformConv(in_channels=256, out_channels=256, kernel_size=(3, 3), stride=2, dilation=1, padding=1, groups=1, deformable_groups=1, bias=True)
          (bn): GroupNorm(16, 256, eps=1e-05, affine=True)
        )
      )
      (AttnConv): Sequential(
        (0): AdaptiveAvgPool2d(output_size=1)
        (1): Conv2d(256, 1, kernel_size=(1, 1), stride=(1, 1))
        (2): ReLU(inplace=True)
      )
      (h_sigmoid): h_sigmoid(
        (relu): ReLU6(inplace=True)
      )
      (relu): DYReLU(
        (avg_pool): AdaptiveAvgPool2d(output_size=1)
        (fc): Sequential(
          (0): Linear(in_features=256, out_features=64, bias=True)
          (1): ReLU(inplace=True)
          (2): Linear(in_features=64, out_features=1024, bias=True)
          (3): h_sigmoid(
            (relu): ReLU6(inplace=True)
          )
        )
      )
      (offset): Conv2d(256, 27, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    )
  )
)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/393061.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

一文带你了解阿里的开源Java诊断工具 :Arthas

Arthas 是阿里开源的 Java 诊断工具&#xff0c;相比 JDK 内置的诊断工具&#xff0c;要更人性化&#xff0c;并且功能强大&#xff0c;可以实现许多问题的一键定位&#xff0c;是我用到的最方便的诊断工具。 下载和安装见官网 https://arthas.aliyun.com/doc/profiler.html 下…

Gem5模拟器,如何在linux系统中查看内存、CPU、硬盘、进程、网络等信息(十二)

虽然说&#xff0c;这个记录的是与Linux相关的操作&#xff0c;每次查每次忘&#xff0c;必须写一个来归总一下&#xff0c;以免我漫山遍野找命令。但是不想新开一一个主题&#xff0c;再加上确实是在运行模拟器时会关注这方面的信息&#xff0c;就把这一节搁这儿啦。 常见的查…

MedCalc v20.217 医学ROC曲线统计分析参考软件

MedCalc是一款医学 ROC 曲线统计软件,用于ROC曲线分析的参考软件,医学工作者设计的医学计算器,功能齐全。它可以帮助医生快速作出普通的医学计算,从而对症下药。提供超过76种常用的规则和方法,包括:病人数据、单位参数、费用计算等等。甚至可以将图形另存为BMP,PNG,GIF…

ATL中__if_exists的替代方案

__if_exists 和 __if_not_exists 是什么? __if_exists 和 __if_not_exists 是微软 ATL (Active Template Library&#xff0c;活动模板库) 中的关键字&#xff0c;可以用来在编译期间测试一个标识符是否存在。如果该标识符存在&#xff0c;则其关联的语句将会被执行。 __if_e…

2023年3月软考中级(系统集成项目管理工程师)报名走起!!!

系统集成项目管理工程师是全国计算机技术与软件专业技术资格&#xff08;水平&#xff09;考试&#xff08;简称软考&#xff09;项目之一&#xff0c;是由国家人力资源和社会保障部、工业和信息化部共同组织的国家级考试&#xff0c;既属于国家职业资格考试&#xff0c;又是职…

【Vue】Vue常见的6种指令

Vue的6种指令-前言指令&#xff08;Directives&#xff09;是vue 为开发者提供的模板语法&#xff0c;用于辅助开发者渲染页面的基本结构。vue 中的指令按照不同的用途可以分为如下6 大类① 内容渲染指令 ② 属性绑定指令 ③ 事件绑定指令 ④ 双向绑定指令 ⑤ 条件渲染指令 ⑥ …

Fortinet设备审计

作为网络安全领域的领导者&#xff0c;Fortinet提供了多种网络安全解决方案&#xff0c;包括下一代防火墙&#xff0c;即FortiGate。通过EventLog Analyzer的FortiGate预定义报表以及其他Fortinet应用程序的详尽列表&#xff0c;充分发挥Fortinet设备的最大作用。FortiGate您的…

粒子群算法

粒子群算法1 粒子群算法介绍2 基本思想3 算法流程4 代码实现1 粒子群算法介绍 粒子群优化算法(PSO&#xff1a;Particle swarm optimization) 是一种进化计算技术&#xff08;evolutionary computation&#xff09;。源于对鸟群捕食的行为研究。粒子群优化算法的基本思想是通过…

我建议,专家不要再建议了

作者| Mr.K 编辑| Emma来源| 技术领导力(ID&#xff1a;jishulingdaoli)关于买房&#xff0c;专家建议&#xff1a;不建议掏空六个钱包凑首付。&#xff08;网友&#xff1a;丈母娘等不到我自己挣够&#xff09;关于农村剩男多&#xff0c;城市剩女多&#xff0c;专家建议&am…

Adobe illustrator学习笔记

Adobe illustrator学习笔记 生命有限&#xff0c;设计无限 学习Adobe illustrator主要是用来制作SVG图片去制作字体图标&#xff0c;因此笔记内容大多会围绕SVG展开。 2023-3-5 1、Adobe illustrator简介 主要用于制作矢量图和插图 2、颜色模式介绍 显示颜色&#xff1a;RGB…

EXCEL里的各种奇怪计算问题:数字后面自动多了 0.0001, 数字后面位数变成000,以及一些取整,数学函数

1 公式计算后的数&#xff0c;用只粘贴数值后&#xff0c;后面自动多了 0.0001&#xff0c;导致不再是整数的问题 问题入戏 见第1个8400&#xff0c;计算时就出现了问题&#xff0c;按正常&#xff0c;这里8400应该是整数&#xff0c;而不应该带小数&#xff0c;但是确实就计…

我不写单元测试,被批了

我是3y&#xff0c;一年CRUD经验用十年的markdown程序员&#x1f468;&#x1f3fb;‍&#x1f4bb;常年被誉为职业八股文选手最近在看单元测试的东西&#xff0c;想跟大家聊聊我的感受。单元测试这块说实在的&#xff0c;我并不太熟悉&#xff0c;我几乎不写单元测试&#xff…

项目中维护一个随时更新的ui库的解决方案之一(uniapp+uview-plus)

1. 环境准备 需要准备两个仓库&#xff0c;第一个仓库用来存uniapp项目的相关代码&#xff0c;第二个用来存放uview-plus UI库的代码&#xff08;第二个仓库的仓库名称为uview-plus&#xff09; 2. 项目结构 我们uniapp目录结构大致如下 我们维护的ui组件应该是uni_modules下…

详解JAVA类加载器

目录 1.概述 2.双亲委派 3.ServiceClassLoader 4.URLClassLoader 5.加载冲突 1.概述 概念&#xff1a; 类加载器&#xff08;Class Loader&#xff09;是Java虚拟机&#xff08;JVM&#xff09;的一个重要组件&#xff0c;负责加载Java类到内存中并使其可以被JVM执行。类…

抢先看!界面控件DevExtreme 2023产品路线图曝光

DevExtreme拥有高性能的HTML5 / JavaScript小部件集合&#xff0c;使您可以利用现代Web开发堆栈&#xff08;包括React&#xff0c;Angular&#xff0c;ASP.NET Core&#xff0c;jQuery&#xff0c;Knockout等&#xff09;构建交互式的Web应用程序&#xff0c;该套件附带功能齐…

【C++】优先级队列 priority_queue,仿函数和函数对象,反向迭代器

目录 1.介绍和实现 2.仿函数和函数对象 3.oj 4.反向迭代器 1.介绍和实现 他也在<queue>的头文件里 但是他的底层是堆&#xff0c;并不满足先入先出&#xff08;不要一看到queue就先入先出&#xff09; 他也是一个容器适配器&#xff0c;用vector适配的&#xff0c;为…

利用Qemu工具仿真ARM64平台

Windows系统利用Qemu仿真ARM64平台0 写在最前1 Windows安装Qemu1.1 下载Qemu1.2 安装Qemu1.3 添加环境变量1.4测试安装是否成功2. Qemu安装Ubuntu-Server-Arm-642.1 安装前的准备2.2 安装Ubuntu server arm 64位镜像3 Windows配置Qemu网络和传输文件3.1 参考内容3.2 Windows安装…

数据湖架构Hudi(五)Hudi集成Flink案例详解

五、Hudi集成Flink案例详解 5.1 hudi集成flink flink的下载地址&#xff1a; https://archive.apache.org/dist/flink/ HudiSupported Flink version0.12.x1.15.x、1.14.x、1.13.x0.11.x1.14.x、1.13.x0.10.x1.13.x0.9.01.12.2 将上述编译好的安装包拷贝到flink下的jars目录…

Python(青铜时代)——字符串

字符串的定义与操作 字符串就是 一串字符 &#xff0c;是编程语言中表示文本的数据类型 在Python中使用一对双引号 "" 或者一对单引号来定义. 使用索引获取一个字符串中 指定位置的字符&#xff0c;索引计数从0开始 可以用 for/while 循环遍历字符串中的每一个字符…

NGINX学习笔记(一):一篇了解NGINX的基本概念

NGINX是什么&#xff1f; NGINX是一款由俄罗斯人伊戈尔赛索耶夫使用C语言开发的、支持热部署的、轻量级的WEB服务器/反向代理服务器/电子邮件代理服务器&#xff0c;因为占用内存较少&#xff0c;启动极快&#xff0c;高并发能力强&#xff0c;所以在互联网项目中广泛应用。可…