pytorch 34 mmdetection配置文件中指定backbone与neck

探索在mmdetection中可用的backbone与neck,尝试自由组合backbone与neck,实现更为丰富的模型。主要研究替换retinanet的backbone(该经验可以用到任意模型中),替换faster-rcnn的neck(该经验可以应用到faster-rcnn系列的变种模型中)。

backbone+neck+head的状态

1.1 宏观概述

在mmdet中检测器由backbone+neck+head组成,分别对应下图的各种目录。其中head分为dense_heads、roi_heads、seg_heads三大类。
pytorch 34 mmdetection配置文件中指定backbone与neck_第1张图片
不同的backbone+neck+head构成了不同类型的detectors,具体如下图所示,其就是具体的目标检测器类型,在下面可以看到faster_rcnn、yolo等系列的检测器。这里的detectors决定了backbone+neck+head的forword的细节,实现了在统一的数据输入下不同模型的boxes处理细节。
pytorch 34 mmdetection配置文件中指定backbone与neck_第2张图片
有的时候,一个系列的模型boxes处理流程相同,故其定义代码只有一点点(比如红框标注的single_stage和tow_stage),其示例如以下代码所示;有的目标检测器处理流程略有不同,则会继承single_stage或tow_stage,修改数据处理流程(就比如yolox和space_rcnn)。

@DETECTORS.register_module()
class FCOS(SingleStageDetector):
    """Implementation of `FCOS `_"""

    def __init__(self,
                 backbone,
                 neck,
                 bbox_head,
                 train_cfg=None,
                 test_cfg=None,
                 pretrained=None,
                 init_cfg=None):
        super(FCOS, self).__init__(backbone, neck, bbox_head, train_cfg,
                                   test_cfg, pretrained, init_cfg)

1.2 通用backbone

mmdet中预设的backbone如下所示,每一个py文件都对应着系列的目标分类模型。后续需研究一下每一个backbone的特殊之处。
pytorch 34 mmdetection配置文件中指定backbone与neck_第3张图片

1.3 neck

可用的neck如下所示,有的necks是可以通用于faster-rcnn系列,有的可以用于yolo系列,而有的neck只能用于特定的模型。

__all__ = [
    'FPN', 'BFP', 'ChannelMapper', 'HRFPN', 'NASFPN', 'FPN_CARAFE', 'PAFPN',
    'NASFCOS_FPN', 'RFP', 'YOLOV3Neck', 'FPG', 'DilatedEncoder',
    'CTResNetNeck', 'SSDNeck', 'YOLOXPAFPN', 'DyHead'
]

1.4 head

通常detectors的类型决定了head的细节,就比如YOLOXHead、CenterNetHead、YOLOFHead、DETRHead、YOLOV3Head等等,分别对应了具体的detectors,基本上不具备通用性。

dense_heads

这里的head用于目标检测框生成和目标分类

__all__ = [
    'AnchorFreeHead', 'AnchorHead', 'GuidedAnchorHead', 'FeatureAdaption',
    'RPNHead', 'GARPNHead', 'RetinaHead', 'RetinaSepBNHead', 'GARetinaHead',
    'SSDHead', 'FCOSHead', 'RepPointsHead', 'FoveaHead',
    'FreeAnchorRetinaHead', 'ATSSHead', 'FSAFHead', 'NASFCOSHead',
    'PISARetinaHead', 'PISASSDHead', 'GFLHead', 'CornerHead', 'YOLACTHead',
    'YOLACTSegmHead', 'YOLACTProtonet', 'YOLOV3Head', 'PAAHead',
    'SABLRetinaHead', 'CentripetalHead', 'VFNetHead', 'StageCascadeRPNHead',
    'CascadeRPNHead', 'EmbeddingRPNHead', 'LDHead', 'CascadeRPNHead',
    'AutoAssignHead', 'DETRHead', 'YOLOFHead', 'DeformableDETRHead',
    'SOLOHead', 'DecoupledSOLOHead', 'CenterNetHead', 'YOLOXHead',
    'DecoupledSOLOLightHead', 'LADHead', 'TOODHead', 'MaskFormerHead'
]

roi_head

roi_head用于两阶段目标检测器中的proposal的修正,目前有以下各种

__all__ = [
    'BaseRoIHead', 'CascadeRoIHead', 'DoubleHeadRoIHead', 'MaskScoringRoIHead',
    'HybridTaskCascadeRoIHead', 'GridRoIHead', 'ResLayer', 'BBoxHead',
    'ConvFCBBoxHead', 'DIIHead', 'SABLHead', 'Shared2FCBBoxHead',
    'StandardRoIHead', 'Shared4Conv1FCBBoxHead', 'DoubleConvFCBBoxHead',
    'FCNMaskHead', 'HTCMaskHead', 'FusedSemanticHead', 'GridHead',
    'MaskIoUHead', 'BaseRoIExtractor', 'GenericRoIExtractor',
    'SingleRoIExtractor', 'PISARoIHead', 'PointRendRoIHead', 'MaskPointHead',
    'CoarseMaskHead', 'DynamicRoIHead', 'SparseRoIHead', 'TridentRoIHead',
    'SCNetRoIHead', 'SCNetMaskHead', 'SCNetSemanticHead', 'SCNetBBoxHead',
    'FeatureRelayHead', 'GlobalContextHead'
]

seg_head

seg_head用于输出语义分割信息,很明显是用于实例分割
pytorch 34 mmdetection配置文件中指定backbone与neck_第4张图片

2、backbone+neck的自由组合

在mmdete配置文件中虽然可以实现backbone+neck的灵活自由组合,但是也存在一定的限制。其中backbone的自由度是最高的,neck的自由度次之,head基本上不能自由组合,因为head对应了特定类型的detectors。

2.1 替换backbone

这里以retinanet的配置文件为基本参考。

默认使用ResNet50做backbone,然后可以将backbone替换为ResNeXt101,SwinTransformer。

默认配置写法

model = dict(
    type='RetinaNet',
    backbone=dict(
        type='ResNet',
        depth=50,
        num_stages=4,
        out_indices=(0, 1, 2, 3),
        frozen_stages=1,
        norm_cfg=dict(type='BN', requires_grad=True),
        norm_eval=True,
        style='pytorch',
        init_cfg=dict(type='Pretrained', checkpoint='torchvision://resnet50')),
    neck=dict( type='FPN',
        in_channels=[256, 512, 1024, 2048],
        out_channels=256,
        start_level=1,
        add_extra_convs='on_input',
        num_outs=5),
    bbox_head=dict( type='RetinaHead',
        num_classes=80,
        in_channels=256,
        stacked_convs=4,
        feat_channels=256,
        anchor_generator=dict(
            type='AnchorGenerator',
            octave_base_scale=4,
            scales_per_octave=3,
            ratios=[0.5, 1.0, 2.0],
            strides=[8, 16, 32, 64, 128]),
        bbox_coder=dict(
            type='DeltaXYWHBBoxCoder',
            target_means=[.0, .0, .0, .0],
            target_stds=[1.0, 1.0, 1.0, 1.0]),
        loss_cls=dict(
            type='FocalLoss',
            use_sigmoid=True,
            gamma=2.0,
            alpha=0.25,
            loss_weight=1.0),
        loss_bbox=dict(type='L1Loss', loss_weight=1.0)),
   

ResNeXt backbone写法

model = dict(
    pretrained='open-mmlab://resnext101_64x4d',
    backbone=dict(type='ResNeXt', depth=101, groups=64, base_width=4))

SwinTransformer backbone写法

这里可以看到对应的neck的in_channels需要单独设置,因为neck的in_channels要与backbone的out_indices的具体chanel数相等。

_base_ = [
    '../_base_/models/retinanet_r50_fpn.py',
    '../_base_/datasets/coco_detection.py',
    '../_base_/schedules/schedule_1x.py', '../_base_/default_runtime.py'
]
pretrained = 'https://github.com/SwinTransformer/storage/releases/download/v1.0.0/swin_tiny_patch4_window7_224.pth'  # noqa
model = dict(
    backbone=dict(
        _delete_=True,
        type='SwinTransformer',
        embed_dims=96,
        depths=[2, 2, 6, 2],
        num_heads=[3, 6, 12, 24],
        window_size=7,
        mlp_ratio=4,
        qkv_bias=True,
        qk_scale=None,
        drop_rate=0.,
        attn_drop_rate=0.,
        drop_path_rate=0.2,
        patch_norm=True,
        out_indices=(1, 2, 3),
        # Please only add indices that would be used
        # in FPN, otherwise some parameter will not be used
        with_cp=False,
        convert_weights=True,
        init_cfg=dict(type='Pretrained', checkpoint=pretrained)),
    neck=dict(in_channels=[192, 384, 768], start_level=0, num_outs=5))

2.2 替换neck

这里以替换faster-rcnn的neck为基本参考。neck不能随意替换,有的neck具有针对性。比如YOLOXPAFPN、CTResNetNeck根据名称就知道只能应用于yolox、CenterNet

此外,需要注意的是neck的in_channels要与backbone的out_indices中具体输出的chanel数对的上,同时其out_channels也要能与head中的in_channels能匹配

默认配置写法

默认使用FPN做neck。

model = dict(
    type='FasterRCNN',
    backbone=dict(
        type='ResNet',
        depth=50,
        num_stages=4,
        out_indices=(0, 1, 2, 3),
        frozen_stages=1,
        norm_cfg=dict(type='BN', requires_grad=True),
        norm_eval=True,
        style='pytorch',
        init_cfg=dict(type='Pretrained', checkpoint='torchvision://resnet50')),
    neck=dict(
        type='FPN',
        in_channels=[256, 512, 1024, 2048],
        out_channels=256,
        num_outs=5),

PAFPN的写法

这里以resnet50为backbone

_base_ = '../faster_rcnn/faster_rcnn_r50_fpn_1x_coco.py'

model = dict(
    neck=dict(
        type='PAFPN',
        in_channels=[256, 512, 1024, 2048],
        out_channels=256,
        num_outs=5))

HRFPN的写法

这里以resnet50为backbone

_base_ = '../faster_rcnn/faster_rcnn_r50_fpn_2x_coco.py'
 

norm_cfg = dict(type='BN', requires_grad=True)
model = dict(
    neck=dict(type='HRFPN', in_channels=[256, 512, 1024, 2048], out_channels=256),
    #neck=dict(type='NASFPN', stack_times=7, norm_cfg=norm_cfg),#一直报错,所以
    #neck=dict(type='PAFPN',in_channels=[256, 512, 1024, 2048],out_channels=256,num_outs=5),
    roi_head=dict(bbox_head=dict(num_classes=20)))

NASFCOS_FPN的写法

_base_ = '../faster_rcnn/faster_rcnn_r50_fpn_2x_coco.py'
 
#1、 设置训练超参数---------- 
#修改模型分类数
norm_cfg = dict(type='BN', requires_grad=True)
model = dict(
    neck=dict(
        type='NASFCOS_FPN',
        in_channels=[256, 512, 1024, 2048],
        out_channels=256,
        start_level=1,
        add_extra_convs=True,
        num_outs=5,
        norm_cfg=dict(type='BN'),
        conv_cfg=dict(type='DCNv2', deform_groups=2)),
    roi_head=dict(bbox_head=dict(num_classes=20)))

你可能感兴趣的:(pytorch 34 mmdetection配置文件中指定backbone与neck)