{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"_kg_hide-input":true,"_kg_hide-output":true},"cell_type":"code","source":"%%capture\n!pip install ../input/detectorsdependencies/packages/ordered_set-4.0.2-py2.py3-none-any.whl\n!pip install ../input/detectorsdependencies/packages/torch-1.4.0-cp37-cp37m-linux_x86_64.whl\n!pip install ../input/detectorsdependencies/packages/torchvision-0.5.0-cp37-cp37m-linux_x86_64.whl\n!pip install ../input/detectorsdependencies/packages/addict-2.2.1-py3-none-any.whl\n!pip install ../input/detectorsdependencies/packages/terminal-0.4.0-py3-none-any.whl\n!pip install ../input/detectorsdependencies/packages/terminaltables-3.1.0-py3-none-any.whl\n!pip install ../input/detectorsdependencies/packages/pytest_runner-5.2-py2.py3-none-any.whl\n!pip install ../input/detectorsdependencies/packages/cityscapesScripts-1.5.0-py3-none-any.whl\n!pip install ../input/detectorsdependencies/packages/imagecorruptions-1.1.0-py3-none-any.whl\n!pip install ../input/detectorsdependencies/packages/asynctest-0.13.0-py3-none-any.whl\n!pip install ../input/detectorsdependencies/packages/codecov-2.1.7-py2.py3-none-any.whl\n!pip install ../input/detectorsdependencies/packages/ubelt-0.9.1-py3-none-any.whl\n!pip install ../input/detectorsdependencies/packages/kwarray-0.5.8-py2.py3-none-any.whl\n!pip install ../input/detectorsdependencies/packages/xdoctest-0.12.0-py2.py3-none-any.whl\n!pip install ../input/detectorsdependencies/packages/mmcv-0.6.0-cp37-cp37m-linux_x86_64.whl\n\n# Setup DetectoRS and pycocotools\n!cp -r ../input/detors ./mmdetection\n\n%cd mmdetection\n!cp -r ../../input/mmdetection20-5-13/cocoapi/cocoapi .\n%cd cocoapi/PythonAPI\n!make\n!make install\n!python setup.py install\n%cd ../..\n!pip install -v -e .\n%cd ..\n\nimport sys\nsys.path.append('mmdetection') # To find local version of DetectoRS\n\n# add to sys python path for pycocotools\nsys.path.append('/opt/conda/lib/python3.7/site-packages/pycocotools-2.0-py3.7-linux-x86_64.egg') # To find local version","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import gc\n\nimport mmcv\n\nfrom mmdet import __version__\nfrom mmdet.apis import init_detector, inference_detector, show_result_pyplot\nfrom mmcv import Config, DictAction\nfrom mmdet.models import build_detector\nfrom mmcv.runner import load_checkpoint, init_dist\nfrom mmcv.parallel import MMDataParallel\nfrom mmdet.apis import single_gpu_test\nfrom mmdet.datasets import build_dataloader, build_dataset\nfrom mmdet.apis import set_random_seed, train_detector\nfrom mmdet.models import build_detector\nfrom mmdet.utils import collect_env, get_root_logger\n\n\nimport argparse\nimport copy\nimport os\nimport os.path as osp\nimport time\n\nimport torch\nimport shutil\nimport pandas as pd\nimport os\nimport json\n\nfrom PIL import Image\nimport matplotlib.pyplot as plt\nimport torch\n\nimport numpy as np\nimport random\n\nimport albumentations as A\n\nSEED = 28\ndef seed_everything(seed):\n    random.seed(seed)\n    os.environ['PYTHONHASHSEED'] = str(seed)\n    np.random.seed(seed)\n    torch.manual_seed(seed)\n    torch.cuda.manual_seed(seed)\n    torch.backends.cudnn.deterministic = True\n    torch.backends.cudnn.benchmark = True\n\nseed_everything(SEED)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Copy the pre-trained ResNet50 as it's used as backbone of DetectoRS\n!mkdir -p /root/.cache/torch/checkpoints/\n!cp ../input/resnet50/resnet50-19c8e357.pth /root/.cache/torch/checkpoints/resnet50-19c8e357.pth","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"conv_cfg = dict(type='ConvAWS')\n\n# model settings\nmodel = dict(\n    type='RecursiveFeaturePyramid',  # Name of the detector, In case of DetectoRS, it is RFP\n    rfp_steps=2,\n    rfp_sharing=False,\n    stage_with_rfp=(False, True, True, True),\n    num_stages=3,\n    pretrained='torchvision://resnet50',  # Pre-trained ImageNet ResNet50 as a backbone of DetectoRS\n    interleaved=True,\n    mask_info_flow=True,\n    backbone=dict(  # Configuration of the backbone model\n        type='ResNet',  # The type of the backbone, refer to https://github.com/open-mmlab/mmdetection/blob/master/mmdet/models/backbones/resnet.py#L288 for more details.\n        depth=50,  # The depth of backbone, usually it is 50 or 101 for ResNet and ResNext backbones.\n        num_stages=4,  # Number of stages of the backbone.\n        out_indices=(0, 1, 2, 3),  # The index of output feature maps produced in each stages\n        frozen_stages=1,  # The weights in the first 1 stage are fronzen\n        conv_cfg=conv_cfg,  \n        sac=dict(type='SAC', use_deform=True),  \n        stage_with_sac=(False, True, True, True),\n        norm_cfg=dict(type='BN', requires_grad=True),  # The config of normalization layers.\n        style='pytorch'),  # The style of backbone, 'pytorch' means that stride 2 layers are in 3x3 conv, 'caffe' means stride 2 layers are in 1x1 convs.\n    neck=dict(\n        type='FPN',  # The neck of detector is FPN.\n        in_channels=[256, 512, 1024, 2048],  # The input channels, this is consistent with the output channels of backbone\n        out_channels=256, # The output channels of each level of the pyramid feature map\n        num_outs=5),  # The number of output scales\n    rpn_head=dict(\n        type='RPNHead',  \n        in_channels=256,\n        feat_channels=256,\n        anchor_scales=[8],\n        anchor_ratios=[0.5, 1.0, 2.0],\n        anchor_strides=[4, 8, 16, 32, 64],\n        target_means=[.0, .0, .0, .0],\n        target_stds=[1.0, 1.0, 1.0, 1.0],\n        loss_cls=dict(\n            type='CrossEntropyLoss', use_sigmoid=True, loss_weight=1.0),\n        loss_bbox=dict(type='SmoothL1Loss', beta=1.0 / 9.0, loss_weight=1.0)),\n    bbox_roi_extractor=dict(\n        type='SingleRoIExtractor',\n        roi_layer=dict(type='RoIAlign', out_size=7, sample_num=2),\n        out_channels=256,\n        featmap_strides=[4, 8, 16, 32]),\n    bbox_head=[\n        dict(\n            type='SharedFCBBoxHead',\n            num_fcs=2,\n            in_channels=256,\n            fc_out_channels=1024,\n            roi_feat_size=7,\n            num_classes=2,\n            target_means=[0., 0., 0., 0.],\n            target_stds=[0.1, 0.1, 0.2, 0.2],\n            reg_class_agnostic=True,\n            loss_cls=dict(\n                type='CrossEntropyLoss', use_sigmoid=False, loss_weight=1.0),\n            loss_bbox=dict(type='SmoothL1Loss', beta=1.0, loss_weight=1.0)),\n        dict(\n            type='SharedFCBBoxHead',\n            num_fcs=2,\n            in_channels=256,\n            fc_out_channels=1024,\n            roi_feat_size=7,\n            num_classes=2,\n            target_means=[0., 0., 0., 0.],\n            target_stds=[0.05, 0.05, 0.1, 0.1],\n            reg_class_agnostic=True,\n            loss_cls=dict(\n                type='CrossEntropyLoss', use_sigmoid=False, loss_weight=1.0),\n            loss_bbox=dict(type='SmoothL1Loss', beta=1.0, loss_weight=1.0)),\n        dict(\n            type='SharedFCBBoxHead',\n            num_fcs=2,\n            in_channels=256,\n            fc_out_channels=1024,\n            roi_feat_size=7,\n            num_classes=2,\n            target_means=[0., 0., 0., 0.],\n            target_stds=[0.033, 0.033, 0.067, 0.067],\n            reg_class_agnostic=True,\n            loss_cls=dict(\n                type='CrossEntropyLoss', use_sigmoid=False, loss_weight=1.0),\n            loss_bbox=dict(type='SmoothL1Loss', beta=1.0, loss_weight=1.0))\n    ],\n    mask_roi_extractor=dict(\n        type='SingleRoIExtractor',\n        roi_layer=dict(type='RoIAlign', out_size=14, sample_num=2),\n        out_channels=256,\n        featmap_strides=[4, 8, 16, 32]),\n    mask_head=[\n        dict(\n            type='HTCMaskHead',\n            with_conv_res=False,\n            num_convs=4,\n            in_channels=256,\n            conv_out_channels=256,\n            num_classes=2,\n            loss_mask=dict(\n                type='CrossEntropyLoss', use_mask=True, loss_weight=1.0)),\n        dict(\n            type='HTCMaskHead',\n            num_convs=4,\n            in_channels=256,\n            conv_out_channels=256,\n            num_classes=2,\n            loss_mask=dict(\n                type='CrossEntropyLoss', use_mask=True, loss_weight=1.0)),\n        dict(\n            type='HTCMaskHead',\n            num_convs=4,\n            in_channels=256,\n            conv_out_channels=256,\n            num_classes=2,\n            loss_mask=dict(\n                type='CrossEntropyLoss', use_mask=True, loss_weight=1.0))\n    ])\n\n# model training and testing settings\ntrain_cfg = dict(\n    rpn=dict(\n        assigner=dict(\n            type='MaxIoUAssigner',\n            pos_iou_thr=0.7,\n            neg_iou_thr=0.3,\n            min_pos_iou=0.3,\n            ignore_iof_thr=-1),\n        sampler=dict(\n            type='RandomSampler',\n            num=256,\n            pos_fraction=0.5,\n            neg_pos_ub=-1,\n            add_gt_as_proposals=False),\n        allowed_border=0,\n        pos_weight=-1,\n        debug=False),\n    rpn_proposal=dict(\n        nms_across_levels=False,\n        nms_pre=2000,\n        nms_post=2000,\n        max_num=2000,\n        nms_thr=0.7,\n        min_bbox_size=0),\n    rcnn=[\n        dict(\n            assigner=dict(\n                type='MaxIoUAssigner',\n                pos_iou_thr=0.5,\n                neg_iou_thr=0.5,\n                min_pos_iou=0.5,\n                ignore_iof_thr=-1),\n            sampler=dict(\n                type='RandomSampler',\n                num=512,\n                pos_fraction=0.25,\n                neg_pos_ub=-1,\n                add_gt_as_proposals=True),\n            mask_size=28,\n            pos_weight=-1,\n            debug=False),\n        dict(\n            assigner=dict(\n                type='MaxIoUAssigner',\n                pos_iou_thr=0.6,\n                neg_iou_thr=0.6,\n                min_pos_iou=0.6,\n                ignore_iof_thr=-1),\n            sampler=dict(\n                type='RandomSampler',\n                num=512,\n                pos_fraction=0.25,\n                neg_pos_ub=-1,\n                add_gt_as_proposals=True),\n            mask_size=28,\n            pos_weight=-1,\n            debug=False),\n        dict(\n            assigner=dict(\n                type='MaxIoUAssigner',\n                pos_iou_thr=0.7,\n                neg_iou_thr=0.7,\n                min_pos_iou=0.7,\n                ignore_iof_thr=-1),\n            sampler=dict(\n                type='RandomSampler',\n                num=512,\n                pos_fraction=0.25,\n                neg_pos_ub=-1,\n                add_gt_as_proposals=True),\n            mask_size=28,\n            pos_weight=-1,\n            debug=False)\n    ],\n    stage_loss_weights=[1, 0.5, 0.25])\n\n\ntest_cfg = dict(\n    rpn=dict(\n        nms_across_levels=False,\n        nms_pre=1000,\n        nms_post=1000,\n        max_num=1000,\n        nms_thr=0.7,\n        min_bbox_size=0),\n    rcnn=dict(\n        score_thr=0.001,\n        nms=dict(type='nms', iou_thr=0.5),\n        max_per_img=100,\n        mask_thr_binary=0.5))\n\n\n# dataset settings\ndataset_type = 'CocoDataset'  # Dataset type, this will be used to define the dataset\n# data_root = '../input/gwdannotations/coco/'  # Root path of data\ndata_root = '/kaggle/input/wheatcoco/coco/'  # Root path of data\nimg_norm_cfg = dict(  # Image normalization config to normalize the input images\n    mean=[123.675, 116.28, 103.53],   # Mean values used to pre-training the pre-trained backbone models\n    std=[58.395, 57.12, 57.375],    # Standard variance used to pre-training the pre-trained backbone models\n    to_rgb=True)  # The channel orders of image used to pre-training the pre-trained backbone models\n\ntrain_transforms = [\n    dict(type='RandomSizedCrop',\n        min_max_height=(800, 800),\n        height=1024,\n        width=1024,\n        p=0.5),\n    dict(type='OneOf',\n         transforms=[\n            dict( type='HueSaturationValue',\n                  hue_shift_limit=0.2,\n                  sat_shift_limit=0.2,\n                  val_shift_limit=0.2, p=0.9),\n            dict(type='RandomBrightnessContrast',\n                  brightness_limit=0.2,\n                  contrast_limit=0.2, p=0.9)\n         ], p=0.9),\n    dict(type='ToGray', p=0.01),\n    dict(type='HorizontalFlip', p=0.5),\n    dict(type='VerticalFlip', p=0.5),\n    dict(type='Resize', height=512, width=512, p=1.0),\n    dict(type='Cutout', num_holes=8, max_h_size=64, max_w_size=64, fill_value=0, p=0.5),\n]\n\nval_transforms = [\n    dict(type='Resize', height=512, width=512, p=1.0)\n]\n\ntrain_pipeline = [\n    dict(type='LoadImageFromFile'),\n    dict(\n        type='LoadAnnotations', with_bbox=True, with_mask=True),\n    dict(\n        type='Albu',\n        transforms=train_transforms,\n        bbox_params=dict(\n            type='BboxParams',\n            format='pascal_voc',\n            label_fields=['gt_labels'],\n            min_visibility=0.0,\n            filter_lost_elements=True),\n        keymap={\n            'img': 'image',\n            'gt_masks': 'masks',\n            'gt_bboxes': 'bboxes'\n        },\n        update_pad_shape=False,\n        skip_img_without_anno=True),\n    dict(type='RandomFlip', flip_ratio=0.5),\n    dict(type='Normalize', **img_norm_cfg),\n    dict(type='DefaultFormatBundle'),\n    dict(\n        type='Collect',\n        keys=['img', 'gt_bboxes', 'gt_labels', 'gt_masks']),\n]\ntest_pipeline = [\n    dict(type='LoadImageFromFile'),\n    dict(\n        type='MultiScaleFlipAug',\n        img_scale=(512, 512),\n        flip=False,\n        transforms=[\n            dict(type='Resize', keep_ratio=True),\n            dict(type='RandomFlip', flip_ratio=0.5),\n            dict(type='Normalize', **img_norm_cfg),\n            dict(type='Pad', size_divisor=32),\n            dict(type='ImageToTensor', keys=['img']),\n            dict(type='Collect', keys=['img']),\n        ])\n]\ndata = dict(\n    imgs_per_gpu=1,  # Batch size\n    workers_per_gpu=2,\n    train=dict(\n        type=dataset_type,\n        ann_file=data_root + 'annotations/instances_train2017.json',\n        img_prefix=data_root + 'images/train2017/',\n        pipeline=train_pipeline),\n    val=dict(\n        type=dataset_type,\n        ann_file=data_root + 'annotations/instances_val2017.json',\n        img_prefix=data_root + 'images/val2017/',\n        pipeline=test_pipeline),\n    test=dict(\n        type=dataset_type,\n        ann_file=data_root + 'annotations/instances_val2017.json',\n        img_prefix=data_root + 'images/val2017/',\n        pipeline=test_pipeline))\nevaluation = dict(metric=['bbox', 'segm'])\n\n# optimizer\noptimizer = dict(type='SGD', lr=0.02, momentum=0.9, weight_decay=0.0001)\noptimizer_config = dict(grad_clip=dict(max_norm=35, norm_type=2))\n\n# learning policy\nlr_config = dict(\n    policy='step',\n    warmup='linear',\n    warmup_iters=500,\n    warmup_ratio=1.0 / 3,\n    step=[36, 39])\n\ncheckpoint_config = dict(interval=1)\n# yapf:disable\n\nlog_config = dict(\n    interval=50,\n    hooks=[\n        dict(type='TextLoggerHook'),\n    ])\n# yapf:enable\n# runtime settings\n\ntotal_epochs = 1\ndist_params = dict(backend='nccl')\nlog_level = 'INFO'\nwork_dir = 'work_dirs'\nload_from = None\nresume_from = None\nworkflow = [('train', 1)]\n\n\nconfig_dict=dict(\n    model=model,\n    train_cfg=train_cfg,\n    test_cfg=test_cfg ,\n    dataset_type=dataset_type,\n    data_root=data_root,\n    img_norm_cfg=img_norm_cfg,\n    train_pipeline=train_pipeline,\n    test_pipeline=test_pipeline,\n    data=data ,\n    evaluation=evaluation ,\n    optimizer=optimizer,\n    optimizer_config=optimizer_config,\n    lr_config=lr_config,\n    total_epochs=total_epochs,\n    checkpoint_config=checkpoint_config,\n    log_config=log_config,\n    dist_params=dist_params,\n    log_level=log_level,\n    load_from =load_from ,\n    resume_from=resume_from,\n    workflow=workflow,\n    gpus = 1,  # Not sure why?. Solved: Because it's used to get GPU IDs\n    work_dir = work_dir\n)\n\nconfig = Config(config_dict) ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"cfg = config\n\n# This flag allows you to enable the inbuilt cudnn auto-tuner to find the best algorithm to use for your hardware.\ntorch.backends.cudnn.benchmark = True\ncfg.gpu_ids = range(1) if cfg.gpus is None else range(cfg.gpus)\n\n# apply the linear scaling rule (https://arxiv.org/abs/1706.02677)\ncfg.optimizer['lr'] = cfg.optimizer['lr'] * len(cfg.gpu_ids) / 8\n\ndistributed = False\n\n# create work_dir\nmmcv.mkdir_or_exist(osp.abspath(cfg.work_dir))\n\n# init the logger before other steps\ntimestamp = time.strftime('%Y%m%d_%H%M%S', time.localtime())\n\nlog_file = osp.join(cfg.work_dir, f'{timestamp}.log')\nlogger = get_root_logger(log_file=log_file, log_level=cfg.log_level)\n\n# init the meta dict to record some important information such as\n# environment info and seed, which will be logged\nmeta = dict()\n\n# log env info\nenv_info_dict = collect_env()\nenv_info = '\\n'.join([(f'{k}: {v}') for k, v in env_info_dict.items()])\ndash_line = '-' * 60 + '\\n'\nlogger.info('Environment info:\\n' + dash_line + env_info + '\\n' + dash_line)\nmeta['env_info'] = env_info\n\n# log some basic info\nlogger.info(f'Distributed training: {distributed}')\nlogger.info(f'Config:\\n{cfg.pretty_text}')\n\n# set random seeds\nlogger.info(f'Set random seed to {SEED}, '\n            f'deterministic: {True}')\nset_random_seed(SEED, deterministic=True)\n\ncfg.seed = SEED\nmeta['seed'] = SEED\n\n# Now build the training model\nmodel = build_detector(cfg.model, train_cfg=cfg.train_cfg, test_cfg=cfg.test_cfg)\n\n# Build the training dataset\ndatasets = [build_dataset(cfg.data.train)]\n\nif len(cfg.workflow) == 2:\n    val_dataset = copy.deepcopy(cfg.data.val)\n    val_dataset.pipeline = cfg.data.train.pipeline\n    datasets.append(build_dataset(val_dataset))\nif cfg.checkpoint_config is not None:\n    # save mmdet version, config file content and class names in\n    # checkpoints as meta data\n    cfg.checkpoint_config.meta = dict(\n        mmdet_version=__version__,\n        config=cfg.pretty_text,\n        CLASSES=datasets[0].CLASSES)\n\n# add an attribute for visualization convenience\nmodel.CLASSES = datasets[0].CLASSES\ntrain_detector(\n    model,\n    datasets,\n    cfg,\n    distributed=distributed,\n    validate=True,\n    timestamp=timestamp,\n    meta=meta)  ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Finally remove this to prevent the unnecessary output\n!rm -rf mmdetection/","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## References\n* https://mmdetection.readthedocs.io/en/latest/config.html#config-file-structure\n* https://www.kaggle.com/jqeric/detectors-new-sota-based-mmdetection/","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat":4,"nbformat_minor":4}