{"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_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"<p style='text-align: center;'><span style=\"color: #000508; font-family: Segoe UI; font-size: 2.5em; font-weight: 300;\">Cowboy outfits detection MMDetection+CascadeRCNN+Weight&Bias</span></p>","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19"}},{"cell_type":"markdown","source":"<span style=\"color: #E45D00; font-family: Segoe UI; font-size: 1.9em; font-weight: 300;\">Overview</span>\n\n&nbsp;&nbsp;✅&nbsp;&nbsp;MMDetection and Weights & Biases Setup<br>\n&nbsp;&nbsp;✅&nbsp;&nbsp;Preparation of MMDetection Config<br>\n&nbsp;&nbsp;✅&nbsp;&nbsp;Weights & Biases Integration<br>\n&nbsp;&nbsp;✅&nbsp;&nbsp;Training and Evaluation<br>\n&nbsp;&nbsp;✅&nbsp;&nbsp;Experiment Tracking and Logging with Weights & Biases<br>\n&nbsp;&nbsp;✅&nbsp;&nbsp;Inference<br>\n\n<span style=\"color: #E45D00; font-family: Segoe UI; font-size: 1.9em; font-weight: 300;\">MMDetection</span>\n\n[MMDetection](https://github.com/open-mmlab/mmdetection) is an open-source toolbox based on PyTorch for Object Detection and Segmentation tasks. The toolbox supports over **50+ baselines**.\n\n<span style=\"color: #000508; font-family: Segoe UI; font-size: 1.4em;\">🧫 Features:</span>\n\n<p style='text-align: justify; font-family: Segoe UI;'><span style=\"color: #000508;  font-size: 1.1em; font-weight: 600;\">Modular Design</span>: The framework is split into different components and we can easily construct a customized object detection framework by combining different modules.</p>\n\n<p style='text-align: justify; font-family: Segoe UI;'><span style=\"color: #000508;  font-size: 1.1em; font-weight: 600;\">Support of multiple frameworks out of box</span>: The toolbox directly supports popular and contemporary detection frameworks, e.g. Faster RCNN, Mask RCNN, RetinaNet, etc.</p>\n\n<p style='text-align: justify; font-family: Segoe UI;'><span style=\"color: #000508;  font-size: 1.1em; font-weight: 600;\">High efficiency</span>: All basic bbox and mask operations run on GPUs. The training speed is faster than or comparable to other codebases, including Detectron2, maskrcnn-benchmark and SimpleDet.</p>\n\n<p style='text-align: justify; font-family: Segoe UI;'><span style=\"color: #000508;  font-size: 1.1em; font-weight: 600;\">State of the art</span>: The toolbox stems from the codebase developed by the MMDet team, who won COCO Detection Challenge in 2018.</p>\n\n\n<span style=\"color: #000508; font-family: Segoe UI; font-size: 1.4em;\">🎆 References:</span>\n\n- **Some amazing notebooks on MMdetection from [Sreevishnu Damodaran](https://www.kaggle.com/sreevishnudamodaran)**\n    - https://www.kaggle.com/sreevishnudamodaran/siim-mmdetection-cascadercnn-weight-bias\n\n\n- https://www.kaggle.com/c/cowboyoutfits/discussion/254656\n- https://www.kaggle.com/c/cowboyoutfits/discussion/254354\n\n<span style=\"color: #000508; font-family: Segoe UI; font-size: 1.4em;\">Please upvote if you like this</span>\n\n","metadata":{"execution":{"iopub.status.busy":"2021-07-26T03:14:32.758685Z","iopub.execute_input":"2021-07-26T03:14:32.759254Z","iopub.status.idle":"2021-07-26T03:14:33.005808Z","shell.execute_reply.started":"2021-07-26T03:14:32.759219Z","shell.execute_reply":"2021-07-26T03:14:33.00449Z"}}},{"cell_type":"markdown","source":"<span style=\"color: #E45D00; font-family: Segoe UI; font-size: 1.9em; font-weight: 300;\">📐 Setup MMDetection</span>","metadata":{}},{"cell_type":"code","source":"%%bash\n# Check nvcc version\nnvcc -V\necho\n# Check GCC version\ngcc --version\necho\n# Check the version of torch and cuda packages\npip list | grep \"torch\\|cuda\"","metadata":{"execution":{"iopub.status.busy":"2021-08-08T09:50:53.047225Z","iopub.execute_input":"2021-08-08T09:50:53.047483Z","iopub.status.idle":"2021-08-08T09:50:54.277139Z","shell.execute_reply.started":"2021-08-08T09:50:53.047457Z","shell.execute_reply":"2021-08-08T09:50:54.27625Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%%capture\n!pip install mmcv-full==1.3.8 -f https://download.openmmlab.com/mmcv/dist/cu110/torch1.7.0/index.html","metadata":{"execution":{"iopub.status.busy":"2021-08-08T09:50:54.278754Z","iopub.execute_input":"2021-08-08T09:50:54.279137Z","iopub.status.idle":"2021-08-08T09:51:08.369457Z","shell.execute_reply.started":"2021-08-08T09:50:54.279096Z","shell.execute_reply":"2021-08-08T09:51:08.368313Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%%capture\n!rm -rf mmdetection\n!git clone https://github.com/open-mmlab/mmdetection.git\n!cd mmdetection && pip install -e .\n\n!pip install Pillow==7.0.0","metadata":{"execution":{"iopub.status.busy":"2021-08-08T09:51:08.375759Z","iopub.execute_input":"2021-08-08T09:51:08.378497Z","iopub.status.idle":"2021-08-08T09:51:43.750002Z","shell.execute_reply.started":"2021-08-08T09:51:08.378453Z","shell.execute_reply":"2021-08-08T09:51:43.748919Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<span style=\"color: #E45D00; font-family: Segoe UI; font-size: 1.9em; font-weight: 300;\">Setup Weights & Biases</span>","metadata":{}},{"cell_type":"code","source":"%%capture\n!pip install wandb --upgrade","metadata":{"execution":{"iopub.status.busy":"2021-08-08T09:51:43.751721Z","iopub.execute_input":"2021-08-08T09:51:43.752085Z","iopub.status.idle":"2021-08-08T09:51:50.55401Z","shell.execute_reply.started":"2021-08-08T09:51:43.752047Z","shell.execute_reply":"2021-08-08T09:51:50.552908Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"To connect the Kaggle Notebook and log in to Weights & Biases, we need to create an API key:\n\n1. New users can sign up for a Free Weights & Biases account for Research and Personal use from the https://wandb.ai/site page. Sign up process takes around 1-2 minutes.\n2. Now get the API key from https://wandb.ai/authorize.\n\nLogin to Weights & Biases from the notebook with the API key by using any of the two methods below:\n\n* Interative:\n    1. Run a cell with wandb.login(). It will ask for the API key, which can be copied and pasted to authenticate.\n\n* Kaggle Secrets:\n    1. The recommended way to use the API key is to use Kaggle Secrets to store the API key. From the top Menu on the Notebook Editor, click on 'Add-ons' and then, select 'Secrets'.\n    2. Select 'Add a new secret' and provide 'wandb_key' for label and it's value as the API key obtained from the previous steps.","metadata":{}},{"cell_type":"code","source":"import wandb\nfrom kaggle_secrets import UserSecretsClient\n\nuser_secrets = UserSecretsClient()\n\n# I have saved my API token with \"wandb_api\" as Label. \n# If you use some other Label make sure to change the same below. \nwandb_api = user_secrets.get_secret(\"wandb_key\") \n\nwandb.login(key=wandb_api)","metadata":{"execution":{"iopub.status.busy":"2021-08-08T09:51:50.555609Z","iopub.execute_input":"2021-08-08T09:51:50.556015Z","iopub.status.idle":"2021-08-08T09:51:51.103347Z","shell.execute_reply.started":"2021-08-08T09:51:50.555976Z","shell.execute_reply":"2021-08-08T09:51:51.102483Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<span style=\"color: #E45D00; font-family: Segoe UI; font-size: 1.9em; font-weight: 300;\">Imports and Seed Everything</span>","metadata":{}},{"cell_type":"code","source":"import sys\nsys.path.insert(0, \"./mmdetection\")\n\nimport os\n# Check Pytorch installation\nimport torch, torchvision\nprint(torch.__version__, torch.cuda.is_available())\n\n# Check mmcv installation\nfrom mmcv.ops import get_compiling_cuda_version, get_compiler_version\nprint(get_compiling_cuda_version())\nprint(get_compiler_version())\n\n# Check MMDetection installation\nfrom mmdet.apis import set_random_seed\n\n# Imports\nimport mmdet\nfrom mmdet.apis import set_random_seed\nfrom mmdet.datasets import build_dataset\nfrom mmdet.models import build_detector\nfrom mmdet.apis import train_detector\n\nimport random\nimport numpy as np\nfrom pathlib import Path\nimport copy\nimport json\nfrom pycocotools.coco import COCO","metadata":{"execution":{"iopub.status.busy":"2021-08-08T09:53:45.50057Z","iopub.execute_input":"2021-08-08T09:53:45.500967Z","iopub.status.idle":"2021-08-08T09:53:59.26205Z","shell.execute_reply.started":"2021-08-08T09:53:45.500935Z","shell.execute_reply":"2021-08-08T09:53:59.261162Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"seed = 1234\n\n\"\"\"Sets the random seeds.\"\"\"\nset_random_seed(seed, deterministic=False)\nrandom.seed(seed)\nnp.random.seed(seed)\ntorch.manual_seed(seed)\ntorch.cuda.manual_seed(seed)\ntorch.backends.cudnn.deterministic = True\ntorch.backends.cudnn.benchmark = False\nos.environ['PYTHONHASHSEED'] = str(seed)","metadata":{"execution":{"iopub.status.busy":"2021-08-08T09:53:59.263577Z","iopub.execute_input":"2021-08-08T09:53:59.263947Z","iopub.status.idle":"2021-08-08T09:53:59.275949Z","shell.execute_reply.started":"2021-08-08T09:53:59.263909Z","shell.execute_reply":"2021-08-08T09:53:59.274841Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<span style=\"color: #E45D00; font-family: Segoe UI; font-size: 1.9em; font-weight: 300;\">Split Train and Valid Data Set</span>\n","metadata":{}},{"cell_type":"code","source":"!mkdir new_anno","metadata":{"execution":{"iopub.status.busy":"2021-08-08T09:53:59.277595Z","iopub.execute_input":"2021-08-08T09:53:59.277938Z","iopub.status.idle":"2021-08-08T09:53:59.914644Z","shell.execute_reply.started":"2021-08-08T09:53:59.277908Z","shell.execute_reply":"2021-08-08T09:53:59.913513Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"You can change the test_n to get a different split","metadata":{}},{"cell_type":"code","source":"random.seed(seed)\n\ndef create_subset(c, cats, test_n=180):\n    new_coco = {}\n    new_coco['info'] = {\"description\": \"CowboySuit\",\n                        \"url\": \"http://github.com/dmlc/gluon-cv\",\n                        \"version\": \"1.0\",\"year\": 2021,\n                        \"contributor\": \"GluonCV/AutoGluon\",\n                        \"date_created\": \"2021/07/01\"}\n    new_coco[\"licenses\"]: [\n        {\"url\": \"http://creativecommons.org/licenses/by/2.0/\",\"id\": 4,\"name\": \"Attribution License\"}]\n    cat_ids = c.getCatIds(cats)\n    train_img_ids = set()\n\n    test_img_ids = set()\n    for cat in cat_ids[::-1]:\n        img_ids = copy.copy(c.getImgIds(catIds=[cat]))\n        random.shuffle(img_ids)\n        tn = min(test_n, int(len(img_ids) * 0.5))\n        new_test = set(img_ids[:tn])\n        exist_test_ids = new_test.intersection(train_img_ids)\n        test_ids = new_test.difference(exist_test_ids)\n        train_ids = set(img_ids).difference(test_ids)\n        print(tn, len(img_ids), len(new_test), len(test_ids), len(train_ids))\n        train_img_ids.update(train_ids)\n        test_img_ids.update(test_ids)\n#         print(len(test_img_ids))\n\n    # prune duplicates\n    dup = train_img_ids.intersection(test_img_ids)\n    train_img_ids = train_img_ids - dup\n\n    train_anno_ids = set()\n    test_anno_ids = set()\n    for cat in cat_ids:\n        train_anno_ids.update(c.getAnnIds(imgIds=list(train_img_ids), catIds=[cat]))\n        test_anno_ids.update(c.getAnnIds(imgIds=list(test_img_ids), catIds=[cat]))\n\n    assert len(train_img_ids.intersection(test_img_ids)) == 0, 'img id conflicts, {} '.format(train_img_ids.intersection(test_img_ids))\n    assert len(train_anno_ids.intersection(test_anno_ids)) == 0, 'anno id conflicts'\n    print('train img ids #:', len(train_img_ids), 'train anno #:', len(train_anno_ids))\n    print('valid img ids #:', len(test_img_ids), 'test anno #:', len(test_anno_ids))\n    new_coco_test = copy.deepcopy(new_coco)\n\n    new_coco[\"images\"] = c.loadImgs(list(train_img_ids))\n    new_coco[\"annotations\"] = c.loadAnns(list(train_anno_ids))\n    for ann in new_coco[\"annotations\"]:\n        ann.pop('segmentation', None)\n    new_coco[\"categories\"] = c.loadCats(cat_ids)\n\n    new_coco_test[\"images\"] = c.loadImgs(list(test_img_ids))\n    new_coco_test[\"annotations\"] = c.loadAnns(list(test_anno_ids))\n    for ann in new_coco_test[\"annotations\"]:\n        ann.pop('segmentation', None)\n    new_coco_test[\"categories\"] = c.loadCats(cat_ids)\n    print('new train split, images:', len(new_coco[\"images\"]), 'annos:', len(new_coco[\"annotations\"]))\n    print('new valid split, images:', len(new_coco_test[\"images\"]), 'annos:', len(new_coco_test[\"annotations\"]))\n    return new_coco, new_coco_test\n\ncoco = COCO('../input/cowboyoutfits/train.json')\nnc, nc_test = create_subset(coco, ['belt', 'sunglasses', 'boot', 'cowboy_hat', 'jacket', ])\n\nwith open('./new_anno/new_train.json', 'w') as f:\n    json.dump(nc, f)\nwith open('./new_anno/new_valid.json', 'w') as f:\n    json.dump(nc_test, f)","metadata":{"execution":{"iopub.status.busy":"2021-08-08T09:54:00.248544Z","iopub.execute_input":"2021-08-08T09:54:00.248923Z","iopub.status.idle":"2021-08-08T09:54:00.565499Z","shell.execute_reply.started":"2021-08-08T09:54:00.248887Z","shell.execute_reply":"2021-08-08T09:54:00.564671Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<span style=\"color: #E45D00; font-family: Segoe UI; font-size: 1.9em; font-weight: 300;\">🔨 Prepare the MMDetection Config</span>","metadata":{}},{"cell_type":"code","source":"from mmcv import Config\n\n# baseline_cfg_path = \"/kaggle/working/mmdetection/configs/cascade_rcnn/cascade_rcnn_x101_32x4d_fpn_1x_coco.py\"\nbaseline_cfg_path = \"/kaggle/working/mmdetection/configs/cascade_rcnn/cascade_rcnn_r50_fpn_1x_coco.py\"\n\ncfg = Config.fromfile(baseline_cfg_path)","metadata":{"execution":{"iopub.status.busy":"2021-08-08T09:54:06.015897Z","iopub.execute_input":"2021-08-08T09:54:06.016289Z","iopub.status.idle":"2021-08-08T09:54:06.044834Z","shell.execute_reply.started":"2021-08-08T09:54:06.016255Z","shell.execute_reply":"2021-08-08T09:54:06.043948Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<span style=\"color: #000508; font-family: Segoe UI; font-size: 1.6em; font-weight: 300;\">General Training Settings</span>\n\n","metadata":{}},{"cell_type":"code","source":"model_name = 'cascade_rcnn_r50_fpn_1x'\njob = 4\n\n# Folder to store model logs and weight files\njob_folder = f'/kaggle/working/job{job}_{model_name}'\ncfg.work_dir = job_folder\n\n# Change the wandb username and project name below\nwnb_username = 'nekokiku'\nwnb_project_name = 'kaggle_cowboy_outfits'\n\n# Set seed thus the results are more reproducible\ncfg.seed = seed\n\n# You should change this if you use different model\ncfg.load_from = 'https://download.openmmlab.com/mmdetection/v2.0/cascade_rcnn/cascade_rcnn_r50_fpn_1x_coco/cascade_rcnn_r50_fpn_1x_coco_20200316-3dc56deb.pth'\n\nif not os.path.exists(job_folder):\n    os.makedirs(job_folder)\n\nprint(\"Job folder:\", job_folder)","metadata":{"execution":{"iopub.status.busy":"2021-07-26T08:21:06.977502Z","iopub.execute_input":"2021-07-26T08:21:06.977817Z","iopub.status.idle":"2021-07-26T08:21:06.985476Z","shell.execute_reply.started":"2021-07-26T08:21:06.977791Z","shell.execute_reply":"2021-07-26T08:21:06.98453Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"12 epochs !","metadata":{}},{"cell_type":"code","source":"# Set the number of classes\nfor head in cfg.model.roi_head.bbox_head:\n    head.num_classes = 5\n\ncfg.gpu_ids = [0]\n\ncfg.runner.max_epochs = 12 # Epochs for the runner that runs the workflow \ncfg.total_epochs = 12\n\n# Learning rate of optimizers. The LR is divided by 8 since the config file is originally for 8 GPUs\ncfg.optimizer.lr = 0.02/8\n\n## Learning rate scheduler config used to register LrUpdater hook\ncfg.lr_config = dict(\n    policy='CosineAnnealing', # The policy of scheduler, also support CosineAnnealing, Cyclic, etc. Refer to details of supported LrUpdater from https://github.com/open-mmlab/mmcv/blob/master/mmcv/runner/hooks/lr_updater.py#L9.\n    by_epoch=False,\n    warmup='linear', # The warmup policy, also support `exp` and `constant`.\n    warmup_iters=500, # The number of iterations for warmup\n    warmup_ratio=0.001, # The ratio of the starting learning rate used for warmup\n    min_lr=1e-07)\n\n# config to register logger hook\ncfg.log_config.interval = 40 # Interval to print the log\n\n# Config to set the checkpoint hook, Refer to https://github.com/open-mmlab/mmcv/blob/master/mmcv/runner/hooks/checkpoint.py for implementation.\ncfg.checkpoint_config.interval = 1 # The save interval is 1","metadata":{"execution":{"iopub.status.busy":"2021-07-26T08:21:06.98684Z","iopub.execute_input":"2021-07-26T08:21:06.987519Z","iopub.status.idle":"2021-07-26T08:21:06.994887Z","shell.execute_reply.started":"2021-07-26T08:21:06.987479Z","shell.execute_reply":"2021-07-26T08:21:06.994079Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<span style=\"color: #000508; font-family: Segoe UI; font-size: 1.6em; font-weight: 300;\">Configure Datasets for Training and Evaluation</span>","metadata":{}},{"cell_type":"code","source":"cfg.dataset_type = 'CocoDataset' # Dataset type, this will be used to define the dataset\ncfg.classes = (\"belt\",\"sunglasses\",\"boot\",\"cowboy_hat\",\"jacket\")\n\ndata_images = '/kaggle/input/cowboyoutfits/images'\n\ncfg.data.train.img_prefix = data_images\ncfg.data.train.classes = cfg.classes\ncfg.data.train.ann_file = '/kaggle/working/new_anno/new_train.json'\ncfg.data.train.type='CocoDataset'\n\ncfg.data.val.img_prefix = data_images\ncfg.data.val.classes = cfg.classes\ncfg.data.val.ann_file = '/kaggle/working/new_anno/new_valid.json'\ncfg.data.val.type='CocoDataset'\n\ncfg.data.test.img_prefix = data_images\ncfg.data.test.classes = cfg.classes\ncfg.data.test.ann_file = '/kaggle/working/new_anno/new_valid.json'\ncfg.data.test.type='CocoDataset'\n\ncfg.data.samples_per_gpu = 4 # Batch size of a single GPU used in testing\ncfg.data.workers_per_gpu = 2 # Worker to pre-fetch data for each single GPU","metadata":{"execution":{"iopub.status.busy":"2021-07-26T08:21:06.995805Z","iopub.execute_input":"2021-07-26T08:21:06.996346Z","iopub.status.idle":"2021-07-26T08:21:07.007574Z","shell.execute_reply.started":"2021-07-26T08:21:06.996308Z","shell.execute_reply":"2021-07-26T08:21:07.006684Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<span style=\"color: #000508; font-family: Segoe UI; font-size: 1.6em; font-weight: 300;\">Setting Metric for Evaluation</span>","metadata":{}},{"cell_type":"code","source":"# The config to build the evaluation hook, refer to https://github.com/open-mmlab/mmdetection/blob/master/mmdet/core/evaluation/eval_hooks.py#L7 for more details.\ncfg.evaluation.metric = 'bbox' # Metrics used during evaluation\n\n# Set the epoch intervel to perform evaluation\ncfg.evaluation.interval = 1\n\ncfg.evaluation.save_best='bbox_mAP'","metadata":{"execution":{"iopub.status.busy":"2021-07-26T08:21:07.00898Z","iopub.execute_input":"2021-07-26T08:21:07.009514Z","iopub.status.idle":"2021-07-26T08:21:07.019762Z","shell.execute_reply.started":"2021-07-26T08:21:07.009475Z","shell.execute_reply":"2021-07-26T08:21:07.018919Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<span style=\"color: #000508; font-family: Segoe UI; font-size: 1.6em; font-weight: 300;\">Prepare the Pre-processing & Augmentation Pipelines</span>","metadata":{}},{"cell_type":"markdown","source":"You can choose different data augmentation strategies","metadata":{}},{"cell_type":"code","source":"# albu_train_transforms = [\n#     dict(type='ShiftScaleRotate', shift_limit=0.0625,\n#          scale_limit=0.15, rotate_limit=15, p=0.4),\n#     dict(type='RandomBrightnessContrast', brightness_limit=0.2,\n#          contrast_limit=0.2, p=0.5),\n#     dict(type='IAAAffine', shear=(-10.0, 10.0), p=0.4),\n#     dict(type=\"Blur\", p=1.0, blur_limit=7),\n#     dict(type='CLAHE', p=0.5),\n#     dict(type='Equalize', mode='cv', p=0.4),\n#     dict(\n#         type=\"OneOf\",\n#         transforms=[\n#             dict(type=\"GaussianBlur\", p=1.0, blur_limit=7),\n#             dict(type=\"MedianBlur\", p=1.0, blur_limit=7),\n#         ],\n#         p=0.4,\n#     ),\n#     ]\n\n# cfg.train_pipeline = [\n#     dict(type='LoadImageFromFile'),\n#     dict(type='LoadAnnotations', with_bbox=True, with_mask=True),\n#     dict(type='Resize', img_scale=(1333, 800), keep_ratio=True),\n#     dict(type='RandomFlip', flip_ratio=0.5),\n#     dict(\n#         type='Albu',\n#         transforms=albu_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=dict(img='image', gt_bboxes='bboxes'),\n#         update_pad_shape=False,\n#         skip_img_without_anno=True),\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","metadata":{"execution":{"iopub.status.busy":"2021-07-26T08:21:07.021047Z","iopub.execute_input":"2021-07-26T08:21:07.021437Z","iopub.status.idle":"2021-07-26T08:21:07.02837Z","shell.execute_reply.started":"2021-07-26T08:21:07.021397Z","shell.execute_reply":"2021-07-26T08:21:07.027548Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<span style=\"color: #000508; font-family: Segoe UI; font-size: 1.6em; font-weight: 300;\">Weights & Biases Integration for Experiment Tracking and Logging</span>","metadata":{}},{"cell_type":"code","source":"cfg.log_config.hooks = [dict(type='TextLoggerHook'),\n                        dict(type='WandbLoggerHook',\n                             init_kwargs=dict(project=wnb_project_name,\n                                              name=f'exp-{model_name}-job{job}',\n                                              entity=wnb_username))\n                       ]","metadata":{"execution":{"iopub.status.busy":"2021-07-26T08:21:07.029692Z","iopub.execute_input":"2021-07-26T08:21:07.030117Z","iopub.status.idle":"2021-07-26T08:21:07.039705Z","shell.execute_reply.started":"2021-07-26T08:21:07.030081Z","shell.execute_reply":"2021-07-26T08:21:07.038946Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<span style=\"color: #000508; font-family: Segoe UI; font-size: 1.6em; font-weight: 300;\">Save Config File</span>","metadata":{}},{"cell_type":"code","source":"cfg_path = f'{job_folder}/job{job}_{Path(baseline_cfg_path).name}'\nprint(cfg_path)\n\n# Save config file for inference later\ncfg.dump(cfg_path)\nprint(f'Config:\\n{cfg.pretty_text}')","metadata":{"execution":{"iopub.status.busy":"2021-07-26T08:21:07.040698Z","iopub.execute_input":"2021-07-26T08:21:07.040989Z","iopub.status.idle":"2021-07-26T08:21:08.037793Z","shell.execute_reply.started":"2021-07-26T08:21:07.040953Z","shell.execute_reply":"2021-07-26T08:21:08.03692Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<span style=\"color: #E45D00; font-family: Segoe UI; font-size: 1.9em; font-weight: 300;\">🚀 Build Dataset and Start Training</span>","metadata":{}},{"cell_type":"code","source":"model = build_detector(cfg.model,\n                       train_cfg=cfg.get('train_cfg'),\n                       test_cfg=cfg.get('test_cfg'))\nmodel.init_weights()","metadata":{"execution":{"iopub.status.busy":"2021-07-26T08:21:48.19223Z","iopub.execute_input":"2021-07-26T08:21:48.192623Z","iopub.status.idle":"2021-07-26T08:21:53.938844Z","shell.execute_reply.started":"2021-07-26T08:21:48.192588Z","shell.execute_reply":"2021-07-26T08:21:53.937783Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"datasets = [build_dataset(cfg.data.train)]","metadata":{"execution":{"iopub.status.busy":"2021-07-26T08:21:53.940751Z","iopub.execute_input":"2021-07-26T08:21:53.941202Z","iopub.status.idle":"2021-07-26T08:21:54.155393Z","shell.execute_reply.started":"2021-07-26T08:21:53.941157Z","shell.execute_reply":"2021-07-26T08:21:54.154457Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_detector(model, datasets[0], cfg, distributed=False, validate=True)","metadata":{"execution":{"iopub.status.busy":"2021-07-26T08:21:54.157192Z","iopub.execute_input":"2021-07-26T08:21:54.157606Z","iopub.status.idle":"2021-07-26T08:49:11.703326Z","shell.execute_reply.started":"2021-07-26T08:21:54.157561Z","shell.execute_reply":"2021-07-26T08:49:11.702214Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<span style=\"color: #E45D00; font-family: Segoe UI; font-size: 1.9em; font-weight: 300;\">📰 Inference and Visualize Output</span>","metadata":{}},{"cell_type":"code","source":"import numpy as np\nfrom tqdm import tqdm\nimport json  # for dumping json serialized results\nimport zipfile  # for creating submission zip file\nimport pandas as pd\nimport cv2\nimport os\nfrom matplotlib import pyplot as plt\nfrom mmdet.apis import inference_detector, init_detector, show_result_pyplot","metadata":{"execution":{"iopub.status.busy":"2021-07-26T08:50:25.708005Z","iopub.execute_input":"2021-07-26T08:50:25.708352Z","iopub.status.idle":"2021-07-26T08:50:25.712672Z","shell.execute_reply.started":"2021-07-26T08:50:25.708321Z","shell.execute_reply":"2021-07-26T08:50:25.711809Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Get the best epoch number\nimport json\nfrom collections import defaultdict\n\nlog_file = f'{job_folder}/None.log.json'\n\n# Source: mmdetection/tools/analysis_tools/analyze_logs.py \ndef load_json_logs(json_logs):\n    # load and convert json_logs to log_dict, key is epoch, value is a sub dict\n    # keys of sub dict is different metrics, e.g. memory, bbox_mAP\n    # value of sub dict is a list of corresponding values of all iterations\n    log_dicts = [dict() for _ in json_logs]\n    for json_log, log_dict in zip(json_logs, log_dicts):\n        with open(json_log, 'r') as log_file:\n            for line in log_file:\n                log = json.loads(line.strip())\n                # skip lines without `epoch` field\n                if 'epoch' not in log:\n                    continue\n                epoch = log.pop('epoch')\n                if epoch not in log_dict:\n                    log_dict[epoch] = defaultdict(list)\n                for k, v in log.items():\n                    log_dict[epoch][k].append(v)\n    return log_dicts\n\nlog_dict = load_json_logs([log_file])\nbest_epoch = np.argmax([item['bbox_mAP'][0] for item in log_dict[0].values()])+1\nbest_epoch","metadata":{"execution":{"iopub.status.busy":"2021-07-26T08:50:26.066598Z","iopub.execute_input":"2021-07-26T08:50:26.066941Z","iopub.status.idle":"2021-07-26T08:50:26.081148Z","shell.execute_reply.started":"2021-07-26T08:50:26.066907Z","shell.execute_reply":"2021-07-26T08:50:26.080165Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\ndef create_submission(df, model, score_thresh=0.1):\n    results = []\n    for index, row in tqdm(df.iterrows()):\n        img_id = row['id']\n        file_name = row['file_name']\n        img_base = '/kaggle/input/cowboyoutfits/images/'\n        img = img_base + file_name\n        result = inference_detector(model, img)\n\n        for i in range(5):\n            if len(result[i]) != 0:\n                for j in result[i]:\n                    j = np.array(j).tolist()\n                    if j[-1] >= score_thresh:\n                        # 这里注意原来是xmin, ymin, xmax, ymax.\n                        # coco 需要的数据格式是xmin, ymin, w, h.\n                        pred = {'image_id': img_id,\n                                'category_id': int(classes_id[i]),\n                                'bbox': [j[0], j[1], j[2]-j[0], j[3]-j[1]],\n                                'score': j[-1]}\n                        results.append(pred)\n    return results\n\n#  zip name \nzip_name = 'cascade_job1'\n# classes\nclasses = ('belt', 'sunglasses', 'boot', 'cowboy_hat', 'jacket')\nclasses_id = ('87', '1034', '131', '318', '588')\n\n# Choose to use a config and checkpoint\nconfig = cfg_path\n# Setup a checkpoint file to load\ncheckpoint = f'{job_folder}/epoch_{best_epoch}.pth'\n# val path\nval_path = '/kaggle/input/cowboyoutfits/valid.csv'\n\n# submission path\nsubmission_path = '/kaggle/working/answer.json'\n# zipfile path\nzipfile_path = '/kaggle/working/' + 'zip_' +  zip_name +'.zip'\n\nmodel = init_detector(config, checkpoint, device='cuda:0')\nsubmission_df = pd.read_csv(val_path)\nsubmission = create_submission(submission_df, model)\n\nprint(config)\nprint(checkpoint)\n\nwith open(submission_path, 'w') as f:\n    json.dump(submission, f)\n\nzf = zipfile.ZipFile(zipfile_path, 'w')\nzf.write(submission_path, 'answer.json')\nzf.close()","metadata":{"execution":{"iopub.status.busy":"2021-07-26T08:50:26.472537Z","iopub.execute_input":"2021-07-26T08:50:26.472884Z","iopub.status.idle":"2021-07-26T08:53:03.773434Z","shell.execute_reply.started":"2021-07-26T08:50:26.472832Z","shell.execute_reply":"2021-07-26T08:53:03.772584Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_xyxy_from_cowboy(img_name, df, json_label):\n    xy_list = []\n    fname_id_dict = {}\n    for idx, row in df.iterrows():\n        fname_id_dict.update({row['file_name']: row['id']})\n    print('len(valid)=', len(fname_id_dict))\n    with open(json_label) as f:\n        jdata = json.load(f)\n        for dict in tqdm(jdata):\n            image_id = fname_id_dict[img_name]\n            if image_id == dict['image_id']:\n                # x_min, y_min, x_max, y_max = dict['bbox']\n                x, y, w, h = dict['bbox']\n                x_min, y_min, x_max, y_max = x, y, x + w, y + h\n                xy_list.append([int(x_min), int(y_min), int(x_max), int(y_max)])\n\n    return xy_list\n\n\ndef draw_rect(img, xy_list):\n    for xy in xy_list:\n        cv2.rectangle(img, (xy[0], xy[1]), (xy[2], xy[3]), (0, 0, 255), 2)\n\n\ndataset_path = '/kaggle/input/cowboyoutfits/images/'\ndf = pd.read_csv('/kaggle/input/cowboyoutfits/valid.csv')\nimg_name = df['file_name'].sample(1).tolist()[0]\njson_label = '/kaggle/working/answer.json'\n\nprint(img_name)\nimg = cv2.imread(os.path.join(dataset_path, img_name))\nprint(img.shape)  # (h,w,c)\n\nxy_list = get_xyxy_from_cowboy(img_name, df, json_label)\ndraw_rect(img, xy_list)\nplt.imshow(img)\n","metadata":{"execution":{"iopub.status.busy":"2021-07-26T08:54:18.615257Z","iopub.execute_input":"2021-07-26T08:54:18.615612Z","iopub.status.idle":"2021-07-26T08:54:19.001765Z","shell.execute_reply.started":"2021-07-26T08:54:18.615581Z","shell.execute_reply":"2021-07-26T08:54:19.0008Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!rm -rf mmdetection/","metadata":{"execution":{"iopub.status.busy":"2021-07-26T08:54:46.846036Z","iopub.execute_input":"2021-07-26T08:54:46.846399Z","iopub.status.idle":"2021-07-26T08:54:47.045024Z","shell.execute_reply.started":"2021-07-26T08:54:46.846367Z","shell.execute_reply":"2021-07-26T08:54:47.043884Z"},"trusted":true},"execution_count":null,"outputs":[]}]}