Miao Zheng ff95416c3b
[Features]Support dump segment predition (#2712)
## Motivation

1. It is used to save the segmentation predictions as files and upload
these files to a test server

## Modification

1. Add output_file and format only in `IoUMetric`
 
## BC-breaking (Optional)

No

## Use cases (Optional)

If this PR introduces a new feature, it is better to list some use cases
here, and update the documentation.

## Checklist

1. Pre-commit or other linting tools are used to fix the potential lint
issues.
3. The modification is covered by complete unit tests. If not, please
add more unit test to ensure the correctness.
4. If the modification has potential influence on downstream projects,
this PR should be tested with downstream projects, like MMDet or
MMDet3D.
5. The documentation has been modified accordingly, like docstring or
example tutorials.
2023-03-17 22:58:08 +08:00

15 KiB
Raw Blame History

从 MMSegmentation 0.x 迁移

引言

本指南介绍了 MMSegmentation 0.x 和 MMSegmentation1.x 在行为和 API 方面的基本区别,以及这些如何都与您的迁移过程相关。

新的依赖

MMSegmentation 1.x 依赖于一些新的软件包,您可以准备一个新的干净环境,然后根据安装教程重新安装。

或手动安装以下软件包。

  1. MMEngineMMEngine 是 OpenMMLab 2.0 架构的核心,我们将许多与计算机视觉无关的内容从 MMCV 拆分到 MMEngine 中。

  2. MMCVOpenMMLab 的计算机视觉包。这不是一个新的依赖,但您需要将其升级到 2.0.0rc1 以上的版本。

  3. MMClassification可选OpenMMLab 的图像分类工具箱和基准。这不是一个新的依赖,但您需要将其升级到 1.0.0rc0 以上的版本。

  4. MMDetection(可选): OpenMMLab 的目标检测工具箱和基准。这不是一个新的依赖,但您需要将其升级到 3.0.0rc0 以上的版本。

启动训练

OpenMMLab 2.0 的主要改进是发布了 MMEngine它为启动训练任务的统一接口提供了通用且强大的执行器。

与 MMSeg 0.x 相比MMSeg 1.x 在 tools/train.py 中提供的命令行参数更少

功能 原版 新版
加载预训练模型 --load_from=$CHECKPOINT --cfg-options load_from=$CHECKPOINT
从特定检查点恢复训练 --resume-from=$CHECKPOINT --resume=$CHECKPOINT
从最新的检查点恢复训练 --auto-resume --resume='auto'
培训练期间是否不评估检查点 --no-validate --cfg-options val_cfg=None val_dataloader=None val_evaluator=None
指定训练设备 --gpu-id=$DEVICE_ID -
是否为不同进程设置不同的种子 --diff-seed --cfg-options randomness.diff_rank_seed=True
是否为 CUDNN 后端设置确定性选项 --deterministic --cfg-options randomness.deterministic=True

测试启动

与训练启动类似MMSegmentation 1.x 的测试启动脚本在 tools/test.py 中仅提供关键命令行参数,以下是测试启动脚本的区别,更多关于测试启动的细节请参考这里

功能 0.x 1.x
指定评测指标 --eval mIoU --cfg-options test_evaluator.type=IoUMetric
测试时数据增强 --aug-test --tta
测试时是否只保存预测结果不计算评测指标 --format-only --cfg-options test_evaluator.format_only=True

配置文件

模型设置

model.backendmodel.neckmodel.decode_headmodel.loss 字段没有更改。

添加 model.data_preprocessor 字段以配置 DataPreProcessor,包括:

  • meanSequence可选R、G、B 通道的像素平均值。默认为 None。

  • stdSequence可选R、G、B通道的像素标准差。默认为 None。

  • sizeSequence可选固定的填充大小。

  • size_divisorint可选填充大小的除法因子。

  • seg_pad_valfloat可选分割图的填充值。默认值255。

  • padding_modestr填充类型。默认值'constant'。

    • constant常量值填充值由 pad_val 指定。
  • bgr_to_rgbbool是否将图像从 BGR 转换为 RGB。默认为 False。

  • rgb_to_bgrbool是否将图像从 RGB 转换为 BGR。默认为 False。

注: 有关详细信息,请参阅模型文档

数据集设置

data 的更改:

原版 data 字段被拆分为 train_dataloaderval_dataloadertest_dataloader,允许我们以细粒度配置它们。例如,您可以在训练和测试期间指定不同的采样器和批次大小。 samples_per_gpu 重命名为 batch_sizeworkers_per_gpu 重命名为 num_workers

原版
data = dict(
    samples_per_gpu=4,
    workers_per_gpu=4,
    train=dict(...),
    val=dict(...),
    test=dict(...),
)
新版
train_dataloader = dict(
    batch_size=4,
    num_workers=4,
    dataset=dict(...),
    sampler=dict(type='DefaultSampler', shuffle=True)  # necessary
)

val_dataloader = dict(
    batch_size=4,
    num_workers=4,
    dataset=dict(...),
    sampler=dict(type='DefaultSampler', shuffle=False)  # necessary
)

test_dataloader = val_dataloader

数据增强变换流程变更

  • 原始格式转换 ToTensorImageToTensorCollect 组合为 PackSegInputs
  • 我们不建议在数据集流程中执行 NormalizePad。请将其从流程中删除,并将其设置在 data_preprocessor 字段中。
  • MMSeg 1.x 中原始的 Resize 已更改为 RandomResize ,输入参数 img_scale 重命名为 scalekeep_ratio 的默认值修改为 False。
  • 原始的 test_pipeline 将单尺度和多尺度测试结合在一起,在 MMSeg 1.x 中,我们将其分为 test_pipelinetta_pipeline

注: 我们将一些数据转换工作转移到数据预处理器中,如归一化,请参阅文档了解更多详细信息。

训练流程

原版
train_pipeline = [
    dict(type='LoadImageFromFile'),
    dict(type='LoadAnnotations', reduce_zero_label=True),
    dict(type='Resize', img_scale=(2560, 640), ratio_range=(0.5, 2.0)),
    dict(type='RandomCrop', crop_size=crop_size, cat_max_ratio=0.75),
    dict(type='RandomFlip', prob=0.5),
    dict(type='PhotoMetricDistortion'),
    dict(type='Normalize', **img_norm_cfg),
    dict(type='Pad', size=crop_size, pad_val=0, seg_pad_val=255),
    dict(type='DefaultFormatBundle'),
    dict(type='Collect', keys=['img', 'gt_semantic_seg']),
]
新版
train_pipeline = [
    dict(type='LoadImageFromFile'),
    dict(type='LoadAnnotations', reduce_zero_label=True),
    dict(
        type='RandomResize',
        scale=(2560, 640),
        ratio_range=(0.5, 2.0),
        keep_ratio=True),
    dict(type='RandomCrop', crop_size=crop_size, cat_max_ratio=0.75),
    dict(type='RandomFlip', prob=0.5),
    dict(type='PhotoMetricDistortion'),
    dict(type='PackSegInputs')
]

测试流程

原版
test_pipeline = [
    dict(type='LoadImageFromFile'),
    dict(
        type='MultiScaleFlipAug',
        img_scale=(2560, 640),
        # img_ratios=[0.5, 0.75, 1.0, 1.25, 1.5, 1.75],
        flip=False,
        transforms=[
            dict(type='Resize', keep_ratio=True),
            dict(type='RandomFlip'),
            dict(type='Normalize', **img_norm_cfg),
            dict(type='ImageToTensor', keys=['img']),
            dict(type='Collect', keys=['img']),
        ])
]
新版
test_pipeline = [
    dict(type='LoadImageFromFile'),
    dict(type='Resize', scale=(2560, 640), keep_ratio=True),
    dict(type='LoadAnnotations', reduce_zero_label=True),
    dict(type='PackSegInputs')
]
img_ratios = [0.5, 0.75, 1.0, 1.25, 1.5, 1.75]
tta_pipeline = [
    dict(type='LoadImageFromFile', backend_args=None),
    dict(
        type='TestTimeAug',
        transforms=[
            [
                dict(type='Resize', scale_factor=r, keep_ratio=True)
                for r in img_ratios
            ],
            [
                dict(type='RandomFlip', prob=0., direction='horizontal'),
                dict(type='RandomFlip', prob=1., direction='horizontal')
            ], [dict(type='LoadAnnotations')], [dict(type='PackSegInputs')]
        ])
]

evaluation 中的更改:

  • evaluation 字段被拆分为 val_evaluatortest_evaluator 。而且不再支持 intervalsave_best 参数。 interval 已移动到 train_cfg.val_intervalsave_best 已移动到 default_hooks.checkpoint.save_bestpre_eval 已删除。
  • IoU 已更改为 IoUMetric
原版
evaluation = dict(interval=2000, metric='mIoU', pre_eval=True)
新版
val_evaluator = dict(type='IoUMetric', iou_metrics=['mIoU'])
test_evaluator = val_evaluator

Optimizer 和 Schedule 设置

optimizeroptimizer_config 中的更改:

  • 现在我们使用 optim_wrapper 字段来指定优化过程的所有配置。以及 optimizeroptim_wrapper 的一个子字段。
  • paramwise_cfg 也是 optim_wrapper 的一个子字段,以替代 optimizer
  • optimizer_config 现在被删除,它的所有配置都被移动到 optim_wrapper 中。
  • grad_clip 重命名为 clip_grad
原版
optimizer = dict(type='AdamW', lr=0.0001, weight_decay=0.0005)
optimizer_config = dict(grad_clip=dict(max_norm=1, norm_type=2))
新版
optim_wrapper = dict(
    type='OptimWrapper',
    optimizer=dict(type='AdamW', lr=0.0001, weight_decay=0.0005),
    clip_grad=dict(max_norm=1, norm_type=2))

lr_config 中的更改:

  • 我们将 lr_config 字段删除,并使用新的 param_scheduler 替代。
  • 我们删除了与 warmup 相关的参数,因为我们使用 scheduler 组合来实现该功能。

新的 scheduler 组合机制非常灵活,您可以使用它来设计多种学习率/动量曲线。有关详细信息,请参见教程

原版
lr_config = dict(
    policy='poly',
    warmup='linear',
    warmup_iters=1500,
    warmup_ratio=1e-6,
    power=1.0,
    min_lr=0.0,
    by_epoch=False)
新版
param_scheduler = [
    dict(
        type='LinearLR', start_factor=1e-6, by_epoch=False, begin=0, end=1500),
    dict(
        type='PolyLR',
        power=1.0,
        begin=1500,
        end=160000,
        eta_min=0.0,
        by_epoch=False,
    )
]

runner 中的更改:

原版 runner 字段中的大多数配置被移动到 train_cfgval_cfgtest_cfg 中,以在训练、验证和测试中配置 loop。

原版
runner = dict(type='IterBasedRunner', max_iters=20000)
新版
# The `val_interval` is the original `evaluation.interval`.
train_cfg = dict(type='IterBasedTrainLoop', max_iters=20000, val_interval=2000)
val_cfg = dict(type='ValLoop') # Use the default validation loop.
test_cfg = dict(type='TestLoop') # Use the default test loop.

事实上,在 OpenMMLab 2.0 中,我们引入了 Loop 来控制训练、验证和测试中的行为。Runner 的功能也发生了变化。您可以在 MMMEngine执行器教程 中找到更多的详细信息。

运行时设置

checkpoint_configlog_config 中的更改:

checkpoint_config 被移动到 default_hooks.checkpoint 中,log_config 被移动到 default_hooks.logger 中。 并且我们将许多钩子设置从脚本代码移动到运行时配置的 default_hooks 字段中。

default_hooks = dict(
    # record the time of every iterations.
    timer=dict(type='IterTimerHook'),

    # print log every 50 iterations.
    logger=dict(type='LoggerHook', interval=50, log_metric_by_epoch=False),

    # enable the parameter scheduler.
    param_scheduler=dict(type='ParamSchedulerHook'),

    # save checkpoint every 2000 iterations.
    checkpoint=dict(type='CheckpointHook', by_epoch=False, interval=2000),

    # set sampler seed in distributed environment.
    sampler_seed=dict(type='DistSamplerSeedHook'),

    # validation results visualization.
    visualization=dict(type='SegVisualizationHook'))

此外,我们将原版 logger 拆分为 logger 和 visualizer。logger 用于记录信息visualizer 用于在不同的后端显示 logger如 terminal 和 TensorBoard。

原版
log_config = dict(
    interval=100,
    hooks=[
        dict(type='TextLoggerHook'),
        dict(type='TensorboardLoggerHook'),
    ])
新版
default_hooks = dict(
    ...
    logger=dict(type='LoggerHook', interval=100),
)
vis_backends = [dict(type='LocalVisBackend'),
                dict(type='TensorboardVisBackend')]
visualizer = dict(
    type='SegLocalVisualizer', vis_backends=vis_backends, name='visualizer')

load_fromresume_from 中的更改:

  • 删除 resume_from。我们使用 resumeload_from 来替换它。
    • 如果 resume=Trueload_fromnot None,则从 load_from 中的检查点恢复训练。
    • 如果 resume=Trueload_fromNone,则尝试从工作目录中的最新检查点恢复。
    • 如果 resume=Falseload_fromnot None,则只加载检查点,而不继续训练。
    • 如果 resume=Falseload_fromNone,则不加载或恢复。

dist_params 中的更改:dist_params 字段现在是 env_cfg 的子字段。并且 env_cfg 中还有一些新的配置。

env_cfg = dict(
    # whether to enable cudnn benchmark
    cudnn_benchmark=False,

    # set multi process parameters
    mp_cfg=dict(mp_start_method='fork', opencv_num_threads=0),

    # set distributed parameters
    dist_cfg=dict(backend='nccl'),
)

workflow 的改动:workflow 相关功能被删除。

新字段 visualizervisualizer 是 OpenMMLab 2.0 体系结构中的新设计。我们在 runner 中使用 visualizer 实例来处理结果和日志可视化,并保存到不同的后端。更多详细信息,请参阅可视化教程

新字段 default_scope搜索所有注册模块的起点。MMSegmentation 中的 default_scopemmseg。请参见注册器教程了解更多详情。