このチュートリアルでは、MMDetection で How to xxx
に関する質問への回答を集めています。How to
に関する新しい質問とその回答が見つかった場合は、このドキュメントを更新してください!
MMPretrain を通じてバックボーンネットワークを使用する¶
MMDet、MMPreTrain、MMSeg のモデルレジストリはすべて、MMEngine のルートレジストリを継承しています。これにより、これらのリポジトリは互いに実装済みのモジュールを直接使用できます。したがって、ユーザーは、MMPretrain に既に存在するネットワークを実装することなく、MMDetection で MMPretrain からバックボーンネットワークを使用できます。
MMPretrain に実装されたバックボーンネットワークを使用する¶
RetinaNet
のバックボーンネットワークとしてMobileNetV3-small
を使用したい場合の、設定ファイルの例を以下に示します。
_base_ = [
'../_base_/models/retinanet_r50_fpn.py',
'../_base_/datasets/coco_detection.py',
'../_base_/schedules/schedule_1x.py', '../_base_/default_runtime.py'
]
# please install mmpretrain
# import mmpretrain.models to trigger register_module in mmpretrain
custom_imports = dict(imports=['mmpretrain.models'], allow_failed_imports=False)
pretrained = 'https://download.openmmlab.com/mmclassification/v0/mobilenet_v3/convert/mobilenet_v3_small-8427ecf0.pth'
model = dict(
backbone=dict(
_delete_=True, # Delete the backbone field in _base_
type='mmpretrain.MobileNetV3', # Using MobileNetV3 from mmpretrain
arch='small',
out_indices=(3, 8, 11), # Modify out_indices
init_cfg=dict(
type='Pretrained',
checkpoint=pretrained,
prefix='backbone.')), # The pre-trained weights of backbone network in mmpretrain have prefix='backbone.'. The prefix in the keys will be removed so that these weights can be normally loaded.
# Modify in_channels
neck=dict(in_channels=[24, 48, 96], start_level=0))
MMPretrain を通じて TIMM のバックボーンネットワークを使用する¶
MMPretrain は、PyTorch Image Models (timm) バックボーンネットワークのラッパーも提供しています。ユーザーは、MMPretrain を通じて timm のバックボーンネットワークを直接使用できます。EfficientNet-B1をRetinaNetのバックボーンネットワークとして使用したい場合の、設定ファイルの例を以下に示します。
# https://github.com/open-mmlab/mmdetection/blob/main/configs/timm_example/retinanet_timm-efficientnet-b1_fpn_1x_coco.py
_base_ = [
'../_base_/models/retinanet_r50_fpn.py',
'../_base_/datasets/coco_detection.py',
'../_base_/schedules/schedule_1x.py', '../_base_/default_runtime.py'
]
# please install mmpretrain
# import mmpretrain.models to trigger register_module in mmpretrain
custom_imports = dict(imports=['mmpretrain.models'], allow_failed_imports=False)
model = dict(
backbone=dict(
_delete_=True, # Delete the backbone field in _base_
type='mmpretrain.TIMMBackbone', # Using timm from mmpretrain
model_name='efficientnet_b1',
features_only=True,
pretrained=True,
out_indices=(1, 2, 3, 4)), # Modify out_indices
neck=dict(in_channels=[24, 40, 112, 320])) # Modify in_channels
optimizer = dict(type='SGD', lr=0.01, momentum=0.9, weight_decay=0.0001)
type='mmpretrain.TIMMBackbone'
は、MMDetection で MMPretrain の TIMMBackbone
クラスを使用することを意味し、使用されるモデルは EfficientNet-B1
です。mmpretrain
は MMPretrain リポジトリを、TIMMBackbone
は MMPretrain に実装された TIMMBackbone ラッパーを意味します。
階層型レジストリの原則については、MMEngine ドキュメント を参照してください。MMPretrain の他のバックボーンの使用方法については、MMPretrain ドキュメント を参照してください。
Mosaic 拡張を使用する¶
トレーニングで Mosaic
を使用する場合、同時に MultiImageMixDataset
を使用する必要があります。'Faster R-CNN' アルゴリズムを例として、設定ファイルの train_pipeline
と train_dataset
の値を以下のように変更する必要があります。
# Open configs/faster_rcnn/faster-rcnn_r50_fpn_1x_coco.py directly and add the following fields
data_root = 'data/coco/'
dataset_type = 'CocoDataset'
img_scale=(1333, 800)
train_pipeline = [
dict(type='Mosaic', img_scale=img_scale, pad_val=114.0),
dict(
type='RandomAffine',
scaling_ratio_range=(0.1, 2),
border=(-img_scale[0] // 2, -img_scale[1] // 2)), # The image will be enlarged by 4 times after Mosaic processing,so we use affine transformation to restore the image size.
dict(type='RandomFlip', prob=0.5),
dict(type='PackDetInputs')
]
train_dataset = dict(
_delete_ = True, # remove unnecessary Settings
type='MultiImageMixDataset',
dataset=dict(
type=dataset_type,
ann_file=data_root + 'annotations/instances_train2017.json',
img_prefix=data_root + 'train2017/',
pipeline=[
dict(type='LoadImageFromFile'),
dict(type='LoadAnnotations', with_bbox=True)
],
filter_empty_gt=False,
),
pipeline=train_pipeline
)
data = dict(
train=train_dataset
)
設定ファイルでバックボーンを凍結した後、バックボーンネットワークの凍結を解除する¶
設定ファイルでバックボーンネットワークを凍結し、いくつかのエポック後に凍結を解除したい場合は、フック関数を作成して実行できます。resnet バックボーンを使用する Faster R-CNN を例として、バックボーンネットワークの1つのステージを凍結し、設定ファイルに custom_hooks
を追加できます。
_base_ = [
'../_base_/models/faster-rcnn_r50_fpn.py',
'../_base_/datasets/coco_detection.py',
'../_base_/schedules/schedule_1x.py', '../_base_/default_runtime.py'
]
model = dict(
# freeze one stage of the backbone network.
backbone=dict(frozen_stages=1),
)
custom_hooks = [dict(type="UnfreezeBackboneEpochBasedHook", unfreeze_epoch=1)]
同時に、mmdet/core/hook/unfreeze_backbone_epoch_based_hook.py
にフッククラス UnfreezeBackboneEpochBasedHook
を記述します。
from mmengine.model import is_model_wrapper
from mmengine.hooks import Hook
from mmdet.registry import HOOKS
@HOOKS.register_module()
class UnfreezeBackboneEpochBasedHook(Hook):
"""Unfreeze backbone network Hook.
Args:
unfreeze_epoch (int): The epoch unfreezing the backbone network.
"""
def __init__(self, unfreeze_epoch=1):
self.unfreeze_epoch = unfreeze_epoch
def before_train_epoch(self, runner):
# Unfreeze the backbone network.
# Only valid for resnet.
if runner.epoch == self.unfreeze_epoch:
model = runner.model
if is_model_wrapper(model):
model = model.module
backbone = model.backbone
if backbone.frozen_stages >= 0:
if backbone.deep_stem:
backbone.stem.train()
for param in backbone.stem.parameters():
param.requires_grad = True
else:
backbone.norm1.train()
for m in [backbone.conv1, backbone.norm1]:
for param in m.parameters():
param.requires_grad = True
for i in range(1, backbone.frozen_stages + 1):
m = getattr(backbone, f'layer{i}')
m.train()
for param in m.parameters():
param.requires_grad = True
新しいバックボーンのチャネルを取得する¶
新しいバックボーンのチャネルを取得するには、そのバックボーンを単独で構築し、疑似画像を入力して各ステージの出力を取得できます。
ResNet
を例とします。
from mmdet.models import ResNet
import torch
self = ResNet(depth=18)
self.eval()
inputs = torch.rand(1, 3, 32, 32)
level_outputs = self.forward(inputs)
for level_out in level_outputs:
print(tuple(level_out.shape))
上記のスクリプトの出力は次のとおりです。
(1, 64, 8, 8)
(1, 128, 4, 4)
(1, 256, 2, 2)
(1, 512, 1, 1)
ユーザーはこのスクリプトの ResNet(depth=18)
をカスタマイズしたバックボーンに置き換えることで、新しいバックボーンのチャネルを取得できます。
MMDetection で Detectron2 モデルを使用する¶
ユーザーは Detectron2Wrapper を使用して、MMDetection で Detectron2 のモデルを実行できます。MMDetection では、Faster R-CNN、Mask R-CNN、およびRetinaNet の例を提供しています。
設定ファイルのアルゴリズムコンポーネントは、Detectron2 のものと同じである必要があります。設定時に、まずデフォルトの設定を初期化します。これは Detectron2 で確認できます。次に、設定ファイルの設定がデフォルトの設定を上書きし、これらの設定を使用してモデルが構築されます。入力データは最初に Detectron2 のタイプに変換され、Detectron2 のモデルに供給されます。推論中は、Detectron2 のモデルから計算された結果が MMDetection のタイプに戻されます。
Detectron2 の事前学習済みウェイトを使用する¶
Detectron2Wrapper
のウェイト初期化は、MMDetection のロジックを使用しません。ユーザーは model.d2_detector.weights=xxx
を設定して、事前学習済みウェイトを読み込むことができます。たとえば、model.d2_detector.weights='detectron2://ImageNetPretrained/MSRA/R-50.pkl'
を使用して事前学習済み ResNet-50 を読み込むか、model.d2_detector.weights='detectron2://COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_1x/137260431/model_final_a54504.pkl'
を使用して、Detectron2 で提案された事前学習済み Mask R-CNN ウェイトを読み込むことができます。
**注記:** Detectron2 の事前学習済みモデルは、load_from
を使用して直接読み込むことはできません。tools/model_converters/detectron2_to_mmdet.py
を介して最初に変換する必要があります。
リリースされた detectron2 チェックポイントの推論を行うには、まず tools/model_converters/detectron2_to_mmdet.py
を使用して Detectron2 チェックポイントを MMDetection に変換する必要があります。
python tools/model_converters/detectron2_to_mmdet.py ${Detectron2 ckpt path} ${MMDetectron ckpt path}