# 从 MMSegmentation 0.x 迁移 ## 引言 本指南介绍了 MMSegmentation 0.x 和 MMSegmentation1.x 在表现和 API 方面的基本区别,以及这些与迁移过程的关系。 ## 新的依赖 MMSegmentation 1.x 依赖于一些新的软件包,您可以准备一个新的干净环境,然后根据[安装教程](../get_started.md)重新安装。 或手动安装以下软件包。 1. [MMEngine](https://github.com/open-mmlab/mmengine):MMEngine 是 OpenMMLab 2.0 架构的核心,我们将许多与计算机视觉无关的内容从 MMCV 拆分到 MMEngine 中。 2. [MMCV](https://github.com/open-mmlab/mmcv):OpenMMLab 的计算机视觉包。这不是一个新的依赖,但您需要将其升级到 **2.0.0** 或以上的版本。 3. [MMClassification](https://github.com/open-mmlab/mmclassification)(可选):OpenMMLab 的图像分类工具箱和基准。这不是一个新的依赖,但您需要将其升级到 **1.0.0rc6** 版本。 4. [MMDetection](https://github.com/open-mmlab/mmdetection)(可选): OpenMMLab 的目标检测工具箱和基准。这不是一个新的依赖,但您需要将其升级到 **3.0.0** 或以上的版本。 ## 启动训练 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 |
功能 | 0.x | 1.x |
指定评测指标 | --eval mIoU | --cfg-options test_evaluator.type=IoUMetric |
测试时数据增强 | --aug-test | --tta |
测试时是否只保存预测结果不计算评测指标 | --format-only | --cfg-options test_evaluator.format_only=True |
原版 | ```python data = dict( samples_per_gpu=4, workers_per_gpu=4, train=dict(...), val=dict(...), test=dict(...), ) ``` |
新版 | ```python train_dataloader = dict( batch_size=4, num_workers=4, dataset=dict(...), sampler=dict(type='DefaultSampler', shuffle=True) # 必须 ) val_dataloader = dict( batch_size=4, num_workers=4, dataset=dict(...), sampler=dict(type='DefaultSampler', shuffle=False) # 必须 ) test_dataloader = val_dataloader ``` |
原版 | ```python 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']), ] ``` |
新版 | ```python 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') ] ``` |
原版 | ```python 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']), ]) ] ``` |
新版 | ```python 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')] ]) ] ``` |
原版 | ```python evaluation = dict(interval=2000, metric='mIoU', pre_eval=True) ``` |
新版 | ```python val_evaluator = dict(type='IoUMetric', iou_metrics=['mIoU']) test_evaluator = val_evaluator ``` |
原版 | ```python optimizer = dict(type='AdamW', lr=0.0001, weight_decay=0.0005) optimizer_config = dict(grad_clip=dict(max_norm=1, norm_type=2)) ``` |
新版 | ```python 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)) ``` |
原版 | ```python lr_config = dict( policy='poly', warmup='linear', warmup_iters=1500, warmup_ratio=1e-6, power=1.0, min_lr=0.0, by_epoch=False) ``` |
新版 | ```python 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, ) ] ``` |
原版 | ```python runner = dict(type='IterBasedRunner', max_iters=20000) ``` |
新版 | ```python # `val_interval` 是旧版本的 `evaluation.interval`。 train_cfg = dict(type='IterBasedTrainLoop', max_iters=20000, val_interval=2000) val_cfg = dict(type='ValLoop') # 使用默认的验证循环。 test_cfg = dict(type='TestLoop') # 使用默认的测试循环。 ``` |
原版 | ```python log_config = dict( interval=100, hooks=[ dict(type='TextLoggerHook'), dict(type='TensorboardLoggerHook'), ]) ``` |
新版 | ```python 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') ``` |