mmdetection 模型训练技巧

本文介绍如何通过预训练模型、Soft-NMS、GIoULoss、模型瘦身、在线难例挖掘等技术提升目标检测模型的性能。
部署运行你感兴趣的模型镜像

1. 预训练模型

      关于预训练模型,一般的检测都是使用ImageNet预训练的backbone,这是基本配置,官方也支持这种加载方式。

      高级一点的的就是针对数据集做一次预训练:即将所有的目标裁剪出来,然后训练一个不错的分类模型,这样的初始化相比ImageNet就要好很多。

      最后就是使用coco预训练的完整检测模型权重,这样的效果就是模型收敛速度快,而且效果一般都比较好,也是大家最常用的方法。由于每个任务的类别不同,需要对权重进行微调,这里给出mmdetection修改coco预训练权重类别的脚本。

      脚本以cascade rcnn为例,其他模型的修改与之类似。

# for cascade rcnn
import torch
num_classes = 21
model_coco = torch.load("cascade_rcnn_x101_32x4d_fpn_2x_20181218-28f73c4c.pth")

# weight
model_coco["state_dict"]["bbox_head.0.fc_cls.weight"].resize_(num_classes,1024)
model_coco["state_dict"]["bbox_head.1.fc_cls.weight"].resize_(num_classes,1024)
model_coco["state_dict"]["bbox_head.2.fc_cls.weight"].resize_(num_classes,1024)
# bias
model_coco["state_dict"]["bbox_head.0.fc_cls.bias"].resize_(num_classes)
model_coco["state_dict"]["bbox_head.1.fc_cls.bias"].resize_(num_classes)
model_coco["state_dict"]["bbox_head.2.fc_cls.bias"].resize_(num_classes)
#save new model
torch.save(model_coco,"coco_pretrained_weights_classes_%d.pth"%num_classes)

2. Soft-NMS

    Soft-NMS改进了之前比较暴力的NMS,当IOU超过某个阈值后,不再直接删除该框,而是降低它的置信度(得分),如果得分低到一个阈值,就会被排除;但是如果降低后任然较高,就会保留。

    在mmdetection中的设置如下:

test_cfg = dict(
    rpn=dict(
        nms_across_levels=False,
        nms_pre=1000,
        nms_post=1000,
        max_num=1000,
        nms_thr=0.7,
        min_bbox_size=0),
    rcnn=dict(
        score_thr=0.05, nms=dict(type='soft_nms', iou_thr=0.5), max_per_img=100),
    keep_all_stages=False)

3. GIoULoss

      一般情况下,用GIoULoss代替L1Loss后会涨点。

      原版用的配置文件(使用L1Loss)如下:

    rpn_head=dict(
        type='RPNHead',
        in_channels=256,
        feat_channels=256,
        anchor_generator=dict(
            type='AnchorGenerator',
            scales=[8],
            ratios=[0.5, 1.0, 2.0],
            strides=[4, 8, 16, 32, 64]),
        bbox_coder=dict(
            type='DeltaXYWHBBoxCoder',
            target_means=[0.0, 0.0, 0.0, 0.0],
            target_stds=[1.0, 1.0, 1.0, 1.0]),
        loss_cls=dict(
            type='CrossEntropyLoss', use_sigmoid=True, loss_weight=1.0),
        loss_bbox=dict(type='L1Loss', loss_weight=1.0)),
    roi_head=dict(
        type='StandardRoIHead',
        bbox_roi_extractor=dict(
            type='SingleRoIExtractor',
            roi_layer=dict(type='RoIAlign', out_size=7, sample_num=0),
            out_channels=256,
            featmap_strides=[4, 8, 16, 32]),
        bbox_head=dict(
            type='Shared2FCBBoxHead',
            in_channels=256,
            fc_out_channels=1024,
            roi_feat_size=7,
            num_classes=10,
            bbox_coder=dict(
                type='DeltaXYWHBBoxCoder',
                target_means=[0.0, 0.0, 0.0, 0.0],
                target_stds=[0.1, 0.1, 0.2, 0.2]),
            reg_class_agnostic=False,
            loss_cls=dict(
                type='CrossEntropyLoss', use_sigmoid=False, loss_weight=1.0),
            loss_bbox=dict(type='L1Loss', loss_weight=1.0))))

    添加GIoULoss后的配置文件如下:

    rpn_head=dict(
        type='RPNHead',
        in_channels=256,
        feat_channels=256,
        anchor_generator=dict(
            type='AnchorGenerator',
            scales=[8],
            ratios=[0.5, 1.0, 2.0],
            strides=[4, 8, 16, 32, 64]),
        bbox_coder=dict(
            type='DeltaXYWHBBoxCoder',
            target_means=[0.0, 0.0, 0.0, 0.0],
            target_stds=[1.0, 1.0, 1.0, 1.0]),
        loss_cls=dict(
            type='CrossEntropyLoss', use_sigmoid=True, loss_weight=1.0),
	reg_decoded_bbox=True,      # 使用GIoUI时注意添加
        loss_bbox=dict(type='GIoULoss', loss_weight=5.0)),
    roi_head=dict(
        type='StandardRoIHead',
        bbox_roi_extractor=dict(
            type='SingleRoIExtractor',
            roi_layer=dict(type='RoIAlign', out_size=7, sample_num=0),
            out_channels=256,
            featmap_strides=[4, 8, 16, 32]),
        bbox_head=dict(
            type='Shared2FCBBoxHead',
	    
            in_channels=256,
            fc_out_channels=1024,
            roi_feat_size=7,
            num_classes=10,
            bbox_coder=dict(
                type='DeltaXYWHBBoxCoder',
                target_means=[0.0, 0.0, 0.0, 0.0],
                target_stds=[0.1, 0.1, 0.2, 0.2]),
            reg_class_agnostic=False,
            loss_cls=dict(
                type='CrossEntropyLoss', use_sigmoid=False, loss_weight=1.0),
            reg_decoded_bbox=True,     # 使用GIoUI时注意添加
            loss_bbox=dict(type='GIoULoss', loss_weight=5.0))))

4. 模型瘦身小技巧

      mmdetection在保存模型时,除了保存权重,还保存了原始数据和优化参数。但是,模型在测试时,有些参数是没有用的,怎样去掉这些无用的参数使模型减小(大约减小50%)呢?见下面的代码:

import torch

model_path = "epoch_30.pth"
checkpoint = torch.load(model_path)
checkpoint['meta'] = None
checkpoint['optimizer'] = None

weights = checkpoint['state_dict']

state_dict = {"state_dict":weights}

torch.save(state_dict,  './epotch_30_new.pth')

5. 在线难例挖掘(OHEM)

   在线难例挖掘:在训练过程中在线的选择困难样本进行训练(选择loss较大的样本)。

   思想比较简单,在mmdetection中的应用如下:

   以faster rcnn为例子:

_base_ = './faster_rcnn_r50_fpn_1x_coco.py'
train_cfg = dict(rcnn=dict(sampler=dict(type='OHEMSampler')))

   第一行为你训练模型的配置文件,第二行把采样方式设置为在线难例挖掘。       

todo:

(1). GIoULoss  已经完成

(2). 在线难例挖掘  已经完成

(3). 混合精度训练

(4). 可变形卷积

(5). 多尺度训练

(6). 多尺度测试与数据增强测试

(7). Albu数据增强库的使用

(8). 模型融合

(9). 过分割测试

(10). mosaic数据增强

(11). PAFPN

(12). 样本均衡抑制长尾分布问题

您可能感兴趣的与本文相关的镜像

GPT-oss:20b

GPT-oss:20b

图文对话
Gpt-oss

GPT OSS 是OpenAI 推出的重量级开放模型,面向强推理、智能体任务以及多样化开发场景

### 如何在 MMDetection 框架中自定义或调整深度学习检测模型的配置与架构 #### 修改模型结构 MMDetection 提供了一个灵活的模块化设计,允许用户通过修改配置文件来自定义模型结构。以下是具体方法: 1. **更改主干网络 (Backbone)** 主干网络通常是 CNN 结构的一部分,负责提取特征图。可以通过 `backbone` 字段指定不同的主干网络。例如,在配置文件中将 ResNet 替换为 MobileNetV2 可以这样设置: ```python backbone=dict( type='MobileNetV2', widen_factor=1., out_indices=(7, ), init_cfg=dict(type='Pretrained', checkpoint='mobilenet_v2.pth')) ``` 这里指定了新的主干网络类型以及预训练权重路径[^1]。 2. **替换颈部结构 (Neck)** 如果希望改变 FPN 或其他颈部组件的设计,则需编辑 neck 参数部分。比如切换到 PANet 而不是默认的 FPN: ```python neck=dict( type='PANet', in_channels=[256, 512, 1024], out_channels=256, num_outs=5) ``` 此外还可以增加额外层或者调整通道数来优化性能[^2]。 3. **调整头部 (Head)** 对于不同任务可能需要特定类型的预测头。如果想把 Faster R-CNN 的 RoI Head 改成 Cascade RCNN 多阶段版本的话如下所示: ```python roi_head=dict( _delete_=True, type='CascadeRoIHead', ... ) ``` #### 自定义超参数和其他选项 除了上述结构调整之外,还有很多地方可以微调影响最终效果的关键因素: - 学习率调度器 (`lr_config`) 和优化策略(`optimizer`) - 数据增强方式(如 Mixup/Cutout) - 测试时间增广(TTA) 下面是一个完整的例子展示了如何综合运用以上技巧创建一个新的实例分割方案: ```python model = dict( type='MaskRCNN', pretrained=None, backbone=dict(...), # 插入上面提到的新骨干网定义 neck=dict(...), rpn_head=dict(...), roi_head=dict(...) ) train_pipeline = [ ... 添加更多样式的变换操作... ] data = dict( samples_per_gpu=2, workers_per_gpu=2, train=dict(pipeline=train_pipeline)) evaluation = dict(metric=['bbox', 'segm']) # 设置更复杂的 LR policy lr_config = dict(policy='CosineAnnealing', min_lr_ratio=0.05) runner = dict(max_epochs=12) ``` 最后记得保存这个新配置并命名为 `.py`, 然后按照官方文档指导运行即可完成整个流程[^3]. ---
评论 25
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

guopeiAI

请博主加个火腿

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值