从 MMSegmentation 0.x 迁移¶
引言¶
本指南介绍了 MMSegmentation 0.x 和 MMSegmentation1.x 在表现和 API 方面的基本区别,以及这些与迁移过程的关系。
新的依赖¶
MMSegmentation 1.x 依赖于一些新的软件包,您可以准备一个新的干净环境,然后根据安装教程重新安装。
或手动安装以下软件包。
MMEngine:MMEngine 是 OpenMMLab 2.0 架构的核心,我们将许多与计算机视觉无关的内容从 MMCV 拆分到 MMEngine 中。
MMCV:OpenMMLab 的计算机视觉包。这不是一个新的依赖,但您需要将其升级到 2.0.0 或以上的版本。
MMClassification(可选):OpenMMLab 的图像分类工具箱和基准。这不是一个新的依赖,但您需要将其升级到 1.0.0rc6 版本。
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 |
测试启动¶
与训练启动类似,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.backend
、model.neck
、model.decode_head
和 model.loss
字段没有更改。
添加 model.data_preprocessor
字段以配置 DataPreProcessor
,包括:
mean
(Sequence,可选):R、G、B 通道的像素平均值。默认为 None。std
(Sequence,可选):R、G、B 通道的像素标准差。默认为 None。size
(Sequence,可选):固定的填充大小。size_divisor
(int,可选):填充图像可以被当前值整除。seg_pad_val
(float,可选):分割图的填充值。默认值:255。padding_mode
(str):填充类型。默认值:’constant’。constant:常量值填充,值由 pad_val 指定。
bgr_to_rgb
(bool):是否将图像从 BGR 转换为 RGB。默认为 False。rgb_to_bgr
(bool):是否将图像从 RGB 转换为 BGR。默认为 False。
注: 有关详细信息,请参阅模型文档。
数据集设置¶
data 的更改:
原版 data
字段被拆分为 train_dataloader
、val_dataloader
和 test_dataloader
,允许我们以细粒度配置它们。例如,您可以在训练和测试期间指定不同的采样器和批次大小。
samples_per_gpu
重命名为 batch_size
。
workers_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) # 必须
)
val_dataloader = dict(
batch_size=4,
num_workers=4,
dataset=dict(...),
sampler=dict(type='DefaultSampler', shuffle=False) # 必须
)
test_dataloader = val_dataloader
|
数据增强变换流程变更
原始格式转换
ToTensor
、ImageToTensor
、Collect
组合为PackSegInputs
我们不建议在数据集流程中执行
Normalize
和 Pad。请将其从流程中删除,并将其设置在data_preprocessor
字段中。MMSeg 1.x 中原始的
Resize
已更改为RandomResize
,输入参数img_scale
重命名为scale
,keep_ratio
的默认值修改为 False。原始的
test_pipeline
将单尺度和多尺度测试结合在一起,在 MMSeg 1.x 中,我们将其分为test_pipeline
和tta_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_evaluator
和test_evaluator
。而且不再支持interval
和save_best
参数。interval
已移动到train_cfg.val_interval
,save_best
已移动到default_hooks.checkpoint.save_best
。pre_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 设置¶
optimizer
和 optimizer_config
中的更改:
现在我们使用
optim_wrapper
字段来指定优化过程的所有配置。以及optimizer
是optim_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_cfg
、val_cfg
和 test_cfg
中,以在训练、验证和测试中配置 loop。
原版 |
runner = dict(type='IterBasedRunner', max_iters=20000)
|
新版 |
# `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') # 使用默认的测试循环。
|
事实上,在 OpenMMLab 2.0 中,我们引入了 Loop
来控制训练、验证和测试中的行为。Runner
的功能也发生了变化。您可以在 MMMEngine 的执行器教程 中找到更多的详细信息。
运行时设置¶
checkpoint_config
和 log_config
中的更改:
checkpoint_config
被移动到 default_hooks.checkpoint
中,log_config
被移动到 default_hooks.logger
中。
并且我们将许多钩子设置从脚本代码移动到运行时配置的 default_hooks
字段中。
default_hooks = dict(
# 记录每次迭代的时间。
timer=dict(type='IterTimerHook'),
# 每50次迭代打印一次日志。
logger=dict(type='LoggerHook', interval=50, log_metric_by_epoch=False),
# 启用参数调度程序。
param_scheduler=dict(type='ParamSchedulerHook'),
# 每2000次迭代保存一次检查点。
checkpoint=dict(type='CheckpointHook', by_epoch=False, interval=2000),
# 在分布式环境中设置采样器种子。
sampler_seed=dict(type='DistSamplerSeedHook'),
# 验证结果可视化。
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_from
和 resume_from
中的更改:
删除
resume_from
。我们使用resume
和load_from
来替换它。如果
resume=True
且load_from
为 not None,则从load_from
中的检查点恢复训练。如果
resume=True
且load_from
为 None,则尝试从工作目录中的最新检查点恢复。如果
resume=False
且load_from
为 not None,则只加载检查点,而不继续训练。如果
resume=False
且load_from
为 None,则不加载或恢复。
dist_params
中的更改:dist_params
字段现在是 env_cfg
的子字段。并且 env_cfg
中还有一些新的配置。
env_cfg = dict(
# 是否启用 cudnn_benchmark
cudnn_benchmark=False,
# 设置多进程参数
mp_cfg=dict(mp_start_method='fork', opencv_num_threads=0),
# 设置分布式参数
dist_cfg=dict(backend='nccl'),
)
workflow
的改动:workflow
相关功能被删除。
新字段 visualizer
:visualizer 是 OpenMMLab 2.0 体系结构中的新设计。我们在 runner 中使用 visualizer 实例来处理结果和日志可视化,并保存到不同的后端。更多详细信息,请参阅可视化教程。
新字段 default_scope
:搜索所有注册模块的起点。MMSegmentation 中的 default_scope
为 mmseg
。请参见注册器教程了解更多详情。