更换目标检测的backbone(以Faster RCNN为例)_frozenbatchnorm2d

先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7

深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新Linux运维全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上运维知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以添加V获取:vip1024b (备注运维)
img

正文

      (2): SqueezeExcitation(
        (avgpool): AdaptiveAvgPool2d(output_size=1)
        (fc1): Conv2d(96, 4, kernel\_size=(1, 1), stride=(1, 1))
        (fc2): Conv2d(4, 96, kernel\_size=(1, 1), stride=(1, 1))
        (activation): SiLU(inplace=True)
        (scale_activation): Sigmoid()
      )
      (3): ConvNormActivation(
        (0): Conv2d(96, 24, kernel\_size=(1, 1), stride=(1, 1), bias=False)
        (1): BatchNorm2d(24, eps=1e-05, momentum=0.1, affine=True, track\_running\_stats=True)
      )
    )
    (stochastic_depth): StochasticDepth(p=0.0125, mode=row)
  )
  (1): MBConv(
    (block): Sequential(
      (0): ConvNormActivation(
        (0): Conv2d(24, 144, kernel\_size=(1, 1), stride=(1, 1), bias=False)
        (1): BatchNorm2d(144, eps=1e-05, momentum=0.1, affine=True, track\_running\_stats=True)
        (2): SiLU(inplace=True)
      )
      (1): ConvNormActivation(
        (0): Conv2d(144, 144, kernel\_size=(3, 3), stride=(1, 1), padding=(1, 1), groups=144, bias=False)
        (1): BatchNorm2d(144, eps=1e-05, momentum=0.1, affine=True, track\_running\_stats=True)
        (2): SiLU(inplace=True)
      )
      (2): SqueezeExcitation(
        (avgpool): AdaptiveAvgPool2d(output_size=1)
        (fc1): Conv2d(144, 6, kernel\_size=(1, 1), stride=(1, 1))
        (fc2): Conv2d(6, 144, kernel\_size=(1, 1), stride=(1, 1))
        (activation): SiLU(inplace=True)
        (scale_activation): Sigmoid()
      )
      (3): ConvNormActivation(
        (0): Conv2d(144, 24, kernel\_size=(1, 1), stride=(1, 1), bias=False)
        (1): BatchNorm2d(24, eps=1e-05, momentum=0.1, affine=True, track\_running\_stats=True)
      )
    )
    (stochastic_depth): StochasticDepth(p=0.025, mode=row)
  )
)
(3): Sequential(
  (0): MBConv(
    (block): Sequential(
      (0): ConvNormActivation(
        (0): Conv2d(24, 144, kernel\_size=(1, 1), stride=(1, 1), bias=False)
        (1): BatchNorm2d(144, eps=1e-05, momentum=0.1, affine=True, track\_running\_stats=True)
        (2): SiLU(inplace=True)
      )
      (1): ConvNormActivation(
        (0): Conv2d(144, 144, kernel\_size=(5, 5), stride=(2, 2), padding=(2, 2), groups=144, bias=False)
        (1): BatchNorm2d(144, eps=1e-05, momentum=0.1, affine=True, track\_running\_stats=True)
        (2): SiLU(inplace=True)
      )
      (2): SqueezeExcitation(
        (avgpool): AdaptiveAvgPool2d(output_size=1)
        (fc1): Conv2d(144, 6, kernel\_size=(1, 1), stride=(1, 1))
        (fc2): Conv2d(6, 144, kernel\_size=(1, 1), stride=(1, 1))
        (activation): SiLU(inplace=True)
        (scale_activation): Sigmoid()
      )
      (3): ConvNormActivation(
        (0): Conv2d(144, 40, kernel\_size=(1, 1), stride=(1, 1), bias=False)
        (1): BatchNorm2d(40, eps=1e-05, momentum=0.1, affine=True, track\_running\_stats=True)
      )
    )
    (stochastic_depth): StochasticDepth(p=0.037500000000000006, mode=row)
  )
  (1): MBConv(
    (block): Sequential(
      (0): ConvNormActivation(
        (0): Conv2d(40, 240, kernel\_size=(1, 1), stride=(1, 1), bias=False)
        (1): BatchNorm2d(240, eps=1e-05, momentum=0.1, affine=True, track\_running\_stats=True)
        (2): SiLU(inplace=True)
      )
      (1): ConvNormActivation(
        (0): Conv2d(240, 240, kernel\_size=(5, 5), stride=(1, 1), padding=(2, 2), groups=240, bias=False)
        (1): BatchNorm2d(240, eps=1e-05, momentum=0.1, affine=True, track\_running\_stats=True)
        (2): SiLU(inplace=True)
      )
      (2): SqueezeExcitation(
        (avgpool): AdaptiveAvgPool2d(output_size=1)
        (fc1): Conv2d(240, 10, kernel\_size=(1, 1), stride=(1, 1))
        (fc2): Conv2d(10, 240, kernel\_size=(1, 1), stride=(1, 1))
        (activation): SiLU(inplace=True)
        (scale_activation): Sigmoid()
      )
      (3): ConvNormActivation(
        (0): Conv2d(240, 40, kernel\_size=(1, 1), stride=(1, 1), bias=False)
        (1): BatchNorm2d(40, eps=1e-05, momentum=0.1, affine=True, track\_running\_stats=True)
      )
    )
    (stochastic_depth): StochasticDepth(p=0.05, mode=row)
  )
)
(4): Sequential(
  (0): MBConv(
    (block): Sequential(
      (0): ConvNormActivation(
        (0): Conv2d(40, 240, kernel\_size=(1, 1), stride=(1, 1), bias=False)
        (1): BatchNorm2d(240, eps=1e-05, momentum=0.1, affine=True, track\_running\_stats=True)
        (2): SiLU(inplace=True)
      )
      (1): ConvNormActivation(
        (0): Conv2d(240, 240, kernel\_size=(3, 3), stride=(2, 2), padding=(1, 1), groups=240, bias=False)
        (1): BatchNorm2d(240, eps=1e-05, momentum=0.1, affine=True, track\_running\_stats=True)
        (2): SiLU(inplace=True)
      )
      (2): SqueezeExcitation(
        (avgpool): AdaptiveAvgPool2d(output_size=1)
        (fc1): Conv2d(240, 10, kernel\_size=(1, 1), stride=(1, 1))
        (fc2): Conv2d(10, 240, kernel\_size=(1, 1), stride=(1, 1))
        (activation): SiLU(inplace=True)
        (scale_activation): Sigmoid()
      )
      (3): ConvNormActivation(
        (0): Conv2d(240, 80, kernel\_size=(1, 1), stride=(1, 1), bias=False)
        (1): BatchNorm2d(80, eps=1e-05, momentum=0.1, affine=True, track\_running\_stats=True)
      )
    )
    (stochastic_depth): StochasticDepth(p=0.0625, mode=row)
  )
  (1): MBConv(
    (block): Sequential(
      (0): ConvNormActivation(
        (0): Conv2d(80, 480, kernel\_size=(1, 1), stride=(1, 1), bias=False)
        (1): BatchNorm2d(480, eps=1e-05, momentum=0.1, affine=True, track\_running\_stats=True)
        (2): SiLU(inplace=True)
      )
      (1): ConvNormActivation(
        (0): Conv2d(480, 480, kernel\_size=(3, 3), stride=(1, 1), padding=(1, 1), groups=480, bias=False)
        (1): BatchNorm2d(480, eps=1e-05, momentum=0.1, affine=True, track\_running\_stats=True)
        (2): SiLU(inplace=True)
      )
      (2): SqueezeExcitation(
        (avgpool): AdaptiveAvgPool2d(output_size=1)
        (fc1): Conv2d(480, 20, kernel\_size=(1, 1), stride=(1, 1))
        (fc2): Conv2d(20, 480, kernel\_size=(1, 1), stride=(1, 1))
        (activation): SiLU(inplace=True)
        (scale_activation): Sigmoid()
      )
      (3): ConvNormActivation(
        (0): Conv2d(480, 80, kernel\_size=(1, 1), stride=(1, 1), bias=False)
        (1): BatchNorm2d(80, eps=1e-05, momentum=0.1, affine=True, track\_running\_stats=True)
      )
    )
    (stochastic_depth): StochasticDepth(p=0.07500000000000001, mode=row)
  )
  (2): MBConv(
    (block): Sequential(
      (0): ConvNormActivation(
        (0): Conv2d(80, 480, kernel\_size=(1, 1), stride=(1, 1), bias=False)
        (1): BatchNorm2d(480, eps=1e-05, momentum=0.1, affine=True, track\_running\_stats=True)
        (2): SiLU(inplace=True)
      )
      (1): ConvNormActivation(
        (0): Conv2d(480, 480, kernel\_size=(3, 3), stride=(1, 1), padding=(1, 1), groups=480, bias=False)
        (1): BatchNorm2d(480, eps=1e-05, momentum=0.1, affine=True, track\_running\_stats=True)
        (2): SiLU(inplace=True)
      )
      (2): SqueezeExcitation(
        (avgpool): AdaptiveAvgPool2d(output_size=1)
        (fc1): Conv2d(480, 20, kernel\_size=(1, 1), stride=(1, 1))
        (fc2): Conv2d(20, 480, kernel\_size=(1, 1), stride=(1, 1))
        (activation): SiLU(inplace=True)
        (scale_activation): Sigmoid()
      )
      (3): ConvNormActivation(
        (0): Conv2d(480, 80, kernel\_size=(1, 1), stride=(1, 1), bias=False)
        (1): BatchNorm2d(80, eps=1e-05, momentum=0.1, affine=True, track\_running\_stats=True)
      )
    )
    (stochastic_depth): StochasticDepth(p=0.08750000000000001, mode=row)
  )
)
(5): Sequential(
  (0): MBConv(
    (block): Sequential(
      (0): ConvNormActivation(
        (0): Conv2d(80, 480, kernel\_size=(1, 1), stride=(1, 1), bias=False)
        (1): BatchNorm2d(480, eps=1e-05, momentum=0.1, affine=True, track\_running\_stats=True)
        (2): SiLU(inplace=True)
      )
      (1): ConvNormActivation(
        (0): Conv2d(480, 480, kernel\_size=(5, 5), stride=(1, 1), padding=(2, 2), groups=480, bias=False)
        (1): BatchNorm2d(480, eps=1e-05, momentum=0.1, affine=True, track\_running\_stats=True)
        (2): SiLU(inplace=True)
      )
      (2): SqueezeExcitation(
        (avgpool): AdaptiveAvgPool2d(output_size=1)
        (fc1): Conv2d(480, 20, kernel\_size=(1, 1), stride=(1, 1))
        (fc2): Conv2d(20, 480, kernel\_size=(1, 1), stride=(1, 1))
        (activation): SiLU(inplace=True)
        (scale_activation): Sigmoid()
      )
      (3): ConvNormActivation(
        (0): Conv2d(480, 112, kernel\_size=(1, 1), stride=(1, 1), bias=False)
        (1): BatchNorm2d(112, eps=1e-05, momentum=0.1, affine=True, track\_running\_stats=True)
      )
    )
    (stochastic_depth): StochasticDepth(p=0.1, mode=row)
  )
  (1): MBConv(
    (block): Sequential(
      (0): ConvNormActivation(
        (0): Conv2d(112, 672, kernel\_size=(1, 1), stride=(1, 1), bias=False)
        (1): BatchNorm2d(672, eps=1e-05, momentum=0.1, affine=True, track\_running\_stats=True)
        (2): SiLU(inplace=True)
      )
      (1): ConvNormActivation(
        (0): Conv2d(672, 672, kernel\_size=(5, 5), stride=(1, 1), padding=(2, 2), groups=672, bias=False)
        (1): BatchNorm2d(672, eps=1e-05, momentum=0.1, affine=True, track\_running\_stats=True)
        (2): SiLU(inplace=True)
      )
      (2): SqueezeExcitation(
        (avgpool): AdaptiveAvgPool2d(output_size=1)
        (fc1): Conv2d(672, 28, kernel\_size=(1, 1), stride=(1, 1))
        (fc2): Conv2d(28, 672, kernel\_size=(1, 1), stride=(1, 1))
        (activation): SiLU(inplace=True)
        (scale_activation): Sigmoid()
      )
      (3): ConvNormActivation(
        (0): Conv2d(672, 112, kernel\_size=(1, 1), stride=(1, 1), bias=False)
        (1): BatchNorm2d(112, eps=1e-05, momentum=0.1, affine=True, track\_running\_stats=True)
      )
    )
    (stochastic_depth): StochasticDepth(p=0.1125, mode=row)
  )
  (2): MBConv(
    (block): Sequential(
      (0): ConvNormActivation(
        (0): Conv2d(112, 672, kernel\_size=(1, 1), stride=(1, 1), bias=False)
        (1): BatchNorm2d(672, eps=1e-05, momentum=0.1, affine=True, track\_running\_stats=True)
        (2): SiLU(inplace=True)
      )
      (1): ConvNormActivation(
        (0): Conv2d(672, 672, kernel\_size=(5, 5), stride=(1, 1), padding=(2, 2), groups=672, bias=False)
        (1): BatchNorm2d(672, eps=1e-05, momentum=0.1, affine=True, track\_running\_stats=True)
        (2): SiLU(inplace=True)
      )
      (2): SqueezeExcitation(
        (avgpool): AdaptiveAvgPool2d(output_size=1)
        (fc1): Conv2d(672, 28, kernel\_size=(1, 1), stride=(1, 1))
        (fc2): Conv2d(28, 672, kernel\_size=(1, 1), stride=(1, 1))
        (activation): SiLU(inplace=True)
        (scale_activation): Sigmoid()
      )
      (3): ConvNormActivation(
        (0): Conv2d(672, 112, kernel\_size=(1, 1), stride=(1, 1), bias=False)
        (1): BatchNorm2d(112, eps=1e-05, momentum=0.1, affine=True, track\_running\_stats=True)
      )
    )
    (stochastic_depth): StochasticDepth(p=0.125, mode=row)
  )
)
(6): Sequential(
  (0): MBConv(
    (block): Sequential(
      (0): ConvNormActivation(
        (0): Conv2d(112, 672, kernel\_size=(1, 1), stride=(1, 1), bias=False)
        (1): BatchNorm2d(672, eps=1e-05, momentum=0.1, affine=True, track\_running\_stats=True)
        (2): SiLU(inplace=True)
      )
      (1): ConvNormActivation(
        (0): Conv2d(672, 672, kernel\_size=(5, 5), stride=(2, 2), padding=(2, 2), groups=672, bias=False)
        (1): BatchNorm2d(672, eps=1e-05, momentum=0.1, affine=True, track\_running\_stats=True)
        (2): SiLU(inplace=True)
      )
      (2): SqueezeExcitation(
        (avgpool): AdaptiveAvgPool2d(output_size=1)
        (fc1): Conv2d(672, 28, kernel\_size=(1, 1), stride=(1, 1))
        (fc2): Conv2d(28, 672, kernel\_size=(1, 1), stride=(1, 1))
        (activation): SiLU(inplace=True)
        (scale_activation): Sigmoid()
      )
      (3): ConvNormActivation(
        (0): Conv2d(672, 192, kernel\_size=(1, 1), stride=(1, 1), bias=False)
        (1): BatchNorm2d(192, eps=1e-05, momentum=0.1, affine=True, track\_running\_stats=True)
      )
    )
    (stochastic_depth): StochasticDepth(p=0.1375, mode=row)
  )
  (1): MBConv(
    (block): Sequential(
      (0): ConvNormActivation(
        (0): Conv2d(192, 1152, kernel\_size=(1, 1), stride=(1, 1), bias=False)
        (1): BatchNorm2d(1152, eps=1e-05, momentum=0.1, affine=True, track\_running\_stats=True)
        (2): SiLU(inplace=True)
      )
      (1): ConvNormActivation(
        (0): Conv2d(1152, 1152, kernel\_size=(5, 5), stride=(1, 1), padding=(2, 2), groups=1152, bias=False)
        (1): BatchNorm2d(1152, eps=1e-05, momentum=0.1, affine=True, track\_running\_stats=True)
        (2): SiLU(inplace=True)
      )
      (2): SqueezeExcitation(
        (avgpool): AdaptiveAvgPool2d(output_size=1)
        (fc1): Conv2d(1152, 48, kernel\_size=(1, 1), stride=(1, 1))
        (fc2): Conv2d(48, 1152, kernel\_size=(1, 1), stride=(1, 1))
        (activation): SiLU(inplace=True)
        (scale_activation): Sigmoid()
      )
      (3): ConvNormActivation(
        (0): Conv2d(1152, 192, kernel\_size=(1, 1), stride=(1, 1), bias=False)
        (1): BatchNorm2d(192, eps=1e-05, momentum=0.1, affine=True, track\_running\_stats=True)
      )
    )
    (stochastic_depth): StochasticDepth(p=0.15000000000000002, mode=row)
  )
  (2): MBConv(
    (block): Sequential(
      (0): ConvNormActivation(
        (0): Conv2d(192, 1152, kernel\_size=(1, 1), stride=(1, 1), bias=False)
        (1): BatchNorm2d(1152, eps=1e-05, momentum=0.1, affine=True, track\_running\_stats=True)
        (2): SiLU(inplace=True)
      )
      (1): ConvNormActivation(
        (0): Conv2d(1152, 1152, kernel\_size=(5, 5), stride=(1, 1), padding=(2, 2), groups=1152, bias=False)
        (1): BatchNorm2d(1152, eps=1e-05, momentum=0.1, affine=True, track\_running\_stats=True)
        (2): SiLU(inplace=True)
      )
      (2): SqueezeExcitation(
        (avgpool): AdaptiveAvgPool2d(output_size=1)
        (fc1): Conv2d(1152, 48, kernel\_size=(1, 1), stride=(1, 1))
        (fc2): Conv2d(48, 1152, kernel\_size=(1, 1), stride=(1, 1))
        (activation): SiLU(inplace=True)
        (scale_activation): Sigmoid()
      )
      (3): ConvNormActivation(
        (0): Conv2d(1152, 192, kernel\_size=(1, 1), stride=(1, 1), bias=False)
        (1): BatchNorm2d(192, eps=1e-05, momentum=0.1, affine=True, track\_running\_stats=True)
      )
    )
    (stochastic_depth): StochasticDepth(p=0.1625, mode=row)
  )
  (3): MBConv(
    (block): Sequential(
      (0): ConvNormActivation(
        (0): Conv2d(192, 1152, kernel\_size=(1, 1), stride=(1, 1), bias=False)
        (1): BatchNorm2d(1152, eps=1e-05, momentum=0.1, affine=True, track\_running\_stats=True)
        (2): SiLU(inplace=True)
      )
      (1): ConvNormActivation(
        (0): Conv2d(1152, 1152, kernel\_size=(5, 5), stride=(1, 1), padding=(2, 2), groups=1152, bias=False)
        (1): BatchNorm2d(1152, eps=1e-05, momentum=0.1, affine=True, track\_running\_stats=True)
        (2): SiLU(inplace=True)
      )
      (2): SqueezeExcitation(
        (avgpool): AdaptiveAvgPool2d(output_size=1)
        (fc1): Conv2d(1152, 48, kernel\_size=(1, 1), stride=(1, 1))
        (fc2): Conv2d(48, 1152, kernel\_size=(1, 1), stride=(1, 1))
        (activation): SiLU(inplace=True)
        (scale_activation): Sigmoid()
      )
      (3): ConvNormActivation(
        (0): Conv2d(1152, 192, kernel\_size=(1, 1), stride=(1, 1), bias=False)
        (1): BatchNorm2d(192, eps=1e-05, momentum=0.1, affine=True, track\_running\_stats=True)
      )
    )
    (stochastic_depth): StochasticDepth(p=0.17500000000000002, mode=row)
  )
)
(7): Sequential(
  (0): MBConv(
    (block): Sequential(
      (0): ConvNormActivation(
        (0): Conv2d(192, 1152, kernel\_size=(1, 1), stride=(1, 1), bias=False)
        (1): BatchNorm2d(1152, eps=1e-05, momentum=0.1, affine=True, track\_running\_stats=True)
        (2): SiLU(inplace=True)
      )
      (1): ConvNormActivation(
        (0): Conv2d(1152, 1152, kernel\_size=(3, 3), stride=(1, 1), padding=(1, 1), groups=1152, bias=False)
        (1): BatchNorm2d(1152, eps=1e-05, momentum=0.1, affine=True, track\_running\_stats=True)
        (2): SiLU(inplace=True)
      )
      (2): SqueezeExcitation(
        (avgpool): AdaptiveAvgPool2d(output_size=1)
        (fc1): Conv2d(1152, 48, kernel\_size=(1, 1), stride=(1, 1))
        (fc2): Conv2d(48, 1152, kernel\_size=(1, 1), stride=(1, 1))
        (activation): SiLU(inplace=True)
        (scale_activation): Sigmoid()
      )
      (3): ConvNormActivation(
        (0): Conv2d(1152, 320, kernel\_size=(1, 1), stride=(1, 1), bias=False)
        (1): BatchNorm2d(320, eps=1e-05, momentum=0.1, affine=True, track\_running\_stats=True)
      )
    )
    (stochastic_depth): StochasticDepth(p=0.1875, mode=row)
  )
)
(8): ConvNormActivation(
  (0): Conv2d(320, 1280, kernel\_size=(1, 1), stride=(1, 1), bias=False)
  (1): BatchNorm2d(1280, eps=1e-05, momentum=0.1, affine=True, track\_running\_stats=True)
  (2): SiLU(inplace=True)
)

)
(avgpool): AdaptiveAvgPool2d(output_size=1)
(classifier): Sequential(
(0): Dropout(p=0.2, inplace=True)
(1): Linear(in_features=1280, out_features=1000, bias=True)
)
)


网络结构`stage 6`,对于与features模块下,索引为5的子模块,所以对应的节点为`"features.5"`


### 构建 Faster RCNN代码讲解


#### 构建backbone


创建好backbone后,接下来讲解如何构建Faster RCNN模型,这里介绍的是不带FPN结构的,也就是说只有一个预测特征层.


#### 实例化AnchorGenerator 和 roi\_pooler


实例化`AnchorGenerator`



anchor_generator = AnchorsGenerator(sizes=((32, 64, 128, 256, 512),),
aspect_ratios=((0.5, 1.0, 2.0),))


传入两个参数,一个是`sizes`,一个是`aspect_ratios`. size 和aspect\_ratios都是元祖类型,并且都是一个元素,因为我们是构建不带FPN的结构,只有一个预测特征层,对应sizes和aspect\_ratios元祖都只有一个元素


如果我们这里不去定义`AnchorGenerator`,在Faster RCNN内部它会自动去构建针对具有FPN结构的`AnchorGenerator` 以及`roi_pooler`,因此需要我们事先去构建 `AnchorGenerator`和`roi_pooler`



anchor_generator = AnchorsGenerator(sizes=((32, 64, 128, 256, 512),),
aspect_ratios=((0.5, 1.0, 2.0),))

roi_pooler = torchvision.ops.MultiScaleRoIAlign(featmap_names=[‘0’], # 在哪些特征层上进行RoIAlign pooling
output_size=[7, 7], # RoIAlign pooling输出特征矩阵尺寸
sampling_ratio=2) # 采样率


这里用的`MutiScaleRoIAlign` ,这个相对Faster RCNN论文所讲的RoiPooler而言会更加精确一些. 由于这里只有一个`key`为0的预测特征层,所以在MultiScaleRoIAlign中传入`featmap_names=['0']`


#### 模型构建


`构建模型`:



model = FasterRCNN(backbone=backbone,
num_classes=num_classes,
rpn_anchor_generator=anchor_generator,
box_roi_pool=roi_pooler)


完整代码如下:



def create_model(num_classes, load_pretrain_weights=True):
import torchvision
from torchvision.models.feature_extraction import create_feature_extractor

# vgg16
backbone=torchvision.models.vgg16_bn(pretrained=False)
print(backbone)

backbone=create_feature_extractor(backbone,return_nodes={"features.42":"0"})
#out=backbone(torch.rand(1,3,224,224))
#print(out["0"].shape)
backbone.out_channels=512

# resnet50 backbone
# backbone=torchvision.models.resnet50(pretrained=False)
# #print(backbone)
# backbone=create\_feature\_extractor(backbone,return\_nodes={"layer3":"0"})
# out=backbone(torch.rand(1,3,224,224))
# print(out["0"].shape)
# backbone.out\_channels=1024

# efficientnet\_b0 backbone
# backbone=torchvision.models.efficientnet\_b0(pretrained=False)
# print(backbone)
# backbone=create\_feature\_extractor(backbone,return\_nodes={"features.5":"0"})
# out=backbone(torch.rand(1,3,224,224))
# print(out["0"].shape)
# backbone.out\_channels=112

anchor_generator = AnchorsGenerator(sizes=((32, 64, 128, 256, 512),),
                                    aspect_ratios=((0.5, 1.0, 2.0),))

roi_pooler = torchvision.ops.MultiScaleRoIAlign(featmap_names=['0'],  # 在哪些特征层上进行RoIAlign pooling
                                                output_size=[7, 7],  # RoIAlign pooling输出特征矩阵尺寸
                                                sampling_ratio=2)  # 采样率

model = FasterRCNN(backbone=backbone,
                   num_classes=num_classes,
                   rpn_anchor_generator=anchor_generator,
                   box_roi_pool=roi_pooler)

return model

### 带FPN结构更换backbone


对应的代码在`change_backbone_with_fpn.py`文件中,同样我们来看下 `create_model`这部分代码.


首先在`create_model`函数中导入两个包



import torchvision
from torchvision.models.feature_extraction import create_feature_extractor


 `我们使用的pytorch版本必须是1.10或以上,torchvision也要按照和pytorch对应的版本`


#### 更换backbone


##### 以 mobienet\_v3\_large backbone 为例



— mobilenet_v3_large fpn backbone —

backbone = torchvision.models.mobilenet_v3_large(pretrained=True)


设置`pretrained=True`,在创建模型的过程会自动下载在ImageNet预训练好的权重.  
 构建带fpn结构的backbone,参考[目标检测FPN结构的使用]( ),  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/d571ce63d355499996abe56ea8be6d0b.png)


主要难点是要知道我们要获取哪些特征层,并且这些特征层对应的是哪一个模块的输出.



return_layers = {“features.6”: “0”, # stride 8
“features.12”: “1”, # stride 16
“features.16”: “2”} # stride 32


创建了一个`return_layers`字典,字典中每一对键值对对应的就是某一个特征层,和不带FPN的backbone比较类似,只是带FPN结构的backbone需要抽取多个特正层.


* key对应的是抽取特征层,在网络中的节点位置
* value, 默认设置从"0"开始递增


![[MobileNetV3-Large结构图]](https://img-blog.csdnimg.cn/cd50654317834a2db1081eaa2bb27641.png)


这个图是原论文为给MobileNetV3-Large网络的一个结构,假设我这边想获取图中用蓝色框框出来的这3个模块所对应的输出,可以看到对于第一个模块我们下采样了8倍,第二个模块下采样了16倍,第三个模块下采样了32倍. 当然也可以按自己的想法选择合适的模块抽取特征.


`如何找到抽取的3个模块的名称呢?`主要有两种方式:


* 第一种是通过源码查看
* 第二种通过`print(backbone)`进行查看。


通过IDE查看构建`MobileNetV3-Large`的源代码,我们可以看到官方所实现的`features`



self.features = nn.Sequential(*layers)


它所存储的就是上图中对应索引0-16的17个模块,在源码中我们可以知道每搭建一层就会增加一个模块,所以对应的索引就是该模块所在位置.图中抽取的模块,对应的是`6,12,16` ,如果不清楚的话也可以打印下backbone进行查看.


设定好return\_layers之后,我们还需要指定下我们抽取的这几个特征层,他们对应的channels,通过上图中的表格可以看出这个层对应的channels,分别是[40,112,960], 如果不清楚chanel的话,我随机创建一个tensor,输入backbone,然后通过简单的循环打印抽取特征层名称和shape.



backbone = torchvision.models.mobilenet_v3_large(pretrained=False)
print(backbone)
return_layers = {“features.6”: “0”, # stride 8
“features.12”: “1”, # stride 16
“features.16”: “2”} # stride 32

提供给fpn的每个特征层channel

in_channels_list = [40, 112, 960]

new_backbone = create_feature_extractor(backbone, return_layers)
img = torch.randn(1, 3, 224, 224)
outputs = new_backbone(img)
[print(f"{k} shape: {v.shape}") for k, v in outputs.items()]


打印的信息:



0 shape: torch.Size([1, 40, 28, 28])
1 shape: torch.Size([1, 112, 14, 14])
2 shape: torch.Size([1, 960, 7, 7])


这里的key `0,1,2`是我们在retrun\_layers中定义的value.其中通道可以看到分别是`40,112,960`,结合每个特征层输出的高和宽的数值,能够帮助我们分析我们抽取的特征层的下采样倍率是不是对的.


接下来,通过实例化`backboneWithFPN`来构建带fpn的backbone.



backbone_with_fpn = BackboneWithFPN(new_backbone,
return_layers=return_layers,
in_channels_list=in_channels_list,
out_channels=256,
extra_blocks=LastLevelMaxPool(),
re_getter=False)


* `这里将re_getter设置为False就不会重构模型了,`直接利用`create_feature_extractor(backbone, return_layers)` 实例化的new\_backbone,因为利用BackboneWithFPN的话它无法获取某个layers下的子模块的输出,因此利用`create_feature_extractor(backbone, return_layers)` 去重构backbone会更方便和灵活.
* 传入return\_layers,in\_channel\_list
* out\_channels为256,我们在构建fpn的时候将每个特征层的channel通过1x1的卷积调整为256  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/b426ce16c35c4052b864e3f1a0455008.png)
* `extra_blocks=LastLevelMaxPool`, 它的作用就是图中我们所画的,在最高层的特征层中,在通过一个Maxpool在进行一次上采样.得到尺度更小的特征层.尺度更小的特征层有利于我们检测更大的目标.而且这里还需要注意一个点Maxpool得到的特征层,它只用于我们的RPN部分,不在Fast-RCNN中使用.


然后利用`FeaturePyramidNetwork`去构建fpn结构



self.fpn = FeaturePyramidNetwork(
in_channels_list=in_channels_list,
out_channels=out_channels,
extra_blocks=extra_blocks,
)


从正向传播可以看到,它利用输入的数据,依次通过boy也就是重构后的backbone,和fpn然后得到我们的输出.



class BackboneWithFPN(nn.Module):
def __init__(self,
backbone: nn.Module,
return_layers=None,
in_channels_list=None,
out_channels=256,
extra_blocks=None,
re_getter=True):
super().init()

    if extra_blocks is None:
        extra_blocks = LastLevelMaxPool()

    if re_getter is True:
        assert return_layers is not None
        self.body = IntermediateLayerGetter(backbone, return_layers=return_layers)
    else:
        self.body = backbone

    self.fpn = FeaturePyramidNetwork(
        in_channels_list=in_channels_list,
        out_channels=out_channels,
        extra_blocks=extra_blocks,
    )

    self.out_channels = out_channels

def forward(self, x):
    x = self.body(x)
    x = self.fpn(x)
    return x

从而完成BackboneWithFPN的backbone的构建


#### AnchorGenerator 和aspect\_ratios





**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

**需要这份系统化的资料的朋友,可以添加V获取:vip1024b (备注运维)**
![img](https://img-blog.csdnimg.cn/img_convert/2b14c3c7fb5436b556d3b6a6d3b3291f.jpeg)

**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**
rn_layers)
        else:
            self.body = backbone

        self.fpn = FeaturePyramidNetwork(
            in_channels_list=in_channels_list,
            out_channels=out_channels,
            extra_blocks=extra_blocks,
        )

        self.out_channels = out_channels

    def forward(self, x):
        x = self.body(x)
        x = self.fpn(x)
        return x


从而完成BackboneWithFPN的backbone的构建

AnchorGenerator 和aspect_ratios

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip1024b (备注运维)
[外链图片转存中…(img-46j4mFPs-1713613100508)]

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 14
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值