MMDetection 2.x から 3.x への設定ファイルの移行¶
MMDetection 3.x の設定ファイルは、2.x バージョンと比べて大幅に変更されています。このドキュメントでは、2.x の設定ファイルを 3.x に移行する方法を説明します。
前のチュートリアル設定ファイルについて学ぶでは、Mask R-CNN を例に MMDetection 3.x の設定ファイル構造を紹介しました。ここでは、同じ構造に従って、2.x の設定ファイルを 3.x に移行する方法を示します。
モデル設定¶
モデル設定は、3.x と 2.x との間で大きな変更はありません。モデルのバックボーン、ネック、ヘッド、そして `train_cfg` と `test_cfg` については、パラメータは 2.x と同じです。
一方、MMDetection 3.x では `DataPreprocessor` モジュールを追加しました。`DataPreprocessor` モジュールの設定は `model.data_preprocessor` にあります。これは、入力データの前処理(入力画像の正規化、サイズが異なる画像のバッチへのパディング、メモリからVRAMへの画像の読み込みなど)に使用されます。この設定は、以前のバージョンの `train_pipeline` と `test_pipeline` の `Normalize` と `Pad` モジュールに置き換わります。
2.x 設定 |
# Image normalization parameters
img_norm_cfg = dict(
mean=[123.675, 116.28, 103.53],
std=[58.395, 57.12, 57.375],
to_rgb=True)
pipeline=[
...,
dict(type='Normalize', **img_norm_cfg),
dict(type='Pad', size_divisor=32), # Padding the image to multiples of 32
...
]
|
3.x 設定 |
model = dict(
data_preprocessor=dict(
type='DetDataPreprocessor',
# Image normalization parameters
mean=[123.675, 116.28, 103.53],
std=[58.395, 57.12, 57.375],
bgr_to_rgb=True,
# Image padding parameters
pad_mask=True, # In instance segmentation, the mask needs to be padded
pad_size_divisor=32) # Padding the image to multiples of 32
)
|
データセットと評価器の設定¶
データセットと評価器の設定は、2.x と比べて大幅に変更されました。データローダーとデータセット、データ変換パイプライン、評価器の設定の3つの側面から、2.x から 3.x への移行方法を紹介します。
データローダーとデータセットの設定¶
新しいバージョンでは、PyTorch の公式 DataLoader とデータ読み込み設定を統一し、ユーザーが理解しやすく、使いやすくしました。トレーニング、検証、テストのデータ読み込み設定を `train_dataloader`、`val_dataloader`、`test_dataloader` にそれぞれ分けて配置しました。ユーザーはこれらのデータローダーに対して異なるパラメータを設定できます。入力パラメータは、基本的に PyTorch DataLoader が要求するパラメータと同じです。
このように、2.x では設定できないパラメータ(`sampler`、`batch_sampler`、`persistent_workers` など)を設定ファイルに配置することで、ユーザーはデータローダーのパラメータをより柔軟に設定できます。
ユーザーは、`train_dataloader.dataset`、`val_dataloader.dataset`、`test_dataloader.dataset` を通じてデータセット設定を設定できます。これは、2.x の `data.train`、`data.val`、`data.test` に対応します。
2.x 設定 |
data = dict(
samples_per_gpu=2,
workers_per_gpu=2,
train=dict(
type=dataset_type,
ann_file=data_root + 'annotations/instances_train2017.json',
img_prefix=data_root + 'train2017/',
pipeline=train_pipeline),
val=dict(
type=dataset_type,
ann_file=data_root + 'annotations/instances_val2017.json',
img_prefix=data_root + 'val2017/',
pipeline=test_pipeline),
test=dict(
type=dataset_type,
ann_file=data_root + 'annotations/instances_val2017.json',
img_prefix=data_root + 'val2017/',
pipeline=test_pipeline))
|
3.x 設定 |
train_dataloader = dict(
batch_size=2,
num_workers=2,
persistent_workers=True, # Avoid recreating subprocesses after each iteration
sampler=dict(type='DefaultSampler', shuffle=True), # Default sampler, supports both distributed and non-distributed training
batch_sampler=dict(type='AspectRatioBatchSampler'), # Default batch_sampler, used to ensure that images in the batch have similar aspect ratios, so as to better utilize graphics memory
dataset=dict(
type=dataset_type,
data_root=data_root,
ann_file='annotations/instances_train2017.json',
data_prefix=dict(img='train2017/'),
filter_cfg=dict(filter_empty_gt=True, min_size=32),
pipeline=train_pipeline))
# In version 3.x, validation and test dataloaders can be configured independently
val_dataloader = dict(
batch_size=1,
num_workers=2,
persistent_workers=True,
drop_last=False,
sampler=dict(type='DefaultSampler', shuffle=False),
dataset=dict(
type=dataset_type,
data_root=data_root,
ann_file='annotations/instances_val2017.json',
data_prefix=dict(img='val2017/'),
test_mode=True,
pipeline=test_pipeline))
test_dataloader = val_dataloader # The configuration of the testing dataloader is the same as that of the validation dataloader, which is omitted here
|
データ変換パイプラインの設定¶
前述のように、画像の正規化とパディングの設定を `train_pipeline` と `test_pipeline` から分離し、代わりに `model.data_preprocessor` に配置しました。そのため、3.x バージョンのパイプラインでは、`Normalize` と `Pad` 変換は不要になりました。
同時に、データ形式をパックする変換もリファクタリングし、`Collect` と `DefaultFormatBundle` 変換を `PackDetInputs` にマージしました。この変換は、データパイプラインからのデータをモデルの入力形式にパックする役割を担っています。入力形式変換の詳細については、データフローのドキュメントを参照してください。
以下では、Mask R-CNN の `train_pipeline` を例に、2.x の設定から 3.x の設定への移行方法を示します。
2.x 設定 |
img_norm_cfg = dict(
mean=[123.675, 116.28, 103.53], std=[58.395, 57.12, 57.375], to_rgb=True)
train_pipeline = [
dict(type='LoadImageFromFile'),
dict(type='LoadAnnotations', with_bbox=True),
dict(type='Resize', img_scale=(1333, 800), keep_ratio=True),
dict(type='RandomFlip', flip_ratio=0.5),
dict(type='Normalize', **img_norm_cfg),
dict(type='Pad', size_divisor=32),
dict(type='DefaultFormatBundle'),
dict(type='Collect', keys=['img', 'gt_bboxes', 'gt_labels']),
]
|
3.x 設定 |
train_pipeline = [
dict(type='LoadImageFromFile'),
dict(type='LoadAnnotations', with_bbox=True),
dict(type='Resize', scale=(1333, 800), keep_ratio=True),
dict(type='RandomFlip', prob=0.5),
dict(type='PackDetInputs')
]
|
`test_pipeline` については、`Normalize` と `Pad` 変換の削除に加えて、テスト時のデータ拡張(TTA)を通常のテストプロセスから分離し、`MultiScaleFlipAug` を削除しました。新しい TTA バージョンの使用方法の詳細については、TTA ドキュメントを参照してください。
以下では、Mask R-CNN の `test_pipeline` を例に、2.x の設定から 3.x の設定への移行方法を示します。
2.x 設定 |
test_pipeline = [
dict(type='LoadImageFromFile'),
dict(
type='MultiScaleFlipAug',
img_scale=(1333, 800),
flip=False,
transforms=[
dict(type='Resize', keep_ratio=True),
dict(type='RandomFlip'),
dict(type='Normalize', **img_norm_cfg),
dict(type='Pad', size_divisor=32),
dict(type='ImageToTensor', keys=['img']),
dict(type='Collect', keys=['img']),
])
]
|
3.x 設定 |
test_pipeline = [
dict(type='LoadImageFromFile'),
dict(type='Resize', scale=(1333, 800), keep_ratio=True),
dict(
type='PackDetInputs',
meta_keys=('img_id', 'img_path', 'ori_shape', 'img_shape',
'scale_factor'))
]
|
さらに、いくつかのデータ拡張変換もリファクタリングしました。次の表に、2.x バージョンと 3.x バージョンで使用される変換のマッピングを示します。
名称 | 2.x 設定 | 3.x 設定 |
---|---|---|
Resize |
dict(type='Resize',
img_scale=(1333, 800),
keep_ratio=True)
|
dict(type='Resize',
scale=(1333, 800),
keep_ratio=True)
|
RandomResize |
dict(
type='Resize',
img_scale=[
(1333, 640), (1333, 800)],
multiscale_mode='range',
keep_ratio=True)
|
dict(
type='RandomResize',
scale=[
(1333, 640), (1333, 800)],
keep_ratio=True)
|
RandomChoiceResize |
dict(
type='Resize',
img_scale=[
(1333, 640), (1333, 672),
(1333, 704), (1333, 736),
(1333, 768), (1333, 800)],
multiscale_mode='value',
keep_ratio=True)
|
dict(
type='RandomChoiceResize',
scales=[
(1333, 640), (1333, 672),
(1333, 704), (1333, 736),
(1333, 768), (1333, 800)],
keep_ratio=True)
|
RandomFlip |
dict(type='RandomFlip', flip_ratio=0.5)
|
dict(type='RandomFlip', prob=0.5)
|
評価器の設定¶
3.x バージョンでは、モデル精度の評価はデータセットに関連付けられなくなり、代わりに Evaluator を使用して行われます。Evaluator の設定は、`val_evaluator` と `test_evaluator` の2つの部分に分かれています。`val_evaluator` は検証データセットの評価に使用され、`test_evaluator` はテストデータセットの評価に使用されます。これは、2.x バージョンの `evaluation` フィールドに対応します。
次の表は、2.x と 3.x の Evaluator の対応関係を示しています。
メトリック名 | 2.x 設定 | 3.x 設定 |
---|---|---|
COCO |
data = dict(
val=dict(
type='CocoDataset',
ann_file=data_root + 'annotations/instances_val2017.json'))
evaluation = dict(metric=['bbox', 'segm'])
|
val_evaluator = dict(
type='CocoMetric',
ann_file=data_root + 'annotations/instances_val2017.json',
metric=['bbox', 'segm'],
format_only=False)
|
Pascal VOC |
data = dict(
val=dict(
type=dataset_type,
ann_file=data_root + 'VOC2007/ImageSets/Main/test.txt'))
evaluation = dict(metric='mAP')
|
val_evaluator = dict(
type='VOCMetric',
metric='mAP',
eval_mode='11points')
|
OpenImages |
data = dict(
val=dict(
type='OpenImagesDataset',
ann_file=data_root + 'annotations/validation-annotations-bbox.csv',
img_prefix=data_root + 'OpenImages/validation/',
label_file=data_root + 'annotations/class-descriptions-boxable.csv',
hierarchy_file=data_root +
'annotations/bbox_labels_600_hierarchy.json',
meta_file=data_root + 'annotations/validation-image-metas.pkl',
image_level_ann_file=data_root +
'annotations/validation-annotations-human-imagelabels-boxable.csv'))
evaluation = dict(interval=1, metric='mAP')
|
val_evaluator = dict(
type='OpenImagesMetric',
iou_thrs=0.5,
ioa_thrs=0.5,
use_group_of=True,
get_supercategory=True)
|
CityScapes |
data = dict(
val=dict(
type='CityScapesDataset',
ann_file=data_root +
'annotations/instancesonly_filtered_gtFine_val.json',
img_prefix=data_root + 'leftImg8bit/val/',
pipeline=test_pipeline))
evaluation = dict(metric=['bbox', 'segm'])
|
val_evaluator = [
dict(
type='CocoMetric',
ann_file=data_root +
'annotations/instancesonly_filtered_gtFine_val.json',
metric=['bbox', 'segm']),
dict(
type='CityScapesMetric',
ann_file=data_root +
'annotations/instancesonly_filtered_gtFine_val.json',
seg_prefix=data_root + '/gtFine/val',
outfile_prefix='./work_dirs/cityscapes_metric/instance')
]
|
訓練とテストの設定¶
2.x 設定 |
runner = dict(
type='EpochBasedRunner', # Type of training loop
max_epochs=12) # Maximum number of training epochs
evaluation = dict(interval=2) # Interval for evaluation, check the performance every 2 epochs
|
3.x 設定 |
train_cfg = dict(
type='EpochBasedTrainLoop', # Type of training loop, please refer to https://github.com/open-mmlab/mmengine/blob/main/mmengine/runner/loops.py
max_epochs=12, # Maximum number of training epochs
val_interval=2) # Interval for validation, check the performance every 2 epochs
val_cfg = dict(type='ValLoop') # Type of validation loop
test_cfg = dict(type='TestLoop') # Type of testing loop
|
最適化の設定¶
最適化器と勾配クリッピングの設定は、`optim_wrapper` フィールドに移動されました。次の表は、2.x バージョンと 3.x バージョンの最適化器設定の対応関係を示しています。
2.x 設定 |
optimizer = dict(
type='SGD', # Optimizer: Stochastic Gradient Descent
lr=0.02, # Base learning rate
momentum=0.9, # SGD with momentum
weight_decay=0.0001) # Weight decay
optimizer_config = dict(grad_clip=None) # Configuration for gradient clipping, set to None to disable
|
3.x 設定 |
optim_wrapper = dict( # Configuration for the optimizer wrapper
type='OptimWrapper', # Type of optimizer wrapper, you can switch to AmpOptimWrapper to enable mixed precision training
optimizer=dict( # Optimizer configuration, supports various PyTorch optimizers, please refer to https://pytorch.org/docs/stable/optim.html#algorithms
type='SGD', # SGD
lr=0.02, # Base learning rate
momentum=0.9, # SGD with momentum
weight_decay=0.0001), # Weight decay
clip_grad=None, # Configuration for gradient clipping, set to None to disable. For usage, please see https://mmengine.readthedocs.io/en/latest/tutorials/optimizer.html
)
|
学習率の設定は、lr_config
フィールドからparam_scheduler
フィールドに移行されました。param_scheduler
の設定は、PyTorchの学習率スケジューラにより近く、より柔軟です。以下の表は、2.xバージョンと3.xバージョンの学習率設定の対応関係を示しています。
2.x 設定 |
lr_config = dict(
policy='step', # Use multi-step learning rate strategy during training
warmup='linear', # Use linear learning rate warmup
warmup_iters=500, # End warmup at iteration 500
warmup_ratio=0.001, # Coefficient for learning rate warmup
step=[8, 11], # Learning rate decay at which epochs
gamma=0.1) # Learning rate decay coefficient
|
3.x 設定 |
param_scheduler = [
dict(
type='LinearLR', # Use linear learning rate warmup
start_factor=0.001, # Coefficient for learning rate warmup
by_epoch=False, # Update the learning rate during warmup at each iteration
begin=0, # Starting from the first iteration
end=500), # End at the 500th iteration
dict(
type='MultiStepLR', # Use multi-step learning rate strategy during training
by_epoch=True, # Update the learning rate at each epoch
begin=0, # Starting from the first epoch
end=12, # Ending at the 12th epoch
milestones=[8, 11], # Learning rate decay at which epochs
gamma=0.1) # Learning rate decay coefficient
]
|
その他の学習率調整ポリシーの移行方法については、MMEngineの学習率移行ドキュメントを参照してください。
その他の設定の移行¶
チェックポイント保存の設定¶
機能 | 2.x 設定 | 3.x 設定 |
---|---|---|
保存間隔の設定 |
checkpoint_config = dict(
interval=1)
|
default_hooks = dict(
checkpoint=dict(
type='CheckpointHook',
interval=1))
|
最良モデルの保存 |
evaluation = dict(
save_best='auto')
|
default_hooks = dict(
checkpoint=dict(
type='CheckpointHook',
save_best='auto'))
|
最新モデルの保持 |
checkpoint_config = dict(
max_keep_ckpts=3)
|
default_hooks = dict(
checkpoint=dict(
type='CheckpointHook',
max_keep_ckpts=3))
|
ログの設定¶
MMDetection 3.xでは、ログの出力と視覚化は、MMEngineのロガーとビジュアライザーによってそれぞれ実行されます。以下の表は、MMDetection 2.xと3.xにおけるログの出力と視覚化の設定の比較を示しています。
機能 | 2.x 設定 | 3.x 設定 |
---|---|---|
ログ出力間隔の設定 |
log_config = dict(interval=50)
|
default_hooks = dict(
logger=dict(type='LoggerHook', interval=50))
# Optional: set moving average window size
log_processor = dict(
type='LogProcessor', window_size=50)
|
TensorBoardまたはWandBを使用したログの視覚化 |
log_config = dict(
interval=50,
hooks=[
dict(type='TextLoggerHook'),
dict(type='TensorboardLoggerHook'),
dict(type='MMDetWandbHook',
init_kwargs={
'project': 'mmdetection',
'group': 'maskrcnn-r50-fpn-1x-coco'
},
interval=50,
log_checkpoint=True,
log_checkpoint_metadata=True,
num_eval_images=100)
])
|
vis_backends = [
dict(type='LocalVisBackend'),
dict(type='TensorboardVisBackend'),
dict(type='WandbVisBackend',
init_kwargs={
'project': 'mmdetection',
'group': 'maskrcnn-r50-fpn-1x-coco'
})
]
visualizer = dict(
type='DetLocalVisualizer',
vis_backends=vis_backends,
name='visualizer')
|
視覚化関連のチュートリアルについては、MMDetectionの視覚化チュートリアルを参照してください。
ランタイム設定¶
3.xバージョンのランタイム設定項目は調整されており、具体的な対応は以下のとおりです。
2.x 設定 | 3.x 設定 |
---|---|
cudnn_benchmark = False
opencv_num_threads = 0
mp_start_method = 'fork'
dist_params = dict(backend='nccl')
log_level = 'INFO'
load_from = None
resume_from = None
|
env_cfg = dict(
cudnn_benchmark=False,
mp_cfg=dict(mp_start_method='fork',
opencv_num_threads=0),
dist_cfg=dict(backend='nccl'))
log_level = 'INFO'
load_from = None
resume = False
|