有没有办法修改 GluonCV 预训练对象检测模型的层

Is there a way to modify the layers of a GluonCV pretrained object detection model

你好,Whosebug。

我希望用可变形的卷积层替换用于对象检测的 GluonCV 预训练模型的卷积层。具体来说,我希望替换 CNN 中用于对象检测模型特征提取的卷积层。我的目标是替换 Faster RCNN 和 SSD 检测模型。

我试过下面的代码片段:

def replace_conv2D(net):
    for key, layer in net._children.items():
        if isinstance(layer, gluon.nn.Conv2D):
            new_conv = gluon.nn.Conv2D(
                channels=layer._channels // 2,
                kernel_size=layer._kwargs['kernel'],
                strides=layer._kwargs['stride'],
                padding=layer._kwargs['pad'],
                in_channels=layer._in_channels // 2)
            with net.name_scope():
                net.register_child(new_conv, key)
            new_conv.initialize(mx.init.Xavier())
        else:
            replace_conv2D(layer)
net = gluon.model_zoo.vision.get_model("resnet18_v1", pretrained=True)
replace_conv2D(net)

并尝试验证模型的卷积层是否被替换为:

def replace_conv2D(net):
    for key, layer in net._children.items():
        print(f"{key}:{layer}")

但我无法验证我的对象检测模型是否替换了它们的卷积层。我只能验证它适用于图像分类模型

它适用于基本的 resnet50 模型(图像分类)

之前(ResNet:50)

ResNetV1(
  (features): HybridSequential(
    (0): Conv2D(3 -> 64, kernel_size=(7, 7), stride=(2, 2), padding=(3, 3), bias=False)
    (1): BatchNorm(axis=1, eps=1e-05, momentum=0.9, fix_gamma=False, use_global_stats=False, in_channels=64)
) 

之后(ResNet50)

ResNetV1(
  (features): HybridSequential(
    (0): DeformableConvolution(None -> 64, kernel_size=(7, 7), stride=(2, 2), padding=(3, 3))
    (1): BatchNorm(axis=1, eps=1e-05, momentum=0.9, fix_gamma=False, use_global_stats=False, in_channels=64)
)

但对于 SSD_resnet50 模型(对象检测):

第一层遇到如下输出:

features FeatureExpander(
<Symbol group [ssd2_resnetv10_stage3_activation5, ssd2_resnetv10_stage4_activation2, ssd2_expand_reu0, ssd2_expand_reu1, ssd2_expand_reu2, ssd2_expand_reu3]> : 1 -> 6
)

方法有运行后,我没有观察到任何变化:

features FeatureExpander(
<Symbol group [ssd2_resnetv10_stage3_activation5, ssd2_resnetv10_stage4_activation2, ssd2_expand_reu0, ssd2_expand_reu1, ssd2_expand_reu2, ssd2_expand_reu3]> : 1 -> 6
)

我通过执行以下步骤解决了这个问题:

  1. 从 GluonCV 的 Github Repo 复制 SSD 模型的源代码到自己的 class 文件
  2. 修改 class 文件以合并所需的更改(在我的例子中用可变形卷积替换某些卷积)以创建我的修改版本
  3. 加载原始 SSD模型,然后将原始模型的参数保存为'transfer.params'
  4. 创建我的 修改后的 SSD 模型,然后加载 'transfer.params'(这是 原始 模型的权重)allow_missing=真 & ignore_extra = 真

生成的修改后的模型将具有预先训练的权重,其中层的名称匹配,但根据需要修改的层除外。

可以扩展这些步骤以根据需要修改 backbone 网络。