{"cells":[{"metadata":{},"cell_type":"markdown","source":"Hey everybody, I wanted to share one of the approaches I got some decent results with. It's based on the [Fully Convolutional One-Stage Object Detection (FCOS) Paper](https://arxiv.org/pdf/1904.01355.pdf). What's neat about this approach is that it doesn't rely on \"anchor boxes\" like Yolo, EffDet, and FasterRCNN. This means there are fewer hyper parameters to tune and as you might have noticed, lb scores can be very sensitive to hyperparameter choices. \n\nThis notebook contains all the code you should need for training and inference. I'm not doing any TTA or pseudo labeling here and I didn't spend much time tuning parameters. So there's likely a lot of room for improvement. \n\nI'm using the [mmdetection framework](https://github.com/open-mmlab/mmdetection) here which uses an approved liscense. It's a little different in that it's entirely config based. So, instead of digging through multiple class file to tweak settings and parameters, you just modify the config. It also lets you see everything you can potentially tweak. Mixing and matching different backbones and heads is really easy and it does a great job keeping track of past configs and training histories. \n\nThe one downside is that it requires a lot of slow boilerplate to get running on Kaggle:","execution_count":null},{"metadata":{"trusted":true,"_kg_hide-input":true,"_kg_hide-output":true},"cell_type":"code","source":"!pip install ../input/mmcvwhl/addict-2.2.1-py3-none-any.whl\n!pip install ../input/mmdetection20-5-13/mmcv-0.5.1-cp37-cp37m-linux_x86_64.whl\n!pip install ../input/mmdetection20-5-13/terminal-0.4.0-py3-none-any.whl\n!pip install ../input/mmdetection20-5-13/terminaltables-3.1.0-py3-none-any.whl","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_kg_hide-input":true,"_kg_hide-output":true},"cell_type":"code","source":"!cp -r ../input/mmdetection20-5-13/mmdetection/mmdetection .","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_kg_hide-input":true,"_kg_hide-output":true},"cell_type":"code","source":"cd mmdetection","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_kg_hide-input":true,"_kg_hide-output":true},"cell_type":"code","source":"!cp -r ../../input/mmdetection20-5-13/cocoapi/cocoapi .","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_kg_hide-input":true,"_kg_hide-output":true},"cell_type":"code","source":"cd cocoapi/PythonAPI","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_kg_hide-output":true,"_kg_hide-input":true},"cell_type":"code","source":"!make","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_kg_hide-output":true,"_kg_hide-input":true},"cell_type":"code","source":"!make install","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_kg_hide-output":true,"_kg_hide-input":true},"cell_type":"code","source":"!python setup.py install","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_kg_hide-input":true,"_kg_hide-output":true},"cell_type":"code","source":"import pycocotools","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_kg_hide-input":true,"_kg_hide-output":true},"cell_type":"code","source":"cd ../..","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_kg_hide-output":true,"_kg_hide-input":true},"cell_type":"code","source":"!pip install -v -e .","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_kg_hide-input":true,"_kg_hide-output":true},"cell_type":"code","source":"cd ../","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_kg_hide-input":true,"_kg_hide-output":true},"cell_type":"code","source":"import sys\nsys.path.append('mmdetection')","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Huge thanks to [@superkevingit](https://www.kaggle.com/superkevingit) and [@cdeotte](https://www.kaggle.com/c/severstal-steel-defect-detection/discussion/113195) who I borrowed the boilerplate from. \n\n1. Here's what the full mmdetection config looks like:","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"dataset_type = 'CocoDataset'\ndata_root = 'data/global_wheat'\nimg_norm_cfg = dict(\n    mean=[123.675, 116.28, 103.53], std=[58.395, 57.12, 57.375], to_rgb=True)\ntrain_pipeline = [\n    dict(type='LoadImageFromFile'),\n    dict(type='LoadAnnotations', with_bbox=True),\n    dict(\n        type='Resize',\n        img_scale=[(1333, 640), (1333, 800)],\n        multiscale_mode='value',\n        keep_ratio=True),\n    dict(type='RandomFlip', flip_ratio=0.5),\n    dict(\n        type='Normalize',\n        mean=[123.675, 116.28, 103.53],\n        std=[58.395, 57.12, 57.375],\n        to_rgb=True),\n    dict(type='Pad', size_divisor=32),\n    dict(type='DefaultFormatBundle'),\n    dict(type='Collect', keys=['img', 'gt_bboxes', 'gt_labels'])\n]\ntest_pipeline = [\n    dict(type='LoadImageFromFile'),\n    dict(\n        type='MultiScaleFlipAug',\n        img_scale=(1333, 800),\n        flip=False,\n        transforms=[\n            dict(type='Resize', keep_ratio=True),\n            dict(type='RandomFlip'),\n            dict(\n                type='Normalize',\n                mean=[123.675, 116.28, 103.53],\n                std=[58.395, 57.12, 57.375],\n                to_rgb=True),\n            dict(type='Pad', size_divisor=32),\n            dict(type='ImageToTensor', keys=['img']),\n            dict(type='Collect', keys=['img'])\n        ])\n]\ndata = dict(\n    samples_per_gpu=6,\n    workers_per_gpu=6,\n    train=dict(\n        type='CocoDataset',\n        ann_file='data/global_wheat/annotations/train_fold1.json',\n        img_prefix='data/global_wheat/train',\n        pipeline=[\n            dict(type='LoadImageFromFile'),\n            dict(type='LoadAnnotations', with_bbox=True),\n            dict(\n                type='Albu',\n                transforms=[\n                    dict(type='ToFloat', max_value=255.0),\n                    dict(\n                        type='RandomSizedCrop',\n                        min_max_height=(650, 1024),\n                        height=1024,\n                        width=1024,\n                        p=0.5),\n                    dict(\n                        type='HueSaturationValue',\n                        hue_shift_limit=0.68,\n                        sat_shift_limit=0.68,\n                        val_shift_limit=0.1,\n                        p=0.75),\n                    dict(\n                        type='RandomBrightnessContrast',\n                        brightness_limit=0.1,\n                        contrast_limit=0.1,\n                        p=0.33),\n                    dict(type='RandomRotate90', p=0.5),\n                    dict(\n                        type='Cutout',\n                        num_holes=20,\n                        max_h_size=32,\n                        max_w_size=32,\n                        fill_value=0.0,\n                        p=0.25),\n                    dict(type='FromFloat', max_value=255.0, dtype='uint8')\n                ],\n                bbox_params=dict(\n                    type='BboxParams',\n                    format='pascal_voc',\n                    label_fields=['gt_labels'],\n                    min_visibility=0.0,\n                    min_area=0,\n                    filter_lost_elements=True),\n                keymap=dict(img='image', gt_bboxes='bboxes'),\n                update_pad_shape=False,\n                skip_img_without_anno=False),\n            dict(\n                type='Resize',\n                img_scale=[(1333, 640), (1333, 800)],\n                multiscale_mode='value',\n                keep_ratio=True),\n            dict(type='RandomFlip', flip_ratio=0.5, direction='horizontal'),\n            dict(type='RandomFlip', flip_ratio=0.5, direction='vertical'),\n            dict(\n                type='Normalize',\n                mean=[123.675, 116.28, 103.53],\n                std=[58.395, 57.12, 57.375],\n                to_rgb=True),\n            dict(type='Pad', size_divisor=32),\n            dict(type='DefaultFormatBundle'),\n            dict(type='Collect', keys=['img', 'gt_bboxes', 'gt_labels'])\n        ],\n        classes=('wheat', )),\n    val=dict(\n        type='CocoDataset',\n        ann_file='data/global_wheat/annotations/val_fold1.json',\n        img_prefix='data/global_wheat/train',\n        pipeline=[\n            dict(type='LoadImageFromFile'),\n            dict(\n                type='MultiScaleFlipAug',\n                img_scale=(1333, 800),\n                flip=False,\n                transforms=[\n                    dict(type='Resize', keep_ratio=True),\n                    dict(type='RandomFlip'),\n                    dict(\n                        type='Normalize',\n                        mean=[123.675, 116.28, 103.53],\n                        std=[58.395, 57.12, 57.375],\n                        to_rgb=True),\n                    dict(type='Pad', size_divisor=32),\n                    dict(type='ImageToTensor', keys=['img']),\n                    dict(type='Collect', keys=['img'])\n                ])\n        ],\n        classes=('wheat', )),\n    test=dict(\n        type='CocoDataset',\n        ann_file='data/coco/annotations/instances_val2017.json',\n        img_prefix='data/coco/val2017/',\n        pipeline=[\n            dict(type='LoadImageFromFile'),\n            dict(\n                type='MultiScaleFlipAug',\n                img_scale=(1333, 800),\n                flip=False,\n                transforms=[\n                    dict(type='Resize', keep_ratio=True),\n                    dict(type='RandomFlip'),\n                    dict(\n                        type='Normalize',\n                        mean=[123.675, 116.28, 103.53],\n                        std=[58.395, 57.12, 57.375],\n                        to_rgb=True),\n                    dict(type='Pad', size_divisor=32),\n                    dict(type='ImageToTensor', keys=['img']),\n                    dict(type='Collect', keys=['img'])\n                ])\n        ]))\nevaluation = dict(interval=1, metric='bbox')\noptimizer = dict(type='AdamW', lr=0.0003)\noptimizer_config = dict(grad_clip=dict(max_norm=35, norm_type=2))\nlr_config = dict(\n    policy='step',\n    warmup='constant',\n    warmup_iters=500,\n    warmup_ratio=0.3333333333333333,\n    step=[15, 25, 38])\ntotal_epochs = 40\ncheckpoint_config = dict(interval=1)\nlog_config = dict(interval=50, hooks=[dict(type='TextLoggerHook')])\ndist_params = dict(backend='nccl')\nlog_level = 'INFO'\nload_from = None\nresume_from = None\nworkflow = [('train', 1)]\nmodel = dict(\n    type='FCOS',\n    pretrained='open-mmlab://resnext101_64x4d',\n    backbone=dict(\n        type='ResNeXt',\n        depth=101,\n        num_stages=4,\n        out_indices=(0, 1, 2, 3),\n        frozen_stages=1,\n        norm_cfg=dict(type='BN', requires_grad=True),\n        norm_eval=True,\n        style='pytorch',\n        groups=64,\n        base_width=4),\n    neck=dict(\n        type='FPN',\n        in_channels=[256, 512, 1024, 2048],\n        out_channels=512,\n        start_level=1,\n        add_extra_convs=True,\n        extra_convs_on_inputs=False,\n        num_outs=5,\n        relu_before_extra_convs=True),\n    bbox_head=dict(\n        type='FCOSHead',\n        num_classes=1,\n        in_channels=512,\n        stacked_convs=4,\n        feat_channels=512,\n        strides=[8, 16, 32, 64, 128],\n        loss_cls=dict(\n            type='FocalLoss',\n            use_sigmoid=True,\n            gamma=2.0,\n            alpha=0.25,\n            loss_weight=1.0),\n        loss_bbox=dict(type='IoULoss', loss_weight=1.0),\n        loss_centerness=dict(\n            type='CrossEntropyLoss', use_sigmoid=True, loss_weight=1.0)))\ntrain_cfg = dict(\n    assigner=dict(\n        type='MaxIoUAssigner',\n        pos_iou_thr=0.5,\n        neg_iou_thr=0.4,\n        min_pos_iou=0,\n        ignore_iof_thr=-1),\n    allowed_border=-1,\n    pos_weight=-1,\n    debug=False)\ntest_cfg = dict(\n    nms_pre=1000,\n    min_bbox_size=0,\n    score_thr=0.05,\n    nms=dict(type='nms', iou_thr=0.5),\n    max_per_img=100)\nclasses = ('wheat', )\nalbu_train_transforms = [\n    dict(type='ToFloat', max_value=255.0),\n    dict(\n        type='RandomSizedCrop',\n        min_max_height=(650, 1024),\n        height=1024,\n        width=1024,\n        p=0.5),\n    dict(\n        type='HueSaturationValue',\n        hue_shift_limit=0.68,\n        sat_shift_limit=0.68,\n        val_shift_limit=0.1,\n        p=0.75),\n    dict(\n        type='RandomBrightnessContrast',\n        brightness_limit=0.1,\n        contrast_limit=0.1,\n        p=0.33),\n    dict(type='RandomRotate90', p=0.5),\n    dict(\n        type='Cutout',\n        num_holes=20,\n        max_h_size=32,\n        max_w_size=32,\n        fill_value=0.0,\n        p=0.25),\n    dict(type='FromFloat', max_value=255.0, dtype='uint8')\n]\nwork_dir = './work_dirs/fcos_wheat2'\ngpu_ids = [0]\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_kg_hide-input":true,"_kg_hide-output":true},"cell_type":"code","source":"config_txt = \"\"\"\ndataset_type = 'CocoDataset'\ndata_root = 'data/global_wheat'\nimg_norm_cfg = dict(\n    mean=[123.675, 116.28, 103.53], std=[58.395, 57.12, 57.375], to_rgb=True)\ntrain_pipeline = [\n    dict(type='LoadImageFromFile'),\n    dict(type='LoadAnnotations', with_bbox=True),\n    dict(\n        type='Resize',\n        img_scale=[(1333, 640), (1333, 800)],\n        multiscale_mode='value',\n        keep_ratio=True),\n    dict(type='RandomFlip', flip_ratio=0.5),\n    dict(\n        type='Normalize',\n        mean=[123.675, 116.28, 103.53],\n        std=[58.395, 57.12, 57.375],\n        to_rgb=True),\n    dict(type='Pad', size_divisor=32),\n    dict(type='DefaultFormatBundle'),\n    dict(type='Collect', keys=['img', 'gt_bboxes', 'gt_labels'])\n]\ntest_pipeline = [\n    dict(type='LoadImageFromFile'),\n    dict(\n        type='MultiScaleFlipAug',\n        img_scale=(1333, 800),\n        flip=False,\n        transforms=[\n            dict(type='Resize', keep_ratio=True),\n            dict(type='RandomFlip'),\n            dict(\n                type='Normalize',\n                mean=[123.675, 116.28, 103.53],\n                std=[58.395, 57.12, 57.375],\n                to_rgb=True),\n            dict(type='Pad', size_divisor=32),\n            dict(type='ImageToTensor', keys=['img']),\n            dict(type='Collect', keys=['img'])\n        ])\n]\ndata = dict(\n    samples_per_gpu=6,\n    workers_per_gpu=6,\n    train=dict(\n        type='CocoDataset',\n        ann_file='data/global_wheat/annotations/train_fold1.json',\n        img_prefix='data/global_wheat/train',\n        pipeline=[\n            dict(type='LoadImageFromFile'),\n            dict(type='LoadAnnotations', with_bbox=True),\n            dict(\n                type='Albu',\n                transforms=[\n                    dict(type='ToFloat', max_value=255.0),\n                    dict(\n                        type='RandomSizedCrop',\n                        min_max_height=(750, 1024),\n                        height=1024,\n                        width=1024,\n                        p=0.5),\n                    dict(\n                        type='HueSaturationValue',\n                        hue_shift_limit=0.68,\n                        sat_shift_limit=0.68,\n                        val_shift_limit=0.1,\n                        p=0.75),\n                    dict(\n                        type='RandomBrightnessContrast',\n                        brightness_limit=0.1,\n                        contrast_limit=0.1,\n                        p=0.33),\n                    dict(type='RandomRotate90', p=0.5),\n                    dict(\n                        type='Cutout',\n                        num_holes=20,\n                        max_h_size=32,\n                        max_w_size=32,\n                        fill_value=0.0,\n                        p=0.25),\n                    dict(type='FromFloat', max_value=255.0, dtype='uint8')\n                ],\n                bbox_params=dict(\n                    type='BboxParams',\n                    format='pascal_voc',\n                    label_fields=['gt_labels'],\n                    min_visibility=0.0,\n                    min_area=0,\n                    filter_lost_elements=True),\n                keymap=dict(img='image', gt_bboxes='bboxes'),\n                update_pad_shape=False,\n                skip_img_without_anno=False),\n            dict(\n                type='Resize',\n                img_scale=[(1333, 640), (1333, 800)],\n                multiscale_mode='value',\n                keep_ratio=True),\n            dict(type='RandomFlip', flip_ratio=0.5, direction='horizontal'),\n            dict(type='RandomFlip', flip_ratio=0.5, direction='vertical'),\n            dict(\n                type='Normalize',\n                mean=[123.675, 116.28, 103.53],\n                std=[58.395, 57.12, 57.375],\n                to_rgb=True),\n            dict(type='Pad', size_divisor=32),\n            dict(type='DefaultFormatBundle'),\n            dict(type='Collect', keys=['img', 'gt_bboxes', 'gt_labels'])\n        ],\n        classes=('wheat', )),\n    val=dict(\n        type='CocoDataset',\n        ann_file='data/global_wheat/annotations/val_fold1.json',\n        img_prefix='data/global_wheat/train',\n        pipeline=[\n            dict(type='LoadImageFromFile'),\n            dict(\n                type='MultiScaleFlipAug',\n                img_scale=(1333, 800),\n                flip=False,\n                transforms=[\n                    dict(type='Resize', keep_ratio=True),\n                    dict(type='RandomFlip'),\n                    dict(\n                        type='Normalize',\n                        mean=[123.675, 116.28, 103.53],\n                        std=[58.395, 57.12, 57.375],\n                        to_rgb=True),\n                    dict(type='Pad', size_divisor=32),\n                    dict(type='ImageToTensor', keys=['img']),\n                    dict(type='Collect', keys=['img'])\n                ])\n        ],\n        classes=('wheat', )),\n    test=dict(\n        type='CocoDataset',\n        ann_file='data/coco/annotations/instances_val2017.json',\n        img_prefix='data/coco/val2017/',\n        pipeline=[\n            dict(type='LoadImageFromFile'),\n            dict(\n                type='MultiScaleFlipAug',\n                img_scale=(1333, 800),\n                flip=False,\n                transforms=[\n                    dict(type='Resize', keep_ratio=True),\n                    dict(type='RandomFlip'),\n                    dict(\n                        type='Normalize',\n                        mean=[123.675, 116.28, 103.53],\n                        std=[58.395, 57.12, 57.375],\n                        to_rgb=True),\n                    dict(type='Pad', size_divisor=32),\n                    dict(type='ImageToTensor', keys=['img']),\n                    dict(type='Collect', keys=['img'])\n                ])\n        ]))\nevaluation = dict(interval=1, metric='bbox')\noptimizer = dict(type='AdamW', lr=0.0003)\noptimizer_config = dict(grad_clip=dict(max_norm=35, norm_type=2))\nlr_config = dict(\n    policy='step',\n    warmup='constant',\n    warmup_iters=500,\n    warmup_ratio=0.3333333333333333,\n    step=[15, 24, 32, 38])\ntotal_epochs = 40\ncheckpoint_config = dict(interval=1)\nlog_config = dict(interval=50, hooks=[dict(type='TextLoggerHook')])\ndist_params = dict(backend='nccl')\nlog_level = 'INFO'\nload_from = None\nresume_from = None\nworkflow = [('train', 1)]\nmodel = dict(\n    type='FCOS',\n    pretrained='open-mmlab://resnext101_64x4d',\n    backbone=dict(\n        type='ResNeXt',\n        depth=101,\n        num_stages=4,\n        out_indices=(0, 1, 2, 3),\n        frozen_stages=1,\n        norm_cfg=dict(type='BN', requires_grad=True),\n        norm_eval=True,\n        style='pytorch',\n        groups=64,\n        base_width=4),\n    neck=dict(\n        type='FPN',\n        in_channels=[256, 512, 1024, 2048],\n        out_channels=512,\n        start_level=1,\n        add_extra_convs=True,\n        extra_convs_on_inputs=False,\n        num_outs=5,\n        relu_before_extra_convs=True),\n    bbox_head=dict(\n        type='FCOSHead',\n        num_classes=1,\n        in_channels=512,\n        stacked_convs=4,\n        feat_channels=512,\n        strides=[8, 16, 32, 64, 128],\n        loss_cls=dict(\n            type='FocalLoss',\n            use_sigmoid=True,\n            gamma=2.0,\n            alpha=0.25,\n            loss_weight=1.0),\n        loss_bbox=dict(type='IoULoss', loss_weight=1.0),\n        loss_centerness=dict(\n            type='CrossEntropyLoss', use_sigmoid=True, loss_weight=1.0)))\ntrain_cfg = dict(\n    assigner=dict(\n        type='MaxIoUAssigner',\n        pos_iou_thr=0.7,\n        neg_iou_thr=0.5,\n        min_pos_iou=0,\n        ignore_iof_thr=-1),\n    allowed_border=-1,\n    pos_weight=-1,\n    debug=False)\ntest_cfg = dict(\n    nms_pre=1000,\n    min_bbox_size=0,\n    score_thr=0.05,\n    nms=dict(type='nms', iou_thr=0.45),\n    max_per_img=200)\nclasses = ('wheat', )\nalbu_train_transforms = [\n    dict(type='ToFloat', max_value=255.0),\n    dict(\n        type='RandomSizedCrop',\n        min_max_height=(750, 1024),\n        height=1024,\n        width=1024,\n        p=0.5),\n    dict(\n        type='HueSaturationValue',\n        hue_shift_limit=0.68,\n        sat_shift_limit=0.68,\n        val_shift_limit=0.1,\n        p=0.75),\n    dict(\n        type='RandomBrightnessContrast',\n        brightness_limit=0.1,\n        contrast_limit=0.1,\n        p=0.33),\n    dict(type='RandomRotate90', p=0.5),\n    dict(\n        type='Cutout',\n        num_holes=20,\n        max_h_size=32,\n        max_w_size=32,\n        fill_value=0.0,\n        p=0.25),\n    dict(type='FromFloat', max_value=255.0, dtype='uint8')\n]\nwork_dir = './work_dirs/fcos_iou'\ngpu_ids = [0]\n\"\"\"\nconfig_file = open(\"/kaggle/working/mmdetection/config.py\", \"w\")\nn = config_file.write(config_txt)\nconfig_file.close()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_kg_hide-input":true,"_kg_hide-output":true},"cell_type":"code","source":"def format_prediction_string(boxes, scores):\n    pred_strings = []\n    for j in zip(scores, boxes):\n        pred_strings.append(\"{0:.4f} {1} {2} {3} {4}\".format(j[0], j[1][0], j[1][1], j[1][2], j[1][3]))\n    return \" \".join(pred_strings)\n","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"In a non-kaggle environment the configs support inheritance so you don't need to fully specify every detail\n\nUsing the model specified above and the weights I trained on my local machine, we'll make predictions our predictions below. Most of the code should look pretty familiar.","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"from mmdet.apis import init_detector, inference_detector\nimport pandas as pd\nimport numpy as np\n\ncheckpoint_path = '../input/resnest3fcos1iouatseven/epoch_40.pth'\nconfig_path = '/kaggle/working/mmdetection/config.py'\n\nmodel = init_detector(config_path, checkpoint_path, device='cuda:0')\n\nval_df = pd.read_csv('../input/global-wheat-detection/sample_submission.csv')\nall_image_ids = set(val_df['image_id'].unique())\npred_threshold = 0.25\n\npred_results = []\nfor image_id in all_image_ids:\n    img = '../input/global-wheat-detection/test/' + image_id + '.jpg'\n    result = inference_detector(model, img)\n    \n    boxes = result[0][:, 0:4]\n    scores = result[0][:, 4]\n\n    boxes[:, 2] = boxes[:, 2] - boxes[:, 0]\n    boxes[:, 3] = boxes[:, 3] - boxes[:, 1]\n    \n    boxes = boxes[scores >= pred_threshold].astype(np.int32)\n    scores = scores[scores >= pred_threshold]\n\n    result = {\n        'image_id': image_id,\n        'PredictionString': format_prediction_string(boxes, scores)\n    }\n\n    pred_results.append(result)\n    \n\ntest_df = pd.DataFrame(pred_results, columns=['image_id', 'PredictionString'])\ntest_df.to_csv('submission.csv', index=False)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Finally, we can't submit if we leave any files other than our submission in the working dir, so we'll clean up some of the boilerplate we copied over earlier:","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"!rm -rf mmdetection/","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Thanks for reading! Let me know in the comments if you have any questions.\n\n-Ryan","execution_count":null}],"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}