{"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":"# Stater kit\n\nThis notebook provides the basics of 1) how to handle the data, 2) good practices and pitfalls to avoid, 3) how to generate the submission file for codalab","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19"}},{"cell_type":"code","source":"%%capture\n!pip install pycocotools\n!pip install mxnet-cu110 autogluon.vision\n!pip install -U gluoncv==0.10.3.post0","metadata":{"execution":{"iopub.status.busy":"2021-07-16T00:45:00.181824Z","iopub.execute_input":"2021-07-16T00:45:00.182113Z","iopub.status.idle":"2021-07-16T00:46:51.054209Z","shell.execute_reply.started":"2021-07-16T00:45:00.182040Z","shell.execute_reply":"2021-07-16T00:46:51.052904Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\nimport logging\nimport sys\nimport os\nimport json  # for dumping json serialized results\nimport zipfile  # for creating submission zip file\nfrom pycocotools.coco import COCO\nroot = '../input/cowboyoutfits'\nlogger = logging.getLogger()\nlogger.addHandler(logging.StreamHandler(sys.stderr))","metadata":{"execution":{"iopub.status.busy":"2021-07-16T00:46:51.058629Z","iopub.execute_input":"2021-07-16T00:46:51.058966Z","iopub.status.idle":"2021-07-16T00:46:51.074166Z","shell.execute_reply.started":"2021-07-16T00:46:51.058929Z","shell.execute_reply":"2021-07-16T00:46:51.073339Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Load the training data","metadata":{}},{"cell_type":"code","source":"coco = COCO(os.path.join(root, 'train.json'))","metadata":{"execution":{"iopub.status.busy":"2021-07-16T00:46:51.077648Z","iopub.execute_input":"2021-07-16T00:46:51.077995Z","iopub.status.idle":"2021-07-16T00:46:51.265997Z","shell.execute_reply.started":"2021-07-16T00:46:51.077969Z","shell.execute_reply":"2021-07-16T00:46:51.265046Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Dataset info and categories","metadata":{}},{"cell_type":"code","source":"print('Data info:', coco.info())\ncategories = {cat_info['name']:cat_info['id'] for cat_info in coco.loadCats(coco.getCatIds())}\nprint('Categories:', categories)","metadata":{"execution":{"iopub.status.busy":"2021-07-16T00:46:51.268681Z","iopub.execute_input":"2021-07-16T00:46:51.269078Z","iopub.status.idle":"2021-07-16T00:46:51.275851Z","shell.execute_reply.started":"2021-07-16T00:46:51.269037Z","shell.execute_reply":"2021-07-16T00:46:51.274905Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Example training module using AutoGluon","metadata":{}},{"cell_type":"code","source":"from autogluon.vision import ObjectDetector","metadata":{"execution":{"iopub.status.busy":"2021-07-16T00:46:51.276979Z","iopub.execute_input":"2021-07-16T00:46:51.277390Z","iopub.status.idle":"2021-07-16T00:46:56.685575Z","shell.execute_reply.started":"2021-07-16T00:46:51.277350Z","shell.execute_reply":"2021-07-16T00:46:56.684754Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train = ObjectDetector.Dataset.from_coco(os.path.join(root, 'train.json'), root=os.path.join(root, 'images'))\ntrain","metadata":{"execution":{"iopub.status.busy":"2021-07-16T00:46:56.686756Z","iopub.execute_input":"2021-07-16T00:46:56.687126Z","iopub.status.idle":"2021-07-16T00:47:02.758313Z","shell.execute_reply.started":"2021-07-16T00:46:56.687090Z","shell.execute_reply":"2021-07-16T00:47:02.757428Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train.show_images()","metadata":{"execution":{"iopub.status.busy":"2021-07-16T00:49:11.441484Z","iopub.execute_input":"2021-07-16T00:49:11.441839Z","iopub.status.idle":"2021-07-16T00:49:20.831088Z","shell.execute_reply.started":"2021-07-16T00:49:11.441807Z","shell.execute_reply":"2021-07-16T00:49:20.830086Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Split train/valid data with cautious\n\nSince the distribution of categories is very imbalanced, we should carefully split the data by category, to make sure we have enough sample for evaluation. ","metadata":{}},{"cell_type":"code","source":"# randomly select 10 images for each category as valid_data\nsample_n_per_cat = 10\nvalid_ids = pd.Int64Index([])\nfor cat_name in categories.keys():\n    df = train[train.apply(lambda x: True if any([y['class'] == cat_name for y in x['rois']]) else False, axis=1)]\n    df = df.sample(sample_n_per_cat)\n    valid_ids = valid_ids.append(df.index)\ntrain_ids = train.index\ntrain_ids = train_ids.drop(valid_ids)\ntrain_data = train.loc[train_ids]\nvalid_data = train.loc[valid_ids]\nprint('train split:', len(train_data), 'valid split', len(valid_data))","metadata":{"execution":{"iopub.status.busy":"2021-07-16T00:49:35.331554Z","iopub.execute_input":"2021-07-16T00:49:35.331918Z","iopub.status.idle":"2021-07-16T00:49:35.514007Z","shell.execute_reply.started":"2021-07-16T00:49:35.331888Z","shell.execute_reply":"2021-07-16T00:49:35.513019Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Training stater code\n\nWe provide  a fundamental training example using autogluon.vision package with default settings. In order to achieve higher scores, there are multiple details you need to take care:\n\n- Imbalanced training sample: consider that the training samples for e.g. belt is very rare, you can try methods like class aware sampling to inflate the rare classes\n- The training data might contain noises in anotations, there are many custom losses to handle this issue\n- others?","metadata":{}},{"cell_type":"code","source":"detector = ObjectDetector(verbosity=2).fit(train_data, valid_data, hyperparameters={'batch_size': 8, 'epochs': 3, 'transfer': 'ssd_512_resnet50_v1_coco'})","metadata":{"execution":{"iopub.status.busy":"2021-07-16T01:25:07.757512Z","iopub.execute_input":"2021-07-16T01:25:07.757955Z","iopub.status.idle":"2021-07-16T02:19:55.573412Z","shell.execute_reply.started":"2021-07-16T01:25:07.757913Z","shell.execute_reply":"2021-07-16T02:19:55.571333Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Generate submission\n\nYou will use `valid.csv` for public phase submission, and `test.csv` for the final phase submission. Note that you only have 3 chance to submit for the final phase so be careful not to submit wrong results on the last day","metadata":{}},{"cell_type":"code","source":"from PIL import Image\ndef create_submission(df, detector, score_thresh=0.1):\n    results = []\n    for index, row in df.iterrows():\n        img_id = row['id']\n        file_name = row['file_name']\n        img = Image.open(file_name)\n        width, height = img.size\n        output = detector.predict(file_name)\n        for _, p in output.iterrows():\n            if p['predict_score'] > score_thresh:\n                roi = p['predict_rois']\n                pred = {'image_id': img_id,\n                        'category_id': categories[p['predict_class']],\n                        'bbox': [roi['xmin'] * width, roi['ymin'] * height, roi['xmax'] * width, roi['ymax'] * height],\n                        'score': p['predict_score']}\n                results.append(pred)\n    return results","metadata":{"execution":{"iopub.status.busy":"2021-07-16T02:30:04.286190Z","iopub.execute_input":"2021-07-16T02:30:04.286555Z","iopub.status.idle":"2021-07-16T02:30:04.295067Z","shell.execute_reply.started":"2021-07-16T02:30:04.286520Z","shell.execute_reply":"2021-07-16T02:30:04.293851Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission_df = pd.read_csv(os.path.join(root, 'valid.csv'))  # replace with test.csv on the last day\nsubmission_df['file_name'] = submission_df.apply(lambda x: os.path.join(root, 'images', x['file_name']), axis=1)\nsubmission = create_submission(submission_df, detector)","metadata":{"execution":{"iopub.status.busy":"2021-07-16T02:30:05.232064Z","iopub.execute_input":"2021-07-16T02:30:05.232387Z","iopub.status.idle":"2021-07-16T02:35:09.313109Z","shell.execute_reply.started":"2021-07-16T02:30:05.232356Z","shell.execute_reply":"2021-07-16T02:35:09.312077Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# create json and zip\nsubmission_name = '/kaggle/working/answer.json'\nwith open(submission_name, 'w') as f:\n    json.dump(submission, f)\nzf = zipfile.ZipFile('/kaggle/working/sample_answer.zip', 'w')\nzf.write(submission_name, 'answer.json')\nzf.close()","metadata":{"execution":{"iopub.status.busy":"2021-07-16T02:35:31.386816Z","iopub.execute_input":"2021-07-16T02:35:31.387159Z","iopub.status.idle":"2021-07-16T02:35:32.956834Z","shell.execute_reply.started":"2021-07-16T02:35:31.387128Z","shell.execute_reply":"2021-07-16T02:35:32.955791Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Submit to codalab competition to get the evaluation score\n\nhttps://competitions.codalab.org/competitions/33573#participate-submit_results\n\nYou have to submit the your solution file together with the file submission to win the awards!","metadata":{}},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}