Skip to content

Open In Colab

Quickstart

MMDetection

Introduction

This tutorial walk you through the different steps of training one of the MMDetection models supported in IceVision. We use either the Fridge Objects dataset or the PennFudan dataset.

The IceVision Framework is an agnostic framework. As an illustration, we will train our model using both the fastai library, and pytorch-lightning libraries.

For more information about how the fridge dataset as well as its corresponding parser check out the IceData repository.

Installing IceVision and IceData

# !pip install icevision[all] icedata -q
!pip install git+git://github.com/airctic/icevision.git#egg=icevision[all] --upgrade -q
# !pip install icedata -q
!pip install git+git://github.com/airctic/icedata.git --upgrade -q

MMDetection Installation

# Install mmdetection
!rm -rf mmdetection
!git clone https://github.com/open-mmlab/mmdetection.git

!pip install -e mmdetection -q
!ls
mmdetection  sample_data

Check Pytorch installation

import torch, torchvision
print(torch.__version__, torch.cuda.is_available())
torch_version, cuda_version = (torch.__version__).split("+")
torch_version, cuda_version
1.7.0+cu101 True

('1.7.0', 'cu101')

MMCV Full-Version Installation

mmcv_full_version = "1.2.5"
mmcv_full_url = f"https://download.openmmlab.com/mmcv/dist/{cuda_version}/torch{torch_version}/index.html" #e.g https://download.openmmlab.com/mmcv/dist/cu101/torch1.7.0/index.html 
mmcv_full_url

!pip install mmcv-full=={mmcv_full_version} -f {mmcv_full_url} -U -q
# Restart Runtime
import os

def restart_runtime():
  os.kill(os.getpid(), 9)

restart_runtime()
import mmcv
print("MMCV: ", mmcv.__version__)
# Check MMDetection installation
import mmdet
print("MMDetection: ", mmdet.__version__)

# Check mmcv installation
from mmcv.ops import get_compiling_cuda_version, get_compiler_version
print(get_compiling_cuda_version())
print(get_compiler_version())

'https://download.openmmlab.com/mmcv/dist/cu101/torch1.7.0/index.html'

MMCV:  1.2.5

MMDetection:  2.9.0
10.1
GCC 7.3

If mmdet is not recognized, Restart Runtime from the "Runtime Menu"

Imports

from icevision.all import *

MMDetection Models Information

models_info contain all the necessary configuration information to build an MMDetection model. That includes:

  • 'model_name'
  • 'model_type'
  • 'cfg_filepath'
  • 'weights_url'
all_models_info = [
          {
            'model_name': "cornernet",
            'model_type': models.mmdet.cornernet,
            'cfg_filepath': "mmdetection/configs/cornernet/cornernet_hourglass104_mstest_32x3_210e_coco.py",
            'weights_url': "http://download.openmmlab.com/mmdetection/v2.0/cornernet/cornernet_hourglass104_mstest_32x3_210e_coco/cornernet_hourglass104_mstest_32x3_210e_coco_20200819_203110-1efaea91.pth",
          },
          {
            'model_name': "centripetalnet",
            'model_type': models.mmdet.centripetalnet,
            'cfg_filepath': "mmdetection/configs/centripetalnet/centripetalnet_hourglass104_mstest_16x6_210e_coco.py",
            'weights_url': "http://download.openmmlab.com/mmdetection/v2.0/centripetalnet/centripetalnet_hourglass104_mstest_16x6_210e_coco/centripetalnet_hourglass104_mstest_16x6_210e_coco_20200915_204804-3ccc61e5.pth",
          },
          {
            'model_name': "retinanet",
            'model_type': models.mmdet.retinanet,
            'cfg_filepath': "mmdetection/configs/_base_/models/retinanet_r50_fpn.py",
            'weights_url': "http://download.openmmlab.com/mmdetection/v2.0/retinanet/retinanet_r50_fpn_1x_coco/retinanet_r50_fpn_1x_coco_20200130-c2398f9e.pth",
          },
          {
            'model_name': "fcos",
            'model_type': models.mmdet.fcos,
            'cfg_filepath': "mmdetection/configs/fcos/fcos_x101_64x4d_fpn_gn-head_mstrain_640-800_2x_coco.py",
            'weights_url': "http://download.openmmlab.com/mmdetection/v2.0/fcos/fcos_x101_64x4d_fpn_gn-head_mstrain_640-800_4x2_2x_coco/fcos_x101_64x4d_fpn_gn-head_mstrain_640-800_4x2_2x_coco_20200229-11f8c079.pth",
          },
          {
            'model_name': "faster_rcnn",
            'model_type': models.mmdet.faster_rcnn,
            'cfg_filepath': "mmdetection/configs/faster_rcnn/faster_rcnn_r50_fpn_1x_coco.py",
            'weights_url': "http://download.openmmlab.com/mmdetection/v2.0/faster_rcnn/faster_rcnn_r50_fpn_1x_coco/faster_rcnn_r50_fpn_1x_coco_20200130-047c8118.pth",
          },
          {
            'model_name': "mask_rcnn",
            'model_type': models.mmdet.mask_rcnn,
            'cfg_filepath': "mmdetection/configs/mask_rcnn/mask_rcnn_r50_fpn_1x_coco.py",
            'weights_url': "http://download.openmmlab.com/mmdetection/v2.0/mask_rcnn/mask_rcnn_r50_fpn_1x_coco/mask_rcnn_r50_fpn_1x_coco_20200205-d4b0c5d6.pth",
          },
        ]

Select a Model to train

You can select one of the following models: "retinanet", "fcos", "faster_rcnn", "mask_rcnn"

model_name = "retinanet"  # "cornernet", "centripetalnet", "retinanet", "fcos", "faster_rcnn", "mask_rcnn"
model_info = next(m_info for m_info in all_models_info if m_info["model_name"] == model_name)
model_info
model_type = model_info["model_type"]
cfg_filepath = model_info["cfg_filepath"]
weights_url = model_info["weights_url"]
{'cfg_filepath': 'mmdetection/configs/_base_/models/retinanet_r50_fpn.py',
 'model_name': 'retinanet',
 'model_type': <module 'icevision.models.mmdet.models.retinanet' from '/usr/local/lib/python3.6/dist-packages/icevision/models/mmdet/models/retinanet/__init__.py'>,
 'weights_url': 'http://download.openmmlab.com/mmdetection/v2.0/retinanet/retinanet_r50_fpn_1x_coco/retinanet_r50_fpn_1x_coco_20200130-c2398f9e.pth'}

Datasets :

  • For Object Detection the Fridge Object Dataset will be used
  • For Mask Detection the PennFudan Dataset will be used
if "mask" in model_name:
  data_dir = icedata.pennfudan.load_data()
  parser = icedata.pennfudan.parser(data_dir)
else:
  data_dir = icedata.fridge.load_data()
  parser = icedata.fridge.parser(data_dir)
train_records, valid_records = parser.parse()

# train_records[0]
presize, size = 512, 384

train_tfms = tfms.A.Adapter(
    [*tfms.A.aug_tfms(size=size, presize=presize), tfms.A.Normalize()]
)
valid_tfms = tfms.A.Adapter([*tfms.A.resize_and_pad(size=size), tfms.A.Normalize()])
train_ds = Dataset(train_records, train_tfms)
valid_ds = Dataset(valid_records, valid_tfms)
train_dl = model_type.train_dl(train_ds, batch_size=8, num_workers=4, shuffle=True)
valid_dl = model_type.valid_dl(valid_ds, batch_size=8, num_workers=4, shuffle=False)
parser.class_map

  0%|          | 0/128 [00:00<?, ?it/s]

INFO     - Autofixing records | icevision.parsers.parser:parse:132

<ClassMap: {'background': 0, 'carton': 1, 'milk_bottle': 2, 'can': 3, 'water_bottle': 4}>

Visualization

Showing some images

samples = [train_ds[0] for _ in range(3)]
show_samples(samples, ncols=3, class_map=parser.class_map)

png

Downloading Pretrained Weights

weights_url

checkpoints_dir = "checkpoints"
!mkdir {checkpoints_dir}
!wget -c -P checkpoints/ {weights_url}

'http://download.openmmlab.com/mmdetection/v2.0/retinanet/retinanet_r50_fpn_1x_coco/retinanet_r50_fpn_1x_coco_20200130-c2398f9e.pth'

--2021-02-19 17:46:07--  http://download.openmmlab.com/mmdetection/v2.0/retinanet/retinanet_r50_fpn_1x_coco/retinanet_r50_fpn_1x_coco_20200130-c2398f9e.pth
Resolving download.openmmlab.com (download.openmmlab.com)... 47.254.186.225
Connecting to download.openmmlab.com (download.openmmlab.com)|47.254.186.225|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 152149505 (145M) [application/octet-stream]
Saving to: ‘checkpoints/retinanet_r50_fpn_1x_coco_20200130-c2398f9e.pth’
retinanet_r50_fpn_1 100%[===================>] 145.10M  8.53MB/s    in 23s     
2021-02-19 17:46:31 (6.44 MB/s) - ‘checkpoints/retinanet_r50_fpn_1x_coco_20200130-c2398f9e.pth’ saved [152149505/152149505]
!ls {checkpoints_dir}
retinanet_r50_fpn_1x_coco_20200130-c2398f9e.pth

MMDetection Configuration File

Updating the Model Config File

Note: You don't need to change the default config. Here, we are only showing how to change any default value stored in the config file. As an example, we are showing how to update the loss_weight(s)

The original config files use the default loss_weight=1.

# Get the weights_path
weights_fname = Path(weights_url).name
weights_path = f"{checkpoints_dir}/{weights_fname}"
weights_path

cfg_filepath
from mmcv import Config

cfg = Config.fromfile(cfg_filepath)
# cfg.model.bbox_head

'checkpoints/retinanet_r50_fpn_1x_coco_20200130-c2398f9e.pth'

'mmdetection/configs/_base_/models/retinanet_r50_fpn.py'

Default loss_weigt(s) = 1

# cfg.model.bbox_head.loss_cls, cfg.model.bbox_head.loss_bbox

Updating Model Config attributes

Note: We can update any attributes defined in the python file where those attributes are populated

In this example, we are updating the loss_weigt(s) with the following values

# cfg.model.bbox_head.loss_cls.loss_weight = 0.8
# cfg.model.bbox_head.loss_bbox.loss_weight = 2
# cfg.model.bbox_head.loss_cls, cfg.model.bbox_head.loss_bbox

Creating a Model

weights_path
model = model_type.model(cfg, num_classes=len(parser.class_map), weights_path=weights_path)
'checkpoints/retinanet_r50_fpn_1x_coco_20200130-c2398f9e.pth'

Training

Training - Fastai

learn = model_type.fastai.learner(dls=[train_dl, valid_dl], model=model, splitter=fastai.trainable_params)
learn.lr_find()
SuggestedLRs(lr_min=5.754399462603033e-05, lr_steep=0.00010964782268274575)

png

learn.fine_tune(20, 3e-4)
epoch train_loss valid_loss time
0 1.192961 0.856517 00:06
epoch train_loss valid_loss time
0 0.692504 0.536435 00:05
1 0.568239 0.376043 00:05
2 0.492997 0.340800 00:05
3 0.432057 0.257431 00:05
4 0.383656 0.228422 00:05
5 0.351317 0.213184 00:05
6 0.333522 0.237355 00:05
7 0.310363 0.181096 00:05
8 0.294222 0.193166 00:05
9 0.273112 0.145784 00:05
10 0.252149 0.161463 00:05
11 0.236207 0.139669 00:05
12 0.219127 0.149458 00:05
13 0.207551 0.131850 00:05
14 0.198437 0.144513 00:05
15 0.189129 0.133218 00:05
16 0.177614 0.119760 00:05
17 0.166518 0.116883 00:05
18 0.158119 0.114125 00:05
19 0.151817 0.114225 00:05

Training - Pytorch-Lightning

class LitModel(model_type.lightning.ModelAdapter):
    def configure_optimizers(self):
        return Adam(self.parameters(), lr=1e-4)

lit_model = LitModel(model)
trainer = pl.Trainer(max_epochs=10, gpus=1, num_sanity_val_steps=0, check_val_every_n_epoch=1)
lr_finder = trainer.tuner.lr_find(lit_model, train_dl, valid_dl)
/usr/local/lib/python3.6/dist-packages/pytorch_lightning/utilities/distributed.py:50: UserWarning: You have set progress_bar_refresh_rate < 20 on Google Colab. This may crash. Consider using progress_bar_refresh_rate >= 20 in Trainer.
  warnings.warn(*args, **kwargs)
GPU available: True, used: True
TPU available: None, using: 0 TPU cores
LOCAL_RANK: 0 - CUDA_VISIBLE_DEVICES: [0]
fig = lr_finder.plot(suggest=True)
fig.show()
  | Name  | Type      | Params
------------------------------------
0 | model | RetinaNet | 36.4 M
------------------------------------
36.2 M    Trainable params
225 K     Non-trainable params
36.4 M    Total params

Finding best initial lr:   0%|          | 0/100 [00:00<?, ?it/s]

LR finder stopped early due to diverging loss.
Restored states from the checkpoint file at /content/lr_find_temp_model.ckpt

png

trainer.fit(lit_model, train_dl, valid_dl)

Show Results

model_type.show_results(model, valid_ds, detection_threshold=.5)

png

Inference

infer_dl = model_type.infer_dl(valid_ds, batch_size=1, shuffle=False)
samples, preds = model_type.predict_dl(model, infer_dl)
show_preds(
    samples=samples[:6],
    preds=preds[:6],
    class_map=parser.class_map,
    denormalize_fn=denormalize_imagenet,
    ncols=3,
)
  0%|          | 0/26 [00:00<?, ?it/s]

png

Happy Learning!

If you need any assistance, feel free to join our forum.