{"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":"# Notebooks used to build the Ensemble\n\n### Our Models:\n\n- File: `\"../input/submission-vbg/ds_tst_F1_noTH_noClean.csv\"`\n - Sergio's Effdet_d2 Fold1: [notebook_v1](https://www.kaggle.com/socom20/effdet-inference)\n [ckpts](https://www.kaggle.com/socom20/vinbigdata-effdet-d2-f0f2-ckpts)\n - CSV file, Old version: [dataset](https://www.kaggle.com/socom20/effdet-inference-old)\n - CSV file, New version: [dataset](https://www.kaggle.com/socom20/effdet-inference)\n\n\n- File: `\"../input/submission-vbg/ds_tst_F2_noTH_noClean.csv\"`\n - Sergio's first Effdet_d2 Fold2: [notebook_v1](https://www.kaggle.com/socom20/effdet-inference)\n [ckpts](https://www.kaggle.com/socom20/vinbigdata-effdet-d2-f0f2-ckpts)\n - CSV file, Old version: [dataset](https://www.kaggle.com/socom20/effdet-inference-old)\n - CSV file, New version: [dataset](https://www.kaggle.com/socom20/effdet-inference)\n\n\n- File: `\"../input/vbg-yolo-submission/Fold 1.csv\"`\n - Mohammed's YOLOv5: [notebook](https://www.kaggle.com/morizin/vinbigdata-yolo-inference)\n [ckpt](https://www.kaggle.com/morizin/resnet50d-096-stage-2)\n - CSV file, Old version: [dataset_v2](https://www.kaggle.com/morizin/vbg-yolo-submission)\n - CSV file, New version: [Fold_2_cleaned](https://www.kaggle.com/morizin/vinbigdata-yolo-inference/output?select=Fold_2_cleaned.csv)\n\n\n- File: `\"../input/vbg-yolo-submission/Fold 4.csv\"`\n - Mohammed's YOLOv5: [notebook](https://www.kaggle.com/morizin/vinbigdata-yolo-inference)\n [ckpt](https://www.kaggle.com/morizin/resnet50d-096-stage-2)\n - CSV file, Old version: [dataset_v2](https://www.kaggle.com/morizin/vbg-yolo-submission)\n - CSV file, New version: [Fold_5_cleaned](https://www.kaggle.com/morizin/vinbigdata-yolo-inference/output?select=Fold_5_cleaned.csv)\n \n\n- File: `\"../input/vbg-yolo-submission/submission (2).csv\"`\n - Mohammed's YOLOv5 TTA: [notebook](https://www.kaggle.com/morizin/vinbigdata-yolo-inference)\n [ckpt](https://www.kaggle.com/morizin/resnet50d-096-stage-2)\n - CSV file, Old version: [dataset_v2](https://www.kaggle.com/morizin/vbg-yolo-submission)\n - CSV file, New version: [Fold_5_TTA](https://www.kaggle.com/morizin/vinbigdata-yolo-inference/output?select=Fold_5_TTA.csv)\n\n\n- File: `\"../input/mohammedyolov5/submission.csv\"`\n - Mohammed's YOLOv5: [notebook_v2](https://www.kaggle.com/morizin/vinbigdata-cxr-ad-yolov5-14-class-infer-184dd1/data?scriptVersionId=57010094&select=submission.csv)\n [ckpt](https://www.kaggle.com/morizin/vinbigdata-cxr-ad-yolov5-14-class-train-4de71f?scriptVersionId=56346979)\n - CSV file: [datset_v1](https://www.kaggle.com/socom20/mohammedyolov5?select=submission.csv)\n \n \n\n### Public Kernels:\n\n- File: `\"../input/yolov5-chest-512/submission.csv\"`\n - nxhong93: [notebook v1](https://www.kaggle.com/nxhong93/yolov5-chest-512/data)\n\n\n- File: `\"../input/publickernel-vinbigdata-yolov5-16-class-version-1/submission.csv\"`\n - duythanhng: [notebook v1](https://www.kaggle.com/duythanhng/vinbigdata-yolov5-16-class/output?scriptVersionId=56314815)\n\n\n- File: `\"../input/public-kernel-vinbigdata-detectron2-prediction-v9/results/20210110_train_all_500k_512/submission_det.csv\"`\n - corochann: [notebook v9](https://www.kaggle.com/corochann/vinbigdata-detectron2-prediction?scriptVersionId=52564402)\n \n\n- File: `\"../input/vinbigdata-2-class-classifier-complete-pipeline/results/tmp_debug/test_pred.csv\"`\n - corochann: [notebook v13](https://www.kaggle.com/corochann/vinbigdata-2-class-classifier-complete-pipeline/output)\n\n","metadata":{}},{"cell_type":"markdown","source":"# Imports","metadata":{}},{"cell_type":"code","source":"!pip install -U ensemble-boxes","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os, sys\nfrom glob import glob\nimport copy\nimport shutil\n\nimport pandas as pd\nimport numpy as np\nimport matplotlib.pyplot as plt\n\nfrom tqdm import tqdm\nfrom ensemble_boxes import *","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Cleaning Functions","metadata":{}},{"cell_type":"code","source":"def solve_bbox_problems(bbox_v, scores_v, labels_v):\n    \"\"\" \n    Solves problems in the \"ensemble-boxes\" way \n    \"\"\"\n    \n    to_remove = np.zeros(bbox_v.shape[0], dtype=np.bool)\n    for i in range(bbox_v.shape[0]):\n        x1, y1, x2, y2 = bbox_v[i]\n        \n        if x2 < x1:\n#             warnings.warn('X2 < X1 value in box. Swap them.')\n            x1, x2 = x2, x1\n        if y2 < y1:\n#             warnings.warn('Y2 < Y1 value in box. Swap them.')\n            y1, y2 = y2, y1\n        if x1 < 0:\n#             warnings.warn('X1 < 0 in box. Set it to 0.')\n            x1 = 0\n        if x1 > 1:\n#             warnings.warn('X1 > 1 in box. Set it to 1. Check that you normalize boxes in [0, 1] range.')\n            x1 = 1\n        if x2 < 0:\n#             warnings.warn('X2 < 0 in box. Set it to 0.')\n            x2 = 0\n        if x2 > 1:\n#             warnings.warn('X2 > 1 in box. Set it to 1. Check that you normalize boxes in [0, 1] range.')\n            x2 = 1\n        if y1 < 0:\n# # #             warnings.warn('Y1 < 0 in box. Set it to 0.')\n            y1 = 0\n        if y1 > 1:\n# #             warnings.warn('Y1 > 1 in box. Set it to 1. Check that you normalize boxes in [0, 1] range.')\n            y1 = 1\n        if y2 < 0:\n#             warnings.warn('Y2 < 0 in box. Set it to 0.')\n            y2 = 0\n        if y2 > 1:\n#             warnings.warn('Y2 > 1 in box. Set it to 1. Check that you normalize boxes in [0, 1] range.')\n            y2 = 1\n        if (x2 - x1) * (y2 - y1) == 0.0:\n#             warnings.warn(\"Zero area box skipped: {}.\".format(box_part))\n            to_remove[i] = True\n    \n        bbox_v[i] = x1, y1, x2, y2\n    \n    if to_remove.sum() > 0:\n        # Hack to remove bboxes using min confidence th\n        bbox_v[to_remove] = np.array([0.0, 0.0, 1.0, 1.0])\n        scores_v[to_remove] = 0.0\n        \n    return bbox_v, scores_v, labels_v\n\n\ndef calc_iou(bb0, bb1):\n    if (len(bb0.shape) == 2):\n        bb0 = bb0.T\n        \n    if (len(bb1.shape) == 2):\n        bb1 = bb1.T\n        \n\n    bb0_x0, bb0_y0, bb0_x1, bb0_y1 = bb0\n    bb1_x0, bb1_y0, bb1_x1, bb1_y1 = bb1\n    \n    assert (bb0_x0 < bb0_x1).all()\n    assert (bb0_y0 < bb0_y1).all()\n    assert (bb1_x0 < bb1_x1).all()\n    assert (bb1_y0 < bb1_y1).all()\n\n    # determine the coordinates of the intersection rectangle\n    x_left   = np.maximum(bb0_x0, bb1_x0)\n    y_top    = np.maximum(bb0_y0, bb1_y0)\n    x_right  = np.minimum(bb0_x1, bb1_x1)\n    y_bottom = np.minimum(bb0_y1, bb1_y1)\n\n#     if (x_right < x_left).all(axis=0) or (y_bottom < y_top).all(axis=0):\n#         return np.zeros( out_dim )\n    \n    ret_mask = ~( (x_right < x_left) + (y_bottom < y_top) )\n\n    # The intersection of two axis-aligned bounding boxes is always an\n    # axis-aligned bounding box\n    intersection_area = (x_right - x_left) * (y_bottom - y_top)\n\n    # compute the area of both AABBs\n    bb0_area = (bb0_x1 - bb0_x0) * (bb0_y1 - bb0_y0)\n    bb1_area = (bb1_x1 - bb1_x0) * (bb1_y1 - bb1_y0)\n    \n    iou = intersection_area / (bb0_area + bb1_area - intersection_area)\n    \n    \n    return iou * ret_mask\n\n\ndef merge_preds(bbox_v, p_det_v=None, mode='p_det_weight'):\n    \n    if p_det_v is None:\n        p_det_v = np.ones(bbox_v.shape[0])\n        \n    if mode == 'p_det_weight' or mode == 'p_det_weight_pmean':\n        typed_p_det_v = p_det_v.astype(bbox_v.dtype)\n        p_v = ( typed_p_det_v / typed_p_det_v.sum() )[:,None]\n        \n        bbox = (bbox_v * p_v).sum(axis=0)\n        p = p_det_v.mean()\n    \n    elif mode == 'p_det_weight_psum':\n        typed_p_det_v = p_det_v.astype(bbox_v.dtype)\n        p_v = ( typed_p_det_v / typed_p_det_v.sum() )[:,None]\n        \n        bbox = (bbox_v * p_v).sum(axis=0)\n        p = p_det_v.sum()\n    \n    elif mode == 'median' or mode == 'median_pmean':\n        bbox = np.median(bbox_v, axis=0)\n        p = p_det_v.mean()\n\n    elif mode == 'p_det_max':\n        i_max = p_det_v.argmax()\n        \n        bbox = bbox_v[i_max]\n        p    = p_det_v[i_max]\n    \n    elif mode == 'random':\n        i_max = np.random.randint(0, p_det_v.shape[0])\n        \n        bbox = bbox_v[i_max]\n        p    = p_det_v[i_max]\n        \n    else:\n        raise Exception(f'Unknown mode \"{mode}\"')\n        \n        \n    return bbox, p\n    \n\ndef clean_predictions(preds_v, iou_th=0.1, mode='p_det_weight', consensus_level=1, n_models2ensemble=1):\n    ret_preds_v = []\n    for pred_d in preds_v:\n        \n        cls_v = pred_d['cls']\n        \n        if 'bbox' in pred_d.keys():\n            bbox_key = 'bbox'\n        else:\n            bbox_key = 'bboxes'\n            \n        bbox_v = pred_d[bbox_key]\n        \n        if 'p_det' in pred_d.keys():\n            ret_p_det = True\n            p_det_v = pred_d['p_det']\n        else:\n            ret_p_det = False\n            p_det_v = np.ones(pred_d['cls'].shape)\n        \n        \n        if 'rad_id' in pred_d.keys():\n            ret_rad_id = True\n            rad_id_v = pred_d['rad_id']\n        else:\n            ret_rad_id = False\n\n\n        if 'model_id' in pred_d.keys():\n            model_id_v = pred_d['model_id']\n        else:\n            model_id_v = np.zeros(pred_d['cls'].shape, dtype=np.int)\n            \n            \n        new_cls_v = []\n        new_bbox_v = []\n        new_p_det_v = []\n        new_rad_id_v = []\n        for i_c in np.unique(cls_v):\n            f_c = (cls_v == i_c)\n            \n            n_c = f_c.sum()\n            if n_c == 1:\n                if consensus_level > 1 and i_c != -1:\n                    continue\n                    \n                    \n                if ret_rad_id:\n                    if i_c == -1:\n                        n_rads = rad_id_v.size\n                        \n                        if n_rads < consensus_level:\n                            continue\n                            \n                        else:\n                            if n_rads > 1:\n                                new_rad_id_v.append( np.concatenate(rad_id_v, axis=-1) )\n                            else:\n                                new_rad_id_v.append( rad_id_v[f_c][0] )\n                    else:\n                        new_rad_id_v.append( rad_id_v[f_c][0] )\n                    \n\n                new_cls_v.append( i_c )\n                new_bbox_v.append( bbox_v[f_c][0] )\n                new_p_det_v.append( p_det_v[f_c][0] )\n                \n                \n                \n            else:\n                f_cls_v = cls_v[f_c]\n                f_bbox_v = bbox_v[f_c]\n                f_p_det_v = p_det_v[f_c]\n                f_model_id_v = model_id_v[f_c]\n\n                if ret_rad_id:\n                    f_rad_id_v = rad_id_v[f_c]\n                    \n                to_join_idxs_v = []\n                for i in range(0, n_c):\n                    idxs_s = set( np.argwhere( calc_iou(f_bbox_v[i], f_bbox_v) > iou_th ).T[0] )\n                    \n#                     print(idxs_s)\n                    for i in range(len(to_join_idxs_v)):\n                        if len( idxs_s.intersection(to_join_idxs_v[i]) ) > 0:\n                            to_join_idxs_v[i] = to_join_idxs_v[i].union(idxs_s)\n                            break\n                            \n                    else:\n                        to_join_idxs_v.append(idxs_s)\n                    \n                for to_join_idxs in to_join_idxs_v:\n                    to_join_idxs = list(to_join_idxs)\n                    \n                    if len(to_join_idxs) < consensus_level:\n                        continue\n                        \n                    bbox, p_det = merge_preds(\n                        f_bbox_v[to_join_idxs],\n                        f_p_det_v[to_join_idxs],\n                        mode=mode,\n                    )\n\n                    if n_models2ensemble > 1:\n                        ens_prop = len( np.unique(f_model_id_v[to_join_idxs]) ) / n_models2ensemble\n                        p_det = p_det * ens_prop\n                        \n                    new_cls_v.append( i_c )\n                    new_bbox_v.append( bbox )\n                    new_p_det_v.append( p_det )\n                    \n                    if ret_rad_id:\n                        new_rad_id_v.append( np.concatenate(f_rad_id_v[to_join_idxs], axis=-1))\n        \n        ret_preds_d = {\n            'cls': np.array(new_cls_v),\n            bbox_key: np.array(new_bbox_v),\n        }\n        \n        if ret_p_det:\n            ret_preds_d['p_det'] = np.array(new_p_det_v)\n            \n        if ret_rad_id:\n            ret_preds_d['rad_id'] = np.array(new_rad_id_v, dtype=object)\n            \n        for k in pred_d.keys():\n            if k not in ['cls', bbox_key, 'p_det', 'rad_id']:\n                ret_preds_d[k] = pred_d[k]\n        \n        ret_preds_v.append(ret_preds_d)\n    \n    return ret_preds_v\n\n\n    \ndef pred_to_str(pred_d):\n    cls_v = pred_d['cls']\n    bbox_v = pred_d['bbox']\n    p_det_v = pred_d['p_det']\n    \n    if len([c for c in cls_v if c <= 14]) == 0:\n        ret_s = '14 1 0 0 1 1'\n    \n    else:\n        s_v = []\n        for cls, p_det, bbox in zip(cls_v.astype(np.int), p_det_v, np.round(bbox_v).astype(np.int)):\n            if cls == 14:\n                bbox = np.array([0,0,1,1])\n            \n            if cls > 14:\n                continue\n                \n            s = '{} {:0.05} {} {} {} {}'.format(\n                int(cls),\n                p_det,\n                *bbox\n            )\n            \n            s_v.append(s)\n            \n        ret_s = ' '.join(s_v)\n    \n    return ret_s\n\n\ndef read_prediction_csv(\n    filename='./ds_tst_F0_V6_JustCLS0_1.25x.csv',\n    skip_cls14=False,\n):\n    sub_df = pd.read_csv(filename)\n    \n    preds_v = []\n    for sample_id, preds in sub_df.values:\n        preds_split = preds.split()\n\n        pred_d = {\n            'sample_id': sample_id,\n            'cls':    [],\n            'bbox': [],\n            'p_det':  [],\n            }\n\n\n        for i in range(0, len(preds_split), 6):\n            cls, p_det, x_min, y_min, x_max, y_max = [float(x) for x in preds_split[i:i+6]]\n            cls = int(cls)\n            \n            if (not skip_cls14) or (cls != 14):\n                \n                if cls != 14:\n                    bboxes = np.array([x_min, y_min, x_max, y_max])\n                    \n                else:\n                    bboxes = np.array([0, 0, 1, 1])\n                \n                pred_d['cls'].append(cls)\n                pred_d['bbox'].append(bboxes)\n                pred_d['p_det'].append(p_det)\n\n        pred_d['cls']    = np.array( pred_d['cls'] )\n        pred_d['bbox']   = np.array( pred_d['bbox'] )\n        pred_d['p_det']  = np.array(pred_d['p_det'] )\n        \n        preds_v.append(pred_d)\n        \n    return preds_v\n\n\ndef predictions_to_df(\n    preds_v,\n    save_path=None,\n):\n    pred_summary_d = {\n        'image_id':[],\n        'PredictionString':[]\n    }\n    \n    for pred_d in preds_v:\n        pred_str = pred_to_str(pred_d)\n        pred_summary_d['image_id'].append( pred_d['sample_id'] )\n        pred_summary_d['PredictionString'].append( pred_str )\n        \n    pred_summary_df = pd.DataFrame(pred_summary_d)\n    \n    if save_path is not None:\n        pred_summary_df.to_csv(\n            save_path,\n            index=None)\n        \n        print(f' Saved submission: \"{save_path}\"')\n        \n    return pred_summary_df\n\n\ndef norm_p_det(pred_v):\n    p_det_v = []\n    for pred_d in pred_v:\n        if len(pred_d['p_det']) > 0:\n            p_det_v.append( pred_d['p_det'] )\n    \n    p_det_v = np.concatenate(p_det_v)\n    p_det_max = p_det_v.max()\n    \n    \n    print('p_det_max =', p_det_max)\n    if p_det_max > 1.0:\n        ret_pred_v = copy.deepcopy(pred_v)\n        for pred_d in ret_pred_v:\n            if len(pred_d['p_det']) > 0:\n                pred_d['p_det'] = pred_d['p_det'] / p_det_max\n    \n    else:\n        print('skipping norm_p_det')\n        \n        return pred_v\n        \n    return ret_pred_v\n\n\ndef fix_boxes(preds_v):\n    \"\"\"\n    Fixes:\n    - p_det > 1.0 or p_det < 0.0\n    - xmax - xmin > 0\n    - ymax - ymin > 0\n\n    \"\"\"\n    for preds_d in preds_v:\n        if len(preds_d['cls']) > 0:\n            dx_dy = preds_d['bbox'][:,2:] - preds_d['bbox'][:,:2]\n            \n            f0 = (dx_dy <= 1).any(axis=-1)\n            f1 = (preds_d['p_det']<=0) + (preds_d['p_det']>1.0)\n            \n            if f0.any() or f1.any():\n                print('.', end='')\n                f = ~(f0 + f1)\n                for k in ['p_det', 'bbox', 'cls']:\n                    preds_d[k] = preds_d[k][f]\n                    \n    return None\n\n\ndef add_class_14(\n    preds_v,\n    pred_clf_c14_filename='2-cls test pred.csv',\n    low_threshold=0.00,\n    high_threshold=0.99,\n    rm_preds_high_th=True,\n    inv_p_cls=True,\n    ):\n\n    cls_df = pd.read_csv(pred_clf_c14_filename)\n\n    class_14_d = {}\n    for sample_id, p_cls in cls_df.values[:,:2]:\n        if inv_p_cls:\n            p_14 = 1.0 - p_cls\n        else:\n            p_14 = p_cls\n\n        if p_14 < low_threshold:\n            # Keep, do nothing.\n            class_14_d[sample_id] = 0.0\n\n        elif p_14 >= high_threshold:\n            # Replace, remove all \"det\" preds.\n            class_14_d[sample_id] = 1.0\n\n        else:\n            # Add, keep \"det\" preds and add normal pred.\n            class_14_d[sample_id] = p_14\n            \n    \n    \n    ret_preds_v = copy.deepcopy(preds_v)\n                                \n    for pred_d in tqdm(ret_preds_v):\n        default_case = False\n        p_14 = class_14_d[ pred_d['sample_id'] ]\n\n        if p_14 == 1:\n            if rm_preds_high_th:\n                pred_d['bbox']  = np.array([[0.0, 0.0, 1.0, 1.0]])\n                pred_d['cls']   = np.array([14])\n                pred_d['p_det'] = np.array([1.0])\n                \n            else:\n                default_case = True\n\n        elif p_14 == 0.0:\n            continue\n\n        else:\n            default_case = True\n            \n        if default_case:\n            if len(pred_d['bbox']) > 0 and 14 not in pred_d['cls']:\n                pred_d['bbox'] = np.append(pred_d['bbox'], np.array([[0.0, 0.0, 1.0, 1.0]]), axis=0)\n                pred_d['cls']  = np.append(pred_d['cls'], 14)\n                pred_d['p_det'] = np.append(pred_d['p_det'], p_14)\n\n            else:\n                pred_d['bbox'] = np.array([[0, 0, 1, 1]])\n                pred_d['cls']  = np.array([14], dtype=np.int)\n                pred_d['p_det'] = np.array([p_14])\n    \n    return ret_preds_v","metadata":{"_kg_hide-input":true,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Reading Inputs","metadata":{}},{"cell_type":"code","source":"# Reading original image shapes\nheight_dict = pd.read_csv('../input/vinbigdata-original-image-dataset/vinbigdata/test.csv').to_dict('records')\nfnl_dict ={}\nfor ix,i in enumerate(height_dict):\n    fnl_dict[i['image_id']] = [i['width'],i['height'],i['width'],i['height']]","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Reading all the predictions\n\nsubs = [\n    pd.read_csv('../input/effdet-inference/ds_tst_F2_noTH_noClean.csv'),\n    pd.read_csv('../input/vbg-yolo-submission/Fold 1.csv'),\n    pd.read_csv('../input/public-kernel-vinbigdata-detectron2-prediction-v9/results/20210110_train_all_500k_512/submission_det.csv'),    \n    pd.read_csv('../input/effdet-inference/ds_tst_F1_noTH_noClean.csv'),\n    pd.read_csv('../input/vbg-yolo-submission/Fold 4.csv'),\n    pd.read_csv('../input/vbg-yolo-submission/submission (2).csv'),\n    pd.read_csv('../input/yolov5-chest-512/submission.csv'),\n    pd.read_csv('../input/yolov5-chest-512/submission.csv'),\n    pd.read_csv('../input/publickernel-vinbigdata-yolov5-16-class-version-1/submission.csv'),\n    pd.read_csv('../input/mohammedyolov5/submission.csv')\n]\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def submission_decoder(df:pd.DataFrame) -> np.ndarray:\n    info = df.values\n    df_lst = []\n    for i in info:\n        pre_lst = i[1].split(' ')\n        for j in range(0,len(pre_lst),6):\n            df_lst.append([i[0],int(pre_lst[j]),float(pre_lst[j+1]),int(pre_lst[j+2]),int(pre_lst[j+3]),\\\n                           int(pre_lst[j+4]),int(pre_lst[j+5]),fnl_dict.get(i[0])[0],fnl_dict.get(i[0])[1]])\n            \n    return pd.DataFrame(df_lst,columns = ['image_id','class_id','score','x_min','y_min','x_max','y_max','width','height'])","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"subs = [submission_decoder(subs[i]) for i in range(len(subs))]","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Ensembling","metadata":{}},{"cell_type":"code","source":"boxes_dict = {}\nscores_dict = {}\nlabels_dict = {}\nwhwh_dict = {}\n\nfor i in tqdm(subs[0].image_id.unique()):\n    if not i in boxes_dict.keys():\n        boxes_dict[i] = []\n        scores_dict[i] = []\n        labels_dict[i] = []\n        whwh_dict[i] = []\n\n    size_ratio = fnl_dict.get(i)\n    whwh_dict[i].append(size_ratio) \n    tmp_df = [subs[x][subs[x]['image_id']==i] for x in range(len(subs))]\n    \n    for x in range(len(tmp_df)):\n        bbox_v = ((tmp_df[x][['x_min','y_min','x_max','y_max']].values)/size_ratio)\n        scores_v = tmp_df[x]['score'].values\n        labels_v = tmp_df[x]['class_id'].values\n        \n        bbox_v, scores_v, labels_v = solve_bbox_problems(bbox_v, scores_v, labels_v)\n        \n        boxes_dict[i].append(bbox_v.tolist())\n        scores_dict[i].append(scores_v.tolist())\n        labels_dict[i].append(labels_v.tolist())\n            ","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"weights  = [3,2,3,3,2,4,4,4,4,3]\nweights1 = [3,2,4,5]\n\niou_thr = 0.25\nskip_box_thr = 0.01\nsigma = 0.1\n\nfnl = {}\n\nfor i in tqdm(boxes_dict.keys()):\n    # First Ensemble using: WBF, NMS, SoftNMS, NMW (10 models)\n    boxes3, scores3, labels3 = weighted_boxes_fusion(boxes_dict[i], scores_dict[i], labels_dict[i],\\\n                                                     weights=weights, iou_thr=iou_thr, skip_box_thr=skip_box_thr)\n    \n    boxes1, scores1, labels1 = nms(boxes_dict[i], scores_dict[i], labels_dict[i], weights=weights, iou_thr=iou_thr)\n    \n    boxes0, scores0, labels0 = soft_nms(boxes_dict[i], scores_dict[i], labels_dict[i], weights=weights,\\\n                                        iou_thr=iou_thr, sigma=sigma, thresh=skip_box_thr)\n    \n    boxes2, scores2, labels2 = non_maximum_weighted(boxes_dict[i], scores_dict[i], labels_dict[i],\\\n                                                    weights=weights, iou_thr=iou_thr, skip_box_thr=skip_box_thr)\n    \n    # Final Ensemble using: WBF (4 previous ensembles)\n    boxes, scores, labels = weighted_boxes_fusion([boxes0,boxes1,boxes2,boxes3],\\\n                                                  [scores0,scores1,scores2,scores3],\\\n                                                  [labels0,labels1,labels2,labels3],\\\n                                                  weights=weights1, iou_thr=iou_thr, skip_box_thr=skip_box_thr)\n    \n    if not i in fnl.keys():\n        fnl[i] = {'boxes':[],'scores':[],'labels':[]}\n        \n    fnl[i]['boxes'] = boxes*whwh_dict[i]\n    fnl[i]['scores'] = scores\n    fnl[i]['labels'] = labels","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"pd_form = []\nfor i in fnl.keys():\n    b = fnl[i]\n    for j in range(len(b['boxes'])):\n        pd_form.append([i,int(b['labels'][j]),round(b['scores'][j],2),\\\n                        int(b['boxes'][j][0]),int(b['boxes'][j][1]),\\\n                        int(b['boxes'][j][2]),int(b['boxes'][j][3])])\n        \nfinal_df = pd.DataFrame(pd_form,columns = ['image_id','class_id','score','x_min','y_min','x_max','y_max'])\nfinal_df = final_df.drop_duplicates(keep = 'first')","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def submission_encoder(df:pd.DataFrame) -> np.ndarray:\n    dct = {}\n    for i in tqdm(df['image_id'].unique()):\n        if not i in dct.keys():\n            dct[i] = []\n        tmp = df[df['image_id'] == i].values\n        for j in tmp:\n            dct[i].append(int(j[1]))\n            dct[i].append(float(j[2]))\n            dct[i].append(int(j[3]))\n            dct[i].append(int(j[4]))\n            dct[i].append(int(j[5]))\n            dct[i].append(int(j[6]))\n        \n        dct[i] = map(str,dct[i])\n        dct[i] = ' '.join(dct[i])\n    dct = [[k, v] for k, v in dct.items()]\n    return pd.DataFrame(dct,columns = ['image_id','PredictionString']).reset_index(drop = True)\n\ndf = submission_encoder(final_df)\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df.to_csv('submission_wo_cls2f.csv', index=False)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Final cleaning + 2 cls filtering","metadata":{}},{"cell_type":"code","source":"# Using filter from:\n# https://www.kaggle.com/corochann/vinbigdata-2-class-classifier-complete-pipeline/output#VinBigData-2-class-classifier-complete-pipeline\n# notebook Version 13\n\npreds_v = read_prediction_csv(\n    \"submission_wo_cls2f.csv\",\n    skip_cls14=False,\n)\n\n# Fixing:\n#     - p_det > 1.0 or p_det < 0.0\n#     - xmax - xmin > 0\n#     - ymax - ymin > 0\n\nfix_boxes(preds_v)\n\nclean_pred_v = clean_predictions(\n    preds_v,\n    iou_th=0.25,\n    mode='p_det_weight_psum') #p_det_max , p_det_weight, p_det_weight_psum\n\n\n# Fixing p_det > 1.0\npred_v = norm_p_det(clean_pred_v)\n\n\n# # Adding class 14\npred_v = add_class_14(\n    pred_v,\n    pred_clf_c14_filename='../input/vinbigdata-2-class-classifier-complete-pipeline/results/tmp_debug/test_pred.csv',\n    low_threshold=0.00,\n    high_threshold=0.999,\n    rm_preds_high_th=False,\n    inv_p_cls=False,\n)\n\n# Saving submission\n\npreds_df = predictions_to_df(\n    pred_v,\n    f'ds_tst_Ens_pmax_w_2clsf_corochann.csv')\n\npreds_df","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}