open-mmlab / mmdetection

OpenMMLab Detection Toolbox and Benchmark
https://mmdetection.readthedocs.io
Apache License 2.0
29.74k stars 9.48k forks source link

How to use "train_detector"? #8245

Closed kimlia545 closed 2 years ago

kimlia545 commented 2 years ago
from mmcv import Config
cfg = Config.fromfile('./configs/faster_rcnn_r50_caffe_fpn_mstrain_1x_coco.py')
from mmdet.apis import set_random_seed

cfg.dataset_type = 'CocoDataset'
cfg.data_root = 'split_data/'

cfg.img_norm_cfg = dict(
    mean=[123.675, 116.28, 103.53], std=[58.395, 57.12, 57.375], to_rgb=True)
cfg.train_pipeline = [
    dict(type='LoadImageFromFile'),
    dict(type='LoadAnnotations', with_bbox=True),
    dict(type='Resize', img_scale=(408, 544), keep_ratio=True),
    dict(type='RandomFlip', flip_ratio=0.5),
    dict(
        type='Normalize',
        mean=[123.675, 116.28, 103.53],
        std=[58.395, 57.12, 57.375],
        to_rgb=True),
    dict(type='Pad', size_divisor=32),
    dict(type='DefaultFormatBundle'),
    dict(type='Collect', keys=['img', 'gt_bboxes', 'gt_labels']),
]
cfg.test_pipeline = [
    dict(type='LoadImageFromFile'),
    dict(
        type='MultiScaleFlipAug',
        img_scale=(408, 544),
        flip=False,
        transforms=[
            dict(type='Resize', keep_ratio=True),
            dict(type='RandomFlip'),
            dict(
                type='Normalize',
                mean=[123.675, 116.28, 103.53],
                std=[58.395, 57.12, 57.375],
                to_rgb=True),
            dict(type='Pad', size_divisor=32),
            dict(type='ImageToTensor', keys=['img']),
            dict(type='Collect', keys=['img']),
        ])
]

cfg.data.test.type = 'CocoDataset'
cfg.data.test.data_root = 'split_data/test/'
cfg.data.test.ann_file = 'test.json'
cfg.data.test.img_prefix = 'split_data/test/images'

cfg.data.train.type = 'CocoDataset'
cfg.data.train.data_root = 'split_data/train/'
cfg.data.train.ann_file = 'train.json'
cfg.data.train.img_prefix = 'split_data/train/images'

cfg.data.val.type = 'CocoDataset'
cfg.data.val.data_root = 'split_data/valid/'
cfg.data.val.ann_file = 'valid.json'
cfg.data.val.img_prefix = 'split_data/valid/images'

cfg.model.roi_head.bbox_head.num_classes = 4
cfg.load_from = 'checkpoints/faster_rcnn_r50_caffe_fpn_mstrain_3x_coco_20210526_095054-1f77628b.pth'

cfg.work_dir = './custom_train'

cfg.optimizer.lr = 0.02 / 8
cfg.lr_config.warmup = None
cfg.log_config.interval = 10

cfg.evaluation.metric = 'mAP'
cfg.evaluation.interval = 12
cfg.checkpoint_config.interval = 12

cfg.device='cuda'
cfg.seed = 0
set_random_seed(0, deterministic=False)
cfg.gpu_ids = range(1)

cfg.log_config.hooks = [
    dict(type='TextLoggerHook'),
    dict(type='TensorboardLoggerHook')]

print(f'Config:\n{cfg.pretty_text}')
from mmdet.datasets import build_dataset
from mmdet.models import build_detector
from mmdet.apis import train_detector

datasets = [build_dataset(cfg.data.train)]

model = build_detector(cfg.model)
model.CLASSES = datasets[0].CLASSES

mmcv.mkdir_or_exist(osp.abspath(cfg.work_dir))
train_detector(model, datasets, cfg, distributed=False, validate=True)

ERROR

AssertionError Traceback (most recent call last)

in 13 # Create work_dir 14 mmcv.mkdir_or_exist(osp.abspath(cfg.work_dir)) ---> 15 train_detector(model, datasets, cfg, distributed=False, validate=True) ~/Desktop/mmdetection/mmdet/apis/train.py in train_detector(model, dataset, cfg, distributed, validate, timestamp, meta) 242 elif cfg.load_from: 243 runner.load_checkpoint(cfg.load_from) --> 244 runner.run(data_loaders, cfg.workflow) ~/.local/lib/python3.8/site-packages/mmcv/runner/epoch_based_runner.py in run(self, data_loaders, workflow, max_epochs, **kwargs) 125 if mode == 'train' and self.epoch >= self._max_epochs: 126 break --> 127 epoch_runner(data_loaders[i], **kwargs) 128 129 time.sleep(1) # wait for some hooks like loggers to finish ~/.local/lib/python3.8/site-packages/mmcv/runner/epoch_based_runner.py in train(self, data_loader, **kwargs) 43 self.data_loader = data_loader 44 self._max_iters = self._max_epochs * len(self.data_loader) ---> 45 self.call_hook('before_train_epoch') 46 time.sleep(2) # Prevent possible deadlock during epoch transition 47 for i, data_batch in enumerate(self.data_loader): ~/.local/lib/python3.8/site-packages/mmcv/runner/base_runner.py in call_hook(self, fn_name) 307 """ 308 for hook in self._hooks: --> 309 getattr(hook, fn_name)(self) 310 311 def get_hook_info(self): ~/Desktop/mmdetection/mmdet/datasets/utils.py in before_train_epoch(self, runner) 156 runner (obj:`EpochBasedRunner`): Epoch based Runner. 157 """ --> 158 self._check_head(runner) 159 160 def before_val_epoch(self, runner): ~/Desktop/mmdetection/mmdet/datasets/utils.py in _check_head(self, runner) 142 if hasattr(module, 'num_classes') and not isinstance( 143 module, (RPNHead, VGG, FusedSemanticHead, GARPNHead)): --> 144 assert module.num_classes == len(dataset.CLASSES), \ 145 (f'The `num_classes` ({module.num_classes}) in ' 146 f'{module.__class__.__name__} of ' AssertionError: The `num_classes` (4) in Shared2FCBBoxHead of MMDataParallel does not matches the length of `CLASSES` 80) in CocoDataset ``` Config: model = dict( type='FastRCNN', backbone=dict( type='ResNet', depth=50, num_stages=4, out_indices=(0, 1, 2, 3), frozen_stages=1, norm_cfg=dict(type='BN', requires_grad=False), norm_eval=True, style='caffe', init_cfg=dict( type='Pretrained', checkpoint='open-mmlab://detectron2/resnet50_caffe')), neck=dict( type='FPN', in_channels=[256, 512, 1024, 2048], out_channels=256, num_outs=5), roi_head=dict( type='StandardRoIHead', bbox_roi_extractor=dict( type='SingleRoIExtractor', roi_layer=dict(type='RoIAlign', output_size=7, sampling_ratio=0), out_channels=256, featmap_strides=[4, 8, 16, 32]), bbox_head=dict( type='Shared2FCBBoxHead', in_channels=256, fc_out_channels=1024, roi_feat_size=7, num_classes=4, bbox_coder=dict( type='DeltaXYWHBBoxCoder', target_means=[0.0, 0.0, 0.0, 0.0], target_stds=[0.1, 0.1, 0.2, 0.2]), reg_class_agnostic=False, loss_cls=dict( type='CrossEntropyLoss', use_sigmoid=False, loss_weight=1.0), loss_bbox=dict(type='L1Loss', loss_weight=1.0))), train_cfg=dict( rcnn=dict( assigner=dict( type='MaxIoUAssigner', pos_iou_thr=0.5, neg_iou_thr=0.5, min_pos_iou=0.5, match_low_quality=False, ignore_iof_thr=-1), sampler=dict( type='RandomSampler', num=512, pos_fraction=0.25, neg_pos_ub=-1, add_gt_as_proposals=True), pos_weight=-1, debug=False)), test_cfg=dict( rcnn=dict( score_thr=0.05, nms=dict(type='nms', iou_threshold=0.5), max_per_img=100))) dataset_type = 'CocoDataset' data_root = 'split_data/' 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=(408, 544), keep_ratio=True), dict(type='RandomFlip', flip_ratio=0.5), dict( type='Normalize', mean=[123.675, 116.28, 103.53], std=[58.395, 57.12, 57.375], to_rgb=True), dict(type='Pad', size_divisor=32), dict(type='DefaultFormatBundle'), dict(type='Collect', keys=['img', 'gt_bboxes', 'gt_labels']) ] 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', mean=[103.53, 116.28, 123.675], std=[1.0, 1.0, 1.0], to_rgb=False), dict(type='Pad', size_divisor=32), dict(type='ImageToTensor', keys=['img']), dict(type='Collect', keys=['img']) ]) ] data = dict( samples_per_gpu=2, workers_per_gpu=2, train=dict( type='CocoDataset', ann_file='train.json', img_prefix='split_data/train/images', pipeline=[ dict(type='LoadImageFromFile'), dict(type='LoadAnnotations', with_bbox=True), 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='RandomFlip', flip_ratio=0.5), dict( type='Normalize', mean=[103.53, 116.28, 123.675], std=[1.0, 1.0, 1.0], to_rgb=False), dict(type='Pad', size_divisor=32), dict(type='DefaultFormatBundle'), dict(type='Collect', keys=['img', 'gt_bboxes', 'gt_labels']) ], data_root='split_data/train/'), val=dict( type='CocoDataset', ann_file='valid.json', img_prefix='split_data/valid/images', 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', mean=[103.53, 116.28, 123.675], std=[1.0, 1.0, 1.0], to_rgb=False), dict(type='Pad', size_divisor=32), dict(type='ImageToTensor', keys=['img']), dict(type='Collect', keys=['img']) ]) ], data_root='split_data/valid/'), test=dict( type='CocoDataset', ann_file='test.json', img_prefix='split_data/test/images', 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', mean=[103.53, 116.28, 123.675], std=[1.0, 1.0, 1.0], to_rgb=False), dict(type='Pad', size_divisor=32), dict(type='ImageToTensor', keys=['img']), dict(type='Collect', keys=['img']) ]) ], data_root='split_data/test/')) evaluation = dict(interval=12, metric='mAP') optimizer = dict(type='SGD', lr=0.0025, momentum=0.9, weight_decay=0.0001) optimizer_config = dict(grad_clip=None) lr_config = dict( policy='step', warmup=None, warmup_iters=500, warmup_ratio=0.001, step=[8, 11]) runner = dict(type='EpochBasedRunner', max_epochs=12) checkpoint_config = dict(interval=12) log_config = dict( interval=10, hooks=[dict(type='TextLoggerHook'), dict(type='TensorboardLoggerHook')]) custom_hooks = [dict(type='NumClassCheckHook')] dist_params = dict(backend='nccl') log_level = 'INFO' load_from = 'checkpoints/faster_rcnn_r50_caffe_fpn_mstrain_3x_coco_20210526_095054-1f77628b.pth' resume_from = None workflow = [('train', 1)] opencv_num_threads = 0 mp_start_method = 'fork' auto_scale_lr = dict(enable=False, base_batch_size=16) work_dir = './tutorial_exps' device = 'cuda' seed = 0 gpu_ids = range(0, 1) ``` # The dataset doesn't seem to have been modified. How do I fix it? ``` from mmdet.utils import update_data_root update_data_root(cfg) datasets = [build_dataset(cfg.data.train)] datasets ``` loading annotations into memory... Done (t=0.12s) creating index... index created! [ CocoDataset Train dataset with number of images 0, and instance counts: +---------------------+-------+-----------------+-------+--------------------+-------+--------------------+-------+-------------------+-------+ | category | count | category | count | category | count | category | count | category | count | +---------------------+-------+-----------------+-------+--------------------+-------+--------------------+-------+-------------------+-------+ | 0 [person] | 0 | 1 [bicycle] | 0 | 2 [car] | 0 | 3 [motorcycle] | 0 | 4 [airplane] | 0 | | 5 [bus] | 0 | 6 [train] | 0 | 7 [truck] | 0 | 8 [boat] | 0 | 9 [traffic light] | 0 | | 10 [fire hydrant] | 0 | 11 [stop sign] | 0 | 12 [parking meter] | 0 | 13 [bench] | 0 | 14 [bird] | 0 | | 15 [cat] | 0 | 16 [dog] | 0 | 17 [horse] | 0 | 18 [sheep] | 0 | 19 [cow] | 0 | | 20 [elephant] | 0 | 21 [bear] | 0 | 22 [zebra] | 0 | 23 [giraffe] | 0 | 24 [backpack] | 0 | | 25 [umbrella] | 0 | 26 [handbag] | 0 | 27 [tie] | 0 | 28 [suitcase] | 0 | 29 [frisbee] | 0 | | 30 [skis] | 0 | 31 [snowboard] | 0 | 32 [sports ball] | 0 | 33 [kite] | 0 | 34 [baseball bat] | 0 | | 35 [baseball glove] | 0 | 36 [skateboard] | 0 | 37 [surfboard] | 0 | 38 [tennis racket] | 0 | 39 [bottle] | 0 | | 40 [wine glass] | 0 | 41 [cup] | 0 | 42 [fork] | 0 | 43 [knife] | 0 | 44 [spoon] | 0 | | 45 [bowl] | 0 | 46 [banana] | 0 | 47 [apple] | 0 | 48 [sandwich] | 0 | 49 [orange] | 0 | | 50 [broccoli] | 0 | 51 [carrot] | 0 | 52 [hot dog] | 0 | 53 [pizza] | 0 | 54 [donut] | 0 | | 55 [cake] | 0 | 56 [chair] | 0 | 57 [couch] | 0 | 58 [potted plant] | 0 | 59 [bed] | 0 | | 60 [dining table] | 0 | 61 [toilet] | 0 | 62 [tv] | 0 | 63 [laptop] | 0 | 64 [mouse] | 0 | | 65 [remote] | 0 | 66 [keyboard] | 0 | 67 [cell phone] | 0 | 68 [microwave] | 0 | 69 [oven] | 0 | | 70 [toaster] | 0 | 71 [sink] | 0 | 72 [refrigerator] | 0 | 73 [book] | 0 | 74 [clock] | 0 | | 75 [vase] | 0 | 76 [scissors] | 0 | 77 [teddy bear] | 0 | 78 [hair drier] | 0 | 79 [toothbrush] | 0 | +---------------------+-------+-----------------+-------+--------------------+-------+--------------------+-------+-------------------+-------+]
kimlia545 commented 2 years ago

solved it The problem was caused by not defining classes in the data.

https://mmdetection.readthedocs.io/en/stable/tutorials/customize_dataset.html

# the new config inherits the base configs to highlight the necessary modification
_base_ = './cascade_mask_rcnn_r50_fpn_1x_coco.py'

# 1. dataset settings
dataset_type = 'CocoDataset'
classes = ('a', 'b', 'c', 'd', 'e')
data = dict(
    samples_per_gpu=2,
    workers_per_gpu=2,
    train=dict(
        type=dataset_type,
        # explicitly add your class names to the field `classes`
        classes=classes,
        ann_file='path/to/your/train/annotation_data',
        img_prefix='path/to/your/train/image_data'),
    val=dict(
        type=dataset_type,
        # explicitly add your class names to the field `classes`
        classes=classes,
        ann_file='path/to/your/val/annotation_data',
        img_prefix='path/to/your/val/image_data'),
    test=dict(
        type=dataset_type,
        # explicitly add your class names to the field `classes`
        classes=classes,
        ann_file='path/to/your/test/annotation_data',
        img_prefix='path/to/your/test/image_data'))

# 2. model settings

# explicitly over-write all the `num_classes` field from default 80 to 5.
model = dict(
    roi_head=dict(
        bbox_head=[
            dict(
                type='Shared2FCBBoxHead',
                # explicitly over-write all the `num_classes` field from default 80 to 5.
                num_classes=5),
            dict(
                type='Shared2FCBBoxHead',
                # explicitly over-write all the `num_classes` field from default 80 to 5.
                num_classes=5),
            dict(
                type='Shared2FCBBoxHead',
                # explicitly over-write all the `num_classes` field from default 80 to 5.
                num_classes=5)],
    # explicitly over-write all the `num_classes` field from default 80 to 5.
    mask_head=dict(num_classes=5)))