diff --git a/.circleci/test.yml b/.circleci/test.yml index 994d4b94e01..f98014366dd 100644 --- a/.circleci/test.yml +++ b/.circleci/test.yml @@ -91,7 +91,7 @@ jobs: type: string cuda: type: enum - enum: ["10.1", "10.2", "11.1"] + enum: ["10.1", "10.2", "11.1", "11.7"] cudnn: type: integer default: 7 @@ -161,8 +161,8 @@ workflows: - lint - build_cpu: name: maximum_version_cpu - torch: 1.13.0 - torchvision: 0.14.0 + torch: 2.0.0 + torchvision: 0.15.1 python: 3.9.0 requires: - minimum_version_cpu @@ -178,6 +178,13 @@ workflows: cuda: "10.2" requires: - hold + - build_cuda: + name: maximum_version_gpu + torch: 2.0.0 + cuda: "11.7" + cudnn: 8 + requires: + - hold merge_stage_test: when: not: << pipeline.parameters.lint_only >> diff --git a/README.md b/README.md index 2cbbe559f1f..1718b0c868a 100644 --- a/README.md +++ b/README.md @@ -21,15 +21,15 @@ [![PyPI](https://img.shields.io/pypi/v/mmdet)](https://pypi.org/project/mmdet) [![docs](https://img.shields.io/badge/docs-latest-blue)](https://mmdetection.readthedocs.io/en/latest/) [![badge](https://github.com/open-mmlab/mmdetection/workflows/build/badge.svg)](https://github.com/open-mmlab/mmdetection/actions) -[![codecov](https://codecov.io/gh/open-mmlab/mmdetection/branch/master/graph/badge.svg)](https://codecov.io/gh/open-mmlab/mmdetection) -[![license](https://img.shields.io/github/license/open-mmlab/mmdetection.svg)](https://github.com/open-mmlab/mmdetection/blob/master/LICENSE) +[![codecov](https://codecov.io/gh/open-mmlab/mmdetection/branch/main/graph/badge.svg)](https://codecov.io/gh/open-mmlab/mmdetection) +[![license](https://img.shields.io/github/license/open-mmlab/mmdetection.svg)](https://github.com/open-mmlab/mmdetection/blob/main/LICENSE) [![open issues](https://isitmaintained.com/badge/open/open-mmlab/mmdetection.svg)](https://github.com/open-mmlab/mmdetection/issues) [![issue resolution](https://isitmaintained.com/badge/resolution/open-mmlab/mmdetection.svg)](https://github.com/open-mmlab/mmdetection/issues) -[📘Documentation](https://mmdetection.readthedocs.io/en/3.x/) | -[🛠️Installation](https://mmdetection.readthedocs.io/en/3.x/get_started.html) | -[👀Model Zoo](https://mmdetection.readthedocs.io/en/3.x/model_zoo.html) | -[🆕Update News](https://mmdetection.readthedocs.io/en/3.x/notes/changelog.html) | +[📘Documentation](https://mmdetection.readthedocs.io/en/latest/) | +[🛠️Installation](https://mmdetection.readthedocs.io/en/latest/get_started.html) | +[👀Model Zoo](https://mmdetection.readthedocs.io/en/latest/model_zoo.html) | +[🆕Update News](https://mmdetection.readthedocs.io/en/latest/notes/changelog.html) | [🚀Ongoing Projects](https://github.com/open-mmlab/mmdetection/projects) | [🤔Reporting Issues](https://github.com/open-mmlab/mmdetection/issues/new/choose) @@ -43,9 +43,9 @@ English | [简体中文](README_zh-CN.md)
## Introduction @@ -60,7 +66,7 @@ English | [简体中文](README_zh-CN.md) MMDetection is an open source object detection toolbox based on PyTorch. It is a part of the [OpenMMLab](https://openmmlab.com/) project. -The master branch works with **PyTorch 1.6+**. +The main branch works with **PyTorch 1.6+**. @@ -108,43 +114,40 @@ We are excited to announce our latest work on real-time object recognition tasks -**v3.0.0rc6** was released in 24/2/2023: +**v3.0.0** was released in 6/4/2023: -- Support [Boxinst](configs/boxinst), [Objects365 Dataset](configs/objects365), and [Separated and Occluded COCO metric](docs/en/user_guides/useful_tools.md#coco-separated--occluded-mask-metric) -- Support [ConvNeXt-V2](projects/ConvNeXt-V2), [DiffusionDet](projects/DiffusionDet), and inference of [EfficientDet](projects/EfficientDet) and [Detic](projects/Detic) in `Projects` -- Refactor [DETR](configs/detr) series and support [Conditional-DETR](configs/conditional_detr), [DAB-DETR](configs/dab_detr), and [DINO](configs/dino) -- Support `DetInferencer` for inference, Test Time Augmentation, and automatically importing modules from registry -- Support RTMDet-Ins ONNXRuntime and TensorRT [deployment](configs/rtmdet/README.md#deployment-tutorial) -- Support [calculating FLOPs of detectors](docs/en/user_guides/useful_tools.md#Model-Complexity) +- Release MMDetection 3.0.0 official version +- Support Semi-automatic annotation Base [Label-Studio](projects/LabelStudio) (#10039) +- Support [EfficientDet](projects/EfficientDet) in projects (#9810) ## Installation -Please refer to [Installation](https://mmdetection.readthedocs.io/en/3.x/get_started.html) for installation instructions. +Please refer to [Installation](https://mmdetection.readthedocs.io/en/latest/get_started.html) for installation instructions. ## Getting Started -Please see [Overview](https://mmdetection.readthedocs.io/en/3.x/get_started.html) for the general introduction of MMDetection. +Please see [Overview](https://mmdetection.readthedocs.io/en/latest/get_started.html) for the general introduction of MMDetection. -For detailed user guides and advanced guides, please refer to our [documentation](https://mmdetection.readthedocs.io/en/3.x/): +For detailed user guides and advanced guides, please refer to our [documentation](https://mmdetection.readthedocs.io/en/latest/): - User Guides2.x Config | ++ +```python +# 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 + ... +] +``` + + | +
2.x Config | ++ +```python +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 Config | ++ +```python +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 Config | ++ +```python +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 + +``` + + | +
2.x Config | ++ +```python +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 Config | ++ +```python +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') +] +``` + + | +
2.x Config | ++ +```python +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 Config | ++ +```python +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')) +] +``` + + | +
Name | +2.x Config | +3.x Config | +
---|---|---|
Resize | ++ +```python +dict(type='Resize', + img_scale=(1333, 800), + keep_ratio=True) +``` + + | + ++ +```python +dict(type='Resize', + scale=(1333, 800), + keep_ratio=True) +``` + + | +
RandomResize | ++ +```python +dict( + type='Resize', + img_scale=[ + (1333, 640), (1333, 800)], + multiscale_mode='range', + keep_ratio=True) +``` + + | ++ +```python +dict( + type='RandomResize', + scale=[ + (1333, 640), (1333, 800)], + keep_ratio=True) +``` + + | +
RandomChoiceResize | ++ +```python +dict( + type='Resize', + img_scale=[ + (1333, 640), (1333, 672), + (1333, 704), (1333, 736), + (1333, 768), (1333, 800)], + multiscale_mode='value', + keep_ratio=True) +``` + + | ++ +```python +dict( + type='RandomChoiceResize', + scales=[ + (1333, 640), (1333, 672), + (1333, 704), (1333, 736), + (1333, 768), (1333, 800)], + keep_ratio=True) +``` + + | +
RandomFlip | ++ +```python +dict(type='RandomFlip', flip_ratio=0.5) +``` + + | ++ +```python +dict(type='RandomFlip', prob=0.5) +``` + + | +
Metric Name | +2.x Config | +3.x Config | +
---|---|---|
COCO | ++ +```python +data = dict( + val=dict( + type='CocoDataset', + ann_file=data_root + 'annotations/instances_val2017.json')) +evaluation = dict(metric=['bbox', 'segm']) +``` + + | + ++ +```python +val_evaluator = dict( + type='CocoMetric', + ann_file=data_root + 'annotations/instances_val2017.json', + metric=['bbox', 'segm'], + format_only=False) +``` + + | +
Pascal VOC | ++ +```python +data = dict( + val=dict( + type=dataset_type, + ann_file=data_root + 'VOC2007/ImageSets/Main/test.txt')) +evaluation = dict(metric='mAP') +``` + + | ++ +```python +val_evaluator = dict( + type='VOCMetric', + metric='mAP', + eval_mode='11points') +``` + + | +
OpenImages | ++ +```python +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') +``` + + | ++ +```python +val_evaluator = dict( + type='OpenImagesMetric', + iou_thrs=0.5, + ioa_thrs=0.5, + use_group_of=True, + get_supercategory=True) +``` + + | +
CityScapes | ++ +```python +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']) +``` + + | ++ +```python +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 Config | ++ +```python +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 Config | ++ +```python +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 +``` + + | +
2.x Config | ++ +```python +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 Config | ++ +```python +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 + ) +``` + + | +
2.x Config | ++ +```python +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 Config | ++ +```python +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 +] + +``` + + | +
Function | +2.x Config | +3.x Config | +
---|---|---|
Set Save Interval | ++ +```python +checkpoint_config = dict( + interval=1) +``` + + | + ++ +```python +default_hooks = dict( + checkpoint=dict( + type='CheckpointHook', + interval=1)) +``` + + | +
Save Best Model | ++ +```python +evaluation = dict( + save_best='auto') +``` + + | ++ +```python +default_hooks = dict( + checkpoint=dict( + type='CheckpointHook', + save_best='auto')) +``` + + | +
Keep Latest Model | ++ +```python +checkpoint_config = dict( + max_keep_ckpts=3) +``` + + | ++ +```python +default_hooks = dict( + checkpoint=dict( + type='CheckpointHook', + max_keep_ckpts=3)) +``` + + | +
Function | +2.x Config | +3.x Config | +
---|---|---|
Set Log Printing Interval | ++ +```python +log_config = dict(interval=50) +``` + + | + ++ +```python +default_hooks = dict( + logger=dict(type='LoggerHook', interval=50)) +# Optional: set moving average window size +log_processor = dict( + type='LogProcessor', window_size=50) +``` + + | +
Use TensorBoard or WandB to visualize logs | ++ +```python +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) + ]) +``` + + | ++ +```python +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') +``` + + | +
2.x Config | +3.x Config | +
---|---|
+ +```python +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 + + +``` + + | ++ +```python +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 +``` + + | +
原配置 | ++ +```python +# 图像归一化参数 +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 到 32 的倍数 + ... +] +``` + + | +
新配置 | ++ +```python +model = dict( + data_preprocessor=dict( + type='DetDataPreprocessor', + # 图像归一化参数 + mean=[123.675, 116.28, 103.53], + std=[58.395, 57.12, 57.375], + bgr_to_rgb=True, + # 图像 padding 参数 + pad_mask=True, # 在实例分割中,需要将 mask 也进行 padding + pad_size_divisor=32) # 图像 padding 到 32 的倍数 +) +``` + + | +
原配置 | ++ +```python +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)) +``` + + | +
新配置 | ++ +```python +train_dataloader = dict( + batch_size=2, + num_workers=2, + persistent_workers=True, # 避免每次迭代后 dataloader 重新创建子进程 + sampler=dict(type='DefaultSampler', shuffle=True), # 默认的 sampler,同时支持分布式训练和非分布式训练 + batch_sampler=dict(type='AspectRatioBatchSampler'), # 默认的 batch_sampler,用于保证 batch 中的图片具有相似的长宽比,从而可以更好地利用显存 + 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)) +# 在 3.x 版本中可以独立配置验证和测试的 dataloader +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 # 测试 dataloader 的配置与验证 dataloader 的配置相同,这里省略 +``` + + | +
原配置 | ++ +```python +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']), +] +``` + + | +
新配置 | ++ +```python +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') +] +``` + + | +
原配置 | ++ +```python +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']), + ]) +] +``` + + | +
新配置 | ++ +```python +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')) +] +``` + + | +
名称 | +原配置 | +新配置 | +
---|---|---|
Resize | ++ +```python +dict(type='Resize', + img_scale=(1333, 800), + keep_ratio=True) +``` + + | + ++ +```python +dict(type='Resize', + scale=(1333, 800), + keep_ratio=True) +``` + + | +
RandomResize | ++ +```python +dict( + type='Resize', + img_scale=[ + (1333, 640), (1333, 800)], + multiscale_mode='range', + keep_ratio=True) +``` + + | ++ +```python +dict( + type='RandomResize', + scale=[ + (1333, 640), (1333, 800)], + keep_ratio=True) +``` + + | +
RandomChoiceResize | ++ +```python +dict( + type='Resize', + img_scale=[ + (1333, 640), (1333, 672), + (1333, 704), (1333, 736), + (1333, 768), (1333, 800)], + multiscale_mode='value', + keep_ratio=True) +``` + + | ++ +```python +dict( + type='RandomChoiceResize', + scales=[ + (1333, 640), (1333, 672), + (1333, 704), (1333, 736), + (1333, 768), (1333, 800)], + keep_ratio=True) +``` + + | +
RandomFlip | ++ +```python +dict(type='RandomFlip', + flip_ratio=0.5) +``` + + | ++ +```python +dict(type='RandomFlip', + prob=0.5) +``` + + | +
评测指标名称 | +原配置 | +新配置 | +
---|---|---|
COCO | ++ +```python +data = dict( + val=dict( + type='CocoDataset', + ann_file=data_root + 'annotations/instances_val2017.json')) +evaluation = dict(metric=['bbox', 'segm']) +``` + + | + ++ +```python +val_evaluator = dict( + type='CocoMetric', + ann_file=data_root + 'annotations/instances_val2017.json', + metric=['bbox', 'segm'], + format_only=False) +``` + + | +
Pascal VOC | ++ +```python +data = dict( + val=dict( + type=dataset_type, + ann_file=data_root + 'VOC2007/ImageSets/Main/test.txt')) +evaluation = dict(metric='mAP') +``` + + | ++ +```python +val_evaluator = dict( + type='VOCMetric', + metric='mAP', + eval_mode='11points') +``` + + | +
OpenImages | ++ +```python +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') +``` + + | ++ +```python +val_evaluator = dict( + type='OpenImagesMetric', + iou_thrs=0.5, + ioa_thrs=0.5, + use_group_of=True, + get_supercategory=True) +``` + + | +
CityScapes | ++ +```python +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']) +``` + + | ++ +```python +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') +] +``` + + | +
原配置 | ++ +```python +runner = dict( + type='EpochBasedRunner', # 训练循环的类型 + max_epochs=12) # 最大训练轮次 +evaluation = dict(interval=2) # 验证间隔。每 2 个 epoch 验证一次 +``` + + | +
新配置 | ++ +```python +train_cfg = dict( + type='EpochBasedTrainLoop', # 训练循环的类型,请参考 https://github.com/open-mmlab/mmengine/blob/main/mmengine/runner/loops.py + max_epochs=12, # 最大训练轮次 + val_interval=2) # 验证间隔。每 2 个 epoch 验证一次 +val_cfg = dict(type='ValLoop') # 验证循环的类型 +test_cfg = dict(type='TestLoop') # 测试循环的类型 +``` + + | +
原配置 | ++ +```python +optimizer = dict( + type='SGD', # 随机梯度下降优化器 + lr=0.02, # 基础学习率 + momentum=0.9, # 带动量的随机梯度下降 + weight_decay=0.0001) # 权重衰减 +optimizer_config = dict(grad_clip=None) # 梯度裁剪的配置,设置为 None 关闭梯度裁剪 +``` + + | +
新配置 | ++ +```python +optim_wrapper = dict( # 优化器封装的配置 + type='OptimWrapper', # 优化器封装的类型。可以切换至 AmpOptimWrapper 来启用混合精度训练 + optimizer=dict( # 优化器配置。支持 PyTorch 的各种优化器。请参考 https://pytorch.org/docs/stable/optim.html#algorithms + type='SGD', # 随机梯度下降优化器 + lr=0.02, # 基础学习率 + momentum=0.9, # 带动量的随机梯度下降 + weight_decay=0.0001), # 权重衰减 + clip_grad=None, # 梯度裁剪的配置,设置为 None 关闭梯度裁剪。使用方法请见 https://mmengine.readthedocs.io/en/latest/tutorials/optimizer.html + ) +``` + + | +
原配置 | ++ +```python +lr_config = dict( + policy='step', # 在训练过程中使用 multi step 学习率策略 + warmup='linear', # 使用线性学习率预热 + warmup_iters=500, # 到第 500 个 iteration 结束预热 + warmup_ratio=0.001, # 学习率预热的系数 + step=[8, 11], # 在哪几个 epoch 进行学习率衰减 + gamma=0.1) # 学习率衰减系数 +``` + + | +
新配置 | ++ +```python +param_scheduler = [ + dict( + type='LinearLR', # 使用线性学习率预热 + start_factor=0.001, # 学习率预热的系数 + by_epoch=False, # 按 iteration 更新预热学习率 + begin=0, # 从第一个 iteration 开始 + end=500), # 到第 500 个 iteration 结束 + dict( + type='MultiStepLR', # 在训练过程中使用 multi step 学习率策略 + by_epoch=True, # 按 epoch 更新学习率 + begin=0, # 从第一个 epoch 开始 + end=12, # 到第 12 个 epoch 结束 + milestones=[8, 11], # 在哪几个 epoch 进行学习率衰减 + gamma=0.1) # 学习率衰减系数 +] +``` + + | +
功能 | +原配置 | +新配置 | +
---|---|---|
设置保存间隔 | ++ +```python +checkpoint_config = dict( + interval=1) +``` + + | + ++ +```python +default_hooks = dict( + checkpoint=dict( + type='CheckpointHook', + interval=1)) +``` + + | +
保存最佳模型 | ++ +```python +evaluation = dict( + save_best='auto') +``` + + | ++ +```python +default_hooks = dict( + checkpoint=dict( + type='CheckpointHook', + save_best='auto')) +``` + + | +
只保留最新的几个模型 | ++ +```python +checkpoint_config = dict( + max_keep_ckpts=3) +``` + + | ++ +```python +default_hooks = dict( + checkpoint=dict( + type='CheckpointHook', + max_keep_ckpts=3)) +``` + + | +
功能 | +原配置 | +新配置 | +
---|---|---|
设置日志打印间隔 | ++ +```python +log_config = dict( + interval=50) +``` + + | + ++ +```python +default_hooks = dict( + logger=dict( + type='LoggerHook', + interval=50)) +# 可选: 配置日志打印数值的平滑窗口大小 +log_processor = dict( + type='LogProcessor', + window_size=50) +``` + + | +
使用 TensorBoard 或 WandB 可视化日志 | ++ +```python +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) + ]) +``` + + | ++ +```python +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') +``` + + | +
原配置 | +新配置 | +
---|---|
+ +```python +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 + + +``` + + | ++ +```python +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 +``` + + | +