{"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":"# Install Packages","metadata":{}},{"cell_type":"code","source":"!conda install '/kaggle/input/pydicom-conda-helper/libjpeg-turbo-2.1.0-h7f98852_0.tar.bz2' -c conda-forge -y\n!conda install '/kaggle/input/pydicom-conda-helper/libgcc-ng-9.3.0-h2828fa1_19.tar.bz2' -c conda-forge -y\n!conda install '/kaggle/input/pydicom-conda-helper/gdcm-2.8.9-py37h500ead1_1.tar.bz2' -c conda-forge -y\n!conda install '/kaggle/input/pydicom-conda-helper/conda-4.10.1-py37h89c1867_0.tar.bz2' -c conda-forge -y\n!conda install '/kaggle/input/pydicom-conda-helper/certifi-2020.12.5-py37h89c1867_1.tar.bz2' -c conda-forge -y\n!conda install '/kaggle/input/pydicom-conda-helper/openssl-1.1.1k-h7f98852_0.tar.bz2' -c conda-forge -y","metadata":{"_kg_hide-output":true,"_kg_hide-input":true,"execution":{"iopub.status.busy":"2021-08-01T07:27:48.630527Z","iopub.execute_input":"2021-08-01T07:27:48.630943Z","iopub.status.idle":"2021-08-01T07:28:59.939891Z","shell.execute_reply.started":"2021-08-01T07:27:48.63086Z","shell.execute_reply":"2021-08-01T07:28:59.938971Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!pip install /kaggle/input/kerasapplications -q\n!pip install /kaggle/input/efficientnet-keras-source-code/ -q --no-deps","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2021-08-01T07:28:59.941682Z","iopub.execute_input":"2021-08-01T07:28:59.942029Z","iopub.status.idle":"2021-08-01T07:29:51.183123Z","shell.execute_reply.started":"2021-08-01T07:28:59.941991Z","shell.execute_reply":"2021-08-01T07:29:51.181953Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Import Libraries","metadata":{}},{"cell_type":"code","source":"import gc\nimport os\nimport sys\nimport shutil\nfrom copy import deepcopy\n\nfrom PIL import Image\nimport pandas as pd\nimport numpy as np\nfrom glob import glob\nfrom tqdm import tqdm\n\nimport pydicom\nfrom pydicom.pixel_data_handlers.util import apply_voi_lut\n\nimport efficientnet.tfkeras as efn\nimport tensorflow as tf\nfrom tensorflow.keras import backend as K \nimport tensorflow_hub as tfhub\n\nimport torch\n\nfrom numba import cuda\n\nimport matplotlib.pyplot as plt\nimport seaborn as sns","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","_kg_hide-input":true,"execution":{"iopub.status.busy":"2021-08-01T07:29:58.955786Z","iopub.execute_input":"2021-08-01T07:29:58.956161Z","iopub.status.idle":"2021-08-01T07:30:05.949855Z","shell.execute_reply.started":"2021-08-01T07:29:58.95612Z","shell.execute_reply":"2021-08-01T07:30:05.948984Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sys.path.append('/kaggle/input/weightedboxesfusion')","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2021-08-01T07:30:05.952286Z","iopub.execute_input":"2021-08-01T07:30:05.952662Z","iopub.status.idle":"2021-08-01T07:30:05.957057Z","shell.execute_reply.started":"2021-08-01T07:30:05.952614Z","shell.execute_reply":"2021-08-01T07:30:05.956166Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from ensemble_boxes import weighted_boxes_fusion, non_maximum_weighted, nms, soft_nms","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2021-08-01T07:30:05.959137Z","iopub.execute_input":"2021-08-01T07:30:05.959636Z","iopub.status.idle":"2021-08-01T07:30:05.999449Z","shell.execute_reply.started":"2021-08-01T07:30:05.959601Z","shell.execute_reply":"2021-08-01T07:30:05.99876Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Load Data","metadata":{}},{"cell_type":"code","source":"def read_prediction_csv(sub_df: pd.DataFrame):\n    preds_v = []\n    for image_id, preds in zip(sub_df['id'].values, sub_df['PredictionString'].values):\n        _cls, bbox, _p_det = [], [], []\n\n        preds_split = preds.split()\n        for i in range(0, len(preds_split), 6):\n            p_det, x_min, y_min, x_max, y_max = [float(x) for x in preds_split[i + 1:i + 6]]\n\n            if preds_split[i] != 'none':\n                bboxes = np.array([x_min, y_min, x_max, y_max])\n                _cls.append(1)\n                bbox.append(bboxes)\n                _p_det.append(p_det)\n\n        preds_v.append(\n            {\n                'sample_id': image_id,\n                'cls': np.array(_cls),\n                'bbox': np.array(bbox),\n                'p_det': np.array(_p_det),\n            }\n        )\n\n        del _cls, bbox, p_det\n\n    gc.collect()\n\n    return preds_v","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2021-08-01T07:30:06.000844Z","iopub.execute_input":"2021-08-01T07:30:06.001181Z","iopub.status.idle":"2021-08-01T07:30:06.009181Z","shell.execute_reply.started":"2021-08-01T07:30:06.001138Z","shell.execute_reply":"2021-08-01T07:30:06.008168Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df = pd.read_csv('/kaggle/input/siim-covid19-detection/sample_submission.csv')\n\nif df.shape[0] == 2477:\n    fast_sub = True\n    fast_df = pd.DataFrame(\n        (\n            [\n                ['00086460a852_study', 'negative 1 0 0 1 1'], \n                ['000c9c05fd14_study', 'negative 1 0 0 1 1'], \n                ['65761e66de9f_image', 'none 1 0 0 1 1'], \n                ['51759b5579bc_image', 'none 1 0 0 1 1']\n            ]\n        ), \n        columns=['id', 'PredictionString']\n    )\nelse:\n    fast_sub = False","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2021-08-01T07:30:06.010431Z","iopub.execute_input":"2021-08-01T07:30:06.01101Z","iopub.status.idle":"2021-08-01T07:30:06.035746Z","shell.execute_reply.started":"2021-08-01T07:30:06.010974Z","shell.execute_reply":"2021-08-01T07:30:06.035015Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## .dcm to .png","metadata":{}},{"cell_type":"code","source":"def read_xray(path, voi_lut: bool = True, fix_monochrome: bool = True):\n    dicom = pydicom.read_file(path)\n\n    if voi_lut:\n        data = apply_voi_lut(dicom.pixel_array, dicom)\n    else:\n        data = dicom.pixel_array\n\n    if fix_monochrome and dicom.PhotometricInterpretation == 'MONOCHROME1':\n        data = np.amax(data) - data\n\n    data = data - np.min(data)\n    data = data / np.max(data)\n    data = (data * 255).astype(np.uint8)\n\n    return data\n\ndef resize(array, size, keep_ratio: bool = False, resample=Image.LANCZOS):\n    im = Image.fromarray(array)\n\n    if keep_ratio:\n        im.thumbnail((size, size), resample)\n    else:\n        im = im.resize((size, size), resample)\n\n    return im","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2021-08-01T07:30:06.03665Z","iopub.execute_input":"2021-08-01T07:30:06.036881Z","iopub.status.idle":"2021-08-01T07:30:06.044397Z","shell.execute_reply.started":"2021-08-01T07:30:06.036859Z","shell.execute_reply":"2021-08-01T07:30:06.043437Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"split = 'test'\n\nsave_dir = f'/kaggle/tmp/{split}/'\nos.makedirs(save_dir, exist_ok=True)\n\nsave_dir = f'/kaggle/tmp/{split}/study/'\nos.makedirs(save_dir, exist_ok=True)","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2021-08-01T07:30:06.045929Z","iopub.execute_input":"2021-08-01T07:30:06.046337Z","iopub.status.idle":"2021-08-01T07:30:06.060286Z","shell.execute_reply.started":"2021-08-01T07:30:06.046299Z","shell.execute_reply":"2021-08-01T07:30:06.059388Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Load study-level image","metadata":{}},{"cell_type":"code","source":"STUDY_RES: int = 1024\n\nif fast_sub:\n    xray = read_xray('/kaggle/input/siim-covid19-detection/train/00086460a852/9e8302230c91/65761e66de9f.dcm')\n    im = resize(xray, size=STUDY_RES)\n    study = '00086460a852' + '_study.png'\n    im.save(os.path.join(save_dir, study))\n\n    xray = read_xray('/kaggle/input/siim-covid19-detection/train/000c9c05fd14/e555410bd2cd/51759b5579bc.dcm')\n    im = resize(xray, size=STUDY_RES)  \n    study = '000c9c05fd14' + '_study.png'\n    im.save(os.path.join(save_dir, study))\nelse:   \n    for dirname, _, filenames in tqdm(os.walk(f'../input/siim-covid19-detection/{split}')):\n        for file in filenames:\n            xray = read_xray(os.path.join(dirname, file))\n            im = resize(xray, size=STUDY_RES)  \n            study = dirname.split('/')[-2] + '_study.png'\n            im.save(os.path.join(save_dir, study))","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2021-08-01T07:30:06.062557Z","iopub.execute_input":"2021-08-01T07:30:06.062954Z","iopub.status.idle":"2021-08-01T07:30:08.111005Z","shell.execute_reply.started":"2021-08-01T07:30:06.06292Z","shell.execute_reply":"2021-08-01T07:30:08.110154Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Load image-level image","metadata":{}},{"cell_type":"code","source":"IMAGE_RES: int = 640\n\nimage_id = []\ndim0 = []\ndim1 = []\nsplits = []\n\nsave_dir = f'/kaggle/tmp/{split}/image/'\nos.makedirs(save_dir, exist_ok=True)\n\nif fast_sub:\n    xray = read_xray('/kaggle/input/siim-covid19-detection/train/00086460a852/9e8302230c91/65761e66de9f.dcm')\n    im = resize(xray, size=IMAGE_RES)  \n    im.save(os.path.join(save_dir,'65761e66de9f_image.png'))\n    image_id.append('65761e66de9f.dcm'.replace('.dcm', ''))\n    dim0.append(xray.shape[0])\n    dim1.append(xray.shape[1])\n    splits.append(split)\n\n    xray = read_xray('/kaggle/input/siim-covid19-detection/train/000c9c05fd14/e555410bd2cd/51759b5579bc.dcm')\n    im = resize(xray, size=IMAGE_RES)  \n    im.save(os.path.join(save_dir, '51759b5579bc_image.png'))\n    image_id.append('51759b5579bc.dcm'.replace('.dcm', ''))\n    dim0.append(xray.shape[0])\n    dim1.append(xray.shape[1])\n    splits.append(split)\nelse:\n    for dirname, _, filenames in tqdm(os.walk(f'../input/siim-covid19-detection/{split}')):\n        for file in filenames:\n            xray = read_xray(os.path.join(dirname, file))\n            im = resize(xray, size=IMAGE_RES)  \n            im.save(os.path.join(save_dir, file.replace('.dcm', '_image.png')))\n            image_id.append(file.replace('.dcm', ''))\n            dim0.append(xray.shape[0])\n            dim1.append(xray.shape[1])\n            splits.append(split)","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2021-08-01T07:30:08.11244Z","iopub.execute_input":"2021-08-01T07:30:08.112787Z","iopub.status.idle":"2021-08-01T07:30:08.577783Z","shell.execute_reply.started":"2021-08-01T07:30:08.112747Z","shell.execute_reply":"2021-08-01T07:30:08.576866Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"meta = pd.DataFrame.from_dict(\n    {\n        'image_id': image_id, \n        'dim0': dim0, \n        'dim1': dim1, \n        'split': splits\n    }\n)","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2021-08-01T07:30:08.579196Z","iopub.execute_input":"2021-08-01T07:30:08.579716Z","iopub.status.idle":"2021-08-01T07:30:08.586021Z","shell.execute_reply.started":"2021-08-01T07:30:08.579677Z","shell.execute_reply":"2021-08-01T07:30:08.584951Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Predict study-level image","metadata":{}},{"cell_type":"markdown","source":"## TF pipeline","metadata":{}},{"cell_type":"code","source":"def auto_select_accelerator():\n    try:\n        tpu = tf.distribute.cluster_resolver.TPUClusterResolver()\n        tf.config.experimental_connect_to_cluster(tpu)\n        tf.tpu.experimental.initialize_tpu_system(tpu)\n        strategy = tf.distribute.experimental.TPUStrategy(tpu)\n        print(\"Running on TPU:\", tpu.master())\n    except ValueError:\n        strategy = tf.distribute.get_strategy()\n    print(f\"Running on {strategy.num_replicas_in_sync} replicas\")\n\n    return strategy\n\n\ndef build_decoder(with_labels: bool = False, target_size=(640, 640), ext: str = 'png'):\n    def decode(path):\n        file_bytes = tf.io.read_file(path)\n        if ext == 'png':\n            img = tf.image.decode_png(file_bytes, channels=3)\n        elif ext in ['jpg', 'jpeg']:\n            img = tf.image.decode_jpeg(file_bytes, channels=3)\n        else:\n            raise ValueError(\"Image extension not supported\")\n\n        img = tf.cast(img, tf.float32) / 255.0\n        img = tf.image.resize(img, target_size)\n\n        return img\n\n    return decode\n\n\ndef build_augmenter(img_size: int, with_labels: bool = False):\n    def augment(img):\n        # img = tf.image.random_crop(value=img, size=(img_size, img_size, 3))\n        img = tf.image.random_flip_left_right(img)\n        # img = tf.image.random_flip_up_down(img)\n        img = tf.image.random_brightness(img, 0.1)\n        return img\n\n    return augment\n\n\ndef build_dataset(\n    paths: str, \n    image_size: int,\n    bs: int = 16, \n    decode_fn=None,\n    augment_fn=None,\n    augment: bool = False,\n    repeat: bool = False\n):\n    if decode_fn is None:\n        decode_fn = build_decoder(False, (image_size, image_size))\n\n    if augment_fn is None:\n        augment_fn = build_augmenter(image_size, False)\n\n    AUTO = tf.data.experimental.AUTOTUNE\n\n    dset = tf.data.Dataset.from_tensor_slices(paths)\n    dset = dset.map(decode_fn, num_parallel_calls=AUTO)\n    # dset = dset.cache(cache_dir) if cache else dset\n    dset = dset.map(augment_fn, num_parallel_calls=AUTO) if augment else dset\n    dset = dset.repeat() if repeat else dset\n    # dset = dset.shuffle(shuffle) if shuffle else dset\n    dset = dset.batch(bs).prefetch(AUTO)\n\n    return dset","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2021-08-01T07:30:08.588015Z","iopub.execute_input":"2021-08-01T07:30:08.588465Z","iopub.status.idle":"2021-08-01T07:30:08.602397Z","shell.execute_reply.started":"2021-08-01T07:30:08.588423Z","shell.execute_reply":"2021-08-01T07:30:08.601438Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"strategy = auto_select_accelerator()\nBATCH_SIZE = strategy.num_replicas_in_sync * 16","metadata":{"execution":{"iopub.status.busy":"2021-08-01T07:30:10.263241Z","iopub.execute_input":"2021-08-01T07:30:10.26357Z","iopub.status.idle":"2021-08-01T07:30:10.272969Z","shell.execute_reply.started":"2021-08-01T07:30:10.263522Z","shell.execute_reply":"2021-08-01T07:30:10.271846Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Models","metadata":{}},{"cell_type":"code","source":"EFNS = [\n    efn.EfficientNetB0, efn.EfficientNetB1, efn.EfficientNetB2, efn.EfficientNetB3, \n    efn.EfficientNetB4, efn.EfficientNetB5, efn.EfficientNetB6, efn.EfficientNetB7\n]\n\ndef build_efnet_model(dim: int, ef: int):\n    inp = tf.keras.layers.Input(shape=(dim, dim, 3))\n    base = EFNS[ef](input_shape=(dim, dim, 3), weights=None, include_top=False)\n\n    x = base(inp)\n    x = tf.keras.layers.GlobalAveragePooling2D()(x)\n\n    head = tf.keras.Sequential([tf.keras.layers.Dropout(.5), tf.keras.layers.Dense(4)])\n\n    x1 = head(x)\n    x2 = head(x)\n    x3 = head(x)\n    x4 = head(x)\n    x5 = head(x)\n\n    x = (x1 + x2 + x3 + x4 + x5) / 5.\n    x = tf.keras.layers.Softmax(dtype='float32')(x)\n\n    model = tf.keras.Model(inputs=inp, outputs=x)\n\n    return model\n\n\ndef build_efnet_opacity_model(dim: int, ef: int):\n    inp = tf.keras.layers.Input(shape=(dim, dim, 3))\n    base = EFNS[ef](input_shape=(dim, dim, 3), weights=None, include_top=False)\n\n    x = base(inp)\n    x = tf.keras.layers.GlobalAveragePooling2D()(x)\n\n    head = tf.keras.Sequential([tf.keras.layers.Dropout(.5), tf.keras.layers.Dense(1)])\n\n    x1 = head(x)\n    x2 = head(x)\n    x3 = head(x)\n    x4 = head(x)\n    x5 = head(x)\n\n    x = (x1 + x2 + x3 + x4 + x5) / 5.\n    x = tf.math.sigmoid(x)\n\n    model = tf.keras.Model(inputs=inp, outputs=x)\n\n    return model","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2021-08-01T07:26:31.666572Z","iopub.execute_input":"2021-08-01T07:26:31.667377Z","iopub.status.idle":"2021-08-01T07:26:31.680575Z","shell.execute_reply.started":"2021-08-01T07:26:31.667331Z","shell.execute_reply":"2021-08-01T07:26:31.679434Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Make format","metadata":{}},{"cell_type":"code","source":"if fast_sub:\n    df = fast_df.copy()\nelse:\n    df = pd.read_csv('/kaggle/input/siim-covid19-detection/sample_submission.csv')\n\ndf['id_last_str'] = [df.loc[i,'id'][-1] for i in range(df.shape[0])]\nstudy_len = df[df['id_last_str'] == 'y'].shape[0]","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2021-08-01T07:30:14.038949Z","iopub.execute_input":"2021-08-01T07:30:14.039294Z","iopub.status.idle":"2021-08-01T07:30:14.053673Z","shell.execute_reply.started":"2021-08-01T07:30:14.039263Z","shell.execute_reply":"2021-08-01T07:30:14.05272Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"if fast_sub:\n    sub_df = fast_df.copy()\nelse:\n    sub_df = pd.read_csv('/kaggle/input/siim-covid19-detection/sample_submission.csv')\n\nsub_df = sub_df[:study_len]\ntest_paths = f'/kaggle/tmp/{split}/study/' + sub_df['id'] +'.png'\n\nsub_df['negative'] = 0\nsub_df['typical'] = 0\nsub_df['indeterminate'] = 0\nsub_df['atypical'] = 0\n\nlabel_cols = sub_df.columns[2:]","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2021-08-01T07:30:14.320441Z","iopub.execute_input":"2021-08-01T07:30:14.32075Z","iopub.status.idle":"2021-08-01T07:30:14.340959Z","shell.execute_reply.started":"2021-08-01T07:30:14.320723Z","shell.execute_reply":"2021-08-01T07:30:14.340241Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Inference","metadata":{}},{"cell_type":"code","source":"def infer_efnet_recipe(test_paths, model_path: str, ef: int, tta: int, img_size: int, prefix: str, do_fastsub: bool, do_opacity_cls: bool = False):\n    global fast_sub\n\n    print(f'[*] recipe ef : {ef} img_size : {img_size} prefix : {prefix}')\n\n    dtest = build_dataset(\n        paths=test_paths,\n        image_size=img_size,\n        bs=BATCH_SIZE, \n        repeat=False if do_fastsub else tta > 1, \n        augment=False if do_fastsub else tta > 1,\n        decode_fn=build_decoder(with_labels=False, target_size=(img_size, img_size), ext='png')\n    )\n\n    model_paths = sorted(glob(os.path.join(model_path, f'effnet*{ef}-{prefix}-res{img_size}-fold*.h5')))\n\n    model = None\n    with strategy.scope():\n        if do_opacity_cls:\n            model = build_efnet_opacity_model(img_size, ef=ef)\n        else:\n            model = build_efnet_model(img_size, ef=ef)\n\n    predictions = []\n    for model_path in model_paths:\n        print(f' [+] load {model_path}')\n        with strategy.scope():\n            model.load_weights(model_path)\n\n        if do_fastsub:\n            pred = model.predict(dtest)\n        else:\n            pred = model.predict(dtest, steps=tta * len(test_paths) / BATCH_SIZE)[:tta * len(test_paths), :]\n            pred = np.mean(pred.reshape(tta, len(test_paths), -1), axis=0)\n\n        predictions.append(pred)\n\n    del model\n    del dtest\n    del model_paths\n\n    gc.collect()\n    K.clear_session()\n\n    return np.mean(predictions, axis=0)","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2021-08-01T07:26:31.739324Z","iopub.execute_input":"2021-08-01T07:26:31.73978Z","iopub.status.idle":"2021-08-01T07:26:31.751203Z","shell.execute_reply.started":"2021-08-01T07:26:31.739722Z","shell.execute_reply":"2021-08-01T07:26:31.749701Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"TTA: int = 1","metadata":{"execution":{"iopub.status.busy":"2021-08-01T07:26:31.75345Z","iopub.execute_input":"2021-08-01T07:26:31.754295Z","iopub.status.idle":"2021-08-01T07:26:31.763411Z","shell.execute_reply.started":"2021-08-01T07:26:31.754221Z","shell.execute_reply":"2021-08-01T07:26:31.762119Z"},"_kg_hide-input":true,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"pred1 = infer_efnet_recipe(\n    test_paths,\n    model_path='/kaggle/input/siim-cvoid-19-effnetb7/', \n    ef=7, \n    tta=TTA, \n    img_size=640, \n    prefix='scce0.05-adam-aug_v3',\n    do_fastsub=fast_sub\n)","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2021-08-01T07:26:31.765275Z","iopub.execute_input":"2021-08-01T07:26:31.765883Z","iopub.status.idle":"2021-08-01T07:26:39.954117Z","shell.execute_reply.started":"2021-08-01T07:26:31.765823Z","shell.execute_reply":"2021-08-01T07:26:39.94681Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"pred2 = infer_efnet_recipe(\n    test_paths,\n    model_path='/kaggle/input/siim-cvoid-19-effnetb6/', \n    ef=6, \n    tta=TTA, \n    img_size=800, \n    prefix='scce0.05-adam',\n    do_fastsub=fast_sub\n)","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2021-08-01T07:26:39.955084Z","iopub.status.idle":"2021-08-01T07:26:39.955561Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sub_df[label_cols] = (pred1 + pred2) / 2.","metadata":{"execution":{"iopub.status.busy":"2021-08-01T07:26:39.956905Z","iopub.status.idle":"2021-08-01T07:26:39.957763Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"del pred1, pred2\ngc.collect()","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sub_df.columns = ['id', 'PredictionString1', 'negative', 'typical', 'indeterminate', 'atypical']\ndf = pd.merge(df, sub_df, on='id', how='left')","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2021-08-01T07:26:39.959226Z","iopub.status.idle":"2021-08-01T07:26:39.960055Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Generate study-string","metadata":{}},{"cell_type":"code","source":"for i in range(study_len):\n    negative = df.at[i, 'negative']\n    typical = df.at[i, 'typical']\n    indeterminate = df.at[i, 'indeterminate']\n    atypical = df.at[i, 'atypical']\n\n    df.at[i, 'PredictionString'] = f'negative {negative} 0 0 1 1 typical {typical} 0 0 1 1 indeterminate {indeterminate} 0 0 1 1 atypical {atypical} 0 0 1 1'\n\ndf_study = df[['id', 'PredictionString']]","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2021-08-01T07:26:39.96176Z","iopub.status.idle":"2021-08-01T07:26:39.962604Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Opacity Detection","metadata":{}},{"cell_type":"code","source":"if fast_sub:\n    sub_df = fast_df.copy()\nelse:\n    sub_df = pd.read_csv('/kaggle/input/siim-covid19-detection/sample_submission.csv')\n\nsub_df = sub_df[study_len:]\ntest_paths = f'/kaggle/tmp/{split}/image/' + sub_df['id'] +'.png'\nsub_df['none'] = 0\n\nlabel_cols = sub_df.columns[2]","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2021-08-01T07:26:39.966523Z","iopub.status.idle":"2021-08-01T07:26:39.967334Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Inference","metadata":{}},{"cell_type":"code","source":"pred1 = infer_efnet_recipe(\n    test_paths,\n    model_path='/kaggle/input/siim-cvoid-19-effnetb7/', \n    ef=7, \n    tta=1, \n    img_size=640, \n    prefix='scce0.05-adam-aug_v3',\n    do_fastsub=fast_sub\n)","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2021-08-01T07:26:39.96899Z","iopub.status.idle":"2021-08-01T07:26:39.969815Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"pred2 = infer_efnet_recipe(\n    test_paths,\n    model_path='/kaggle/input/siim-cvoid-19-effnetb6/', \n    ef=6, \n    tta=1, \n    img_size=800, \n    prefix='scce0.05-adam',\n    do_fastsub=fast_sub\n)","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2021-08-01T07:26:39.971228Z","iopub.status.idle":"2021-08-01T07:26:39.972137Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Ensemble","metadata":{}},{"cell_type":"code","source":"preds = (pred1[:, 0] + pred2[:, 0]) / 2.0\n\nsub_df[label_cols] = preds\ndf_2class = sub_df.reset_index(drop=True)","metadata":{"execution":{"iopub.status.busy":"2021-08-01T07:26:39.973698Z","iopub.status.idle":"2021-08-01T07:26:39.974439Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"del pred1, pred2, preds\n\nK.clear_session()\ngc.collect()","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2021-08-01T07:26:39.976046Z","iopub.status.idle":"2021-08-01T07:26:39.976916Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"cuda.select_device(0)\ncuda.close()\ncuda.select_device(0)","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2021-08-01T07:26:39.978566Z","iopub.status.idle":"2021-08-01T07:26:39.979381Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Predict image-level image","metadata":{}},{"cell_type":"code","source":"meta = meta[meta['split'] == 'test']\n\nif fast_sub:\n    test_df = fast_df.copy()\nelse:\n    test_df = pd.read_csv('/kaggle/input/siim-covid19-detection/sample_submission.csv')\n\ntest_df = df[study_len:].reset_index(drop=True) \nmeta['image_id'] = meta['image_id'] + '_image'\nmeta.columns = ['id', 'dim0', 'dim1', 'split']\ntest_df = pd.merge(test_df, meta, on='id', how='left')","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2021-08-01T07:30:26.713895Z","iopub.execute_input":"2021-08-01T07:30:26.714338Z","iopub.status.idle":"2021-08-01T07:30:26.733262Z","shell.execute_reply.started":"2021-08-01T07:30:26.714297Z","shell.execute_reply":"2021-08-01T07:30:26.731775Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_dir = f'/kaggle/tmp/{split}/image'\n\nshutil.copytree('/kaggle/input/yolov5', '/kaggle/working/yolov5')\nos.chdir('/kaggle/working/yolov5')","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2021-08-01T07:30:27.043285Z","iopub.execute_input":"2021-08-01T07:30:27.043651Z","iopub.status.idle":"2021-08-01T07:30:27.47175Z","shell.execute_reply.started":"2021-08-01T07:30:27.043608Z","shell.execute_reply":"2021-08-01T07:30:27.470836Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Utils","metadata":{}},{"cell_type":"markdown","source":"### yolo2voc","metadata":{}},{"cell_type":"code","source":"def yolo2voc(image_height, image_width, bboxes):\n    \"\"\"\n    yolo => [xmid, ymid, w, h] (normalized)\n    voc  => [x1, y1, x2, y1]\n    \"\"\" \n    bboxes = bboxes.copy().astype(float)  # otherwise all value will be 0 as voc_pascal dtype is np.int\n\n    bboxes[..., [0, 2]] = bboxes[..., [0, 2]] * image_width\n    bboxes[..., [1, 3]] = bboxes[..., [1, 3]] * image_height\n\n    bboxes[..., [0, 1]] = bboxes[..., [0, 1]] - bboxes[..., [2, 3]] / 2.\n    bboxes[..., [2, 3]] = bboxes[..., [0, 1]] + bboxes[..., [2, 3]]\n\n    return bboxes","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2021-08-01T07:30:29.395751Z","iopub.execute_input":"2021-08-01T07:30:29.396098Z","iopub.status.idle":"2021-08-01T07:30:29.406062Z","shell.execute_reply.started":"2021-08-01T07:30:29.396055Z","shell.execute_reply":"2021-08-01T07:30:29.405245Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### solve_bbox_problems","metadata":{}},{"cell_type":"code","source":"def solve_bbox_problems(bbox_v, scores_v):\n    bbox_v = np.asarray(bbox_v)\n    scores_v = np.asarray(scores_v)\n\n    to_remove = np.zeros(len(bbox_v), dtype=np.bool)\n    for i in range(len(bbox_v)):\n        x1, y1, x2, y2 = bbox_v[i]\n\n        if x2 < x1:\n            x1, x2 = x2, x1\n        if y2 < y1:\n            y1, y2 = y2, y1\n        if x1 < 0:\n            x1 = 0\n        if x1 > 1:\n            x1 = 1\n        if x2 < 0:\n            x2 = 0\n        if x2 > 1:\n            x2 = 1\n        if y1 < 0:\n            y1 = 0\n        if y1 > 1:\n            y1 = 1\n        if y2 < 0:\n            y2 = 0\n        if y2 > 1:\n            y2 = 1\n        if (x2 - x1) * (y2 - y1) == 0.0:\n            to_remove[i] = True\n\n        bbox_v[i] = x1, y1, x2, y2\n\n    if to_remove.sum() > 0:\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","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2021-08-01T07:44:31.226314Z","iopub.execute_input":"2021-08-01T07:44:31.226677Z","iopub.status.idle":"2021-08-01T07:44:31.235331Z","shell.execute_reply.started":"2021-08-01T07:44:31.226641Z","shell.execute_reply":"2021-08-01T07:44:31.234304Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### calc_iou","metadata":{}},{"cell_type":"code","source":"def 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    bb0_x0, bb0_y0, bb0_x1, bb0_y1 = bb0\n    bb1_x0, bb1_y0, bb1_x1, bb1_y1 = bb1\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    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    return iou * ret_mask","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2021-08-01T07:44:31.781277Z","iopub.execute_input":"2021-08-01T07:44:31.781681Z","iopub.status.idle":"2021-08-01T07:44:31.789335Z","shell.execute_reply.started":"2021-08-01T07:44:31.781642Z","shell.execute_reply":"2021-08-01T07:44:31.788386Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### merge_preds","metadata":{}},{"cell_type":"code","source":"def merge_preds(bbox_v, p_det_v=None, mode: str = 'p_det_weight'):\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    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    elif mode == 'median' or mode == 'median_pmean':\n        bbox = np.median(bbox_v, axis=0)\n        p = p_det_v.mean()\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    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    else:\n        raise ValueError(f'Unknown mode {mode}')\n\n    return bbox, p","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2021-08-01T07:44:31.998816Z","iopub.execute_input":"2021-08-01T07:44:31.999152Z","iopub.status.idle":"2021-08-01T07:44:32.008435Z","shell.execute_reply.started":"2021-08-01T07:44:31.999116Z","shell.execute_reply":"2021-08-01T07:44:32.007662Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### norm_p_det","metadata":{}},{"cell_type":"code","source":"def norm_p_det(pred_v):\n    p_det_v = [pred_d['p_det'] for pred_d in pred_v if len(pred_d['p_det']) > 0]\n    p_det_v = np.concatenate(p_det_v)\n\n    p_det_max = p_det_v.max()\n\n    print(f'[+] p_det_max = {p_det_max}')\n    if p_det_max <= 1.0:\n        print('[*] skipping norm_p_det')\n        return pred_v\n\n    ret_pred_v = 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    return ret_pred_v","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2021-08-01T07:44:32.148334Z","iopub.execute_input":"2021-08-01T07:44:32.14869Z","iopub.status.idle":"2021-08-01T07:44:32.156852Z","shell.execute_reply.started":"2021-08-01T07:44:32.148654Z","shell.execute_reply":"2021-08-01T07:44:32.155792Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### fix_boxes","metadata":{}},{"cell_type":"code","source":"def fix_boxes(preds_v):\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                f = ~(f0 + f1)\n                for k in ['p_det', 'bbox', 'cls']:\n                    preds_d[k] = preds_d[k][f]","metadata":{"_kg_hide-input":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Detect Yolov5","metadata":{}},{"cell_type":"code","source":"import os\nimport yolov5\nfrom utils.datasets import LoadImages\nfrom utils.general import non_max_suppression, scale_coords, xyxy2xywh\n\nfrom glob import glob\n\n\ndef yolov5_detect():\n    device = torch.device('cuda') if torch.cuda.is_available() else torch.device('cpu')\n\n    model_paths = [\n        # YOLOv5x6\n        '/kaggle/input/siim-covid19-yolov5/yolov5x6-fold0-mAP0.4466.pt',\n        '/kaggle/input/siim-covid19-yolov5/yolov5x6-fold1-mAP0.49373.pt',\n        '/kaggle/input/siim-covid19-yolov5/yolov5x6-fold2-mAP0.48003.pt',\n        '/kaggle/input/siim-covid19-yolov5/yolov5x6-fold3-mAP0.42454.pt',\n        '/kaggle/input/siim-covid19-yolov5/yolov5x6-fold4-mAP0.46058.pt',\n        # YOLOv5X6 res640\n        # '/kaggle/input/siim-covid19-yolov5x6-res640/yolov5x6-res640-fold0-mAP0.4662.pt',\n        # '/kaggle/input/siim-covid19-yolov5x6-res640/yolov5x6-res640-fold1-mAP0.5044.pt',\n        # '/kaggle/input/siim-covid19-yolov5x6-res640/yolov5x6-res640-fold2-mAP0.4762.pt',\n        # '/kaggle/input/siim-covid19-yolov5x6-res640/yolov5x6-res640-fold3-mAP0.4391.pt',\n        # '/kaggle/input/siim-covid19-yolov5x6-res640/yolov5x6-res640-fold4-mAP0.4676.pt',\n        # YOLOv5l6\n        '/kaggle/input/siim-covid19-yolov5l/yolov5l6-res512-fold0-mAP0.42464.pt',\n        '/kaggle/input/siim-covid19-yolov5l/yolov5l6-res512-fold1-mAP0.39763.pt',\n        '/kaggle/input/siim-covid19-yolov5l/yolov5l6-res512-fold2-mAP0.42889.pt',\n        '/kaggle/input/siim-covid19-yolov5l/yolov5l6-res512-fold3-mAP0.39249.pt',\n        '/kaggle/input/siim-covid19-yolov5l/yolov5l6-res512-fold4-mAP0.4241.pt',\n        # YOLOv5m6\n        '/kaggle/input/siim-covid19-yolov5m/yolov5m6-res512-fold0-mAP0.45113.pt',\n        '/kaggle/input/siim-covid19-yolov5m/yolov5m6-res512-fold1-mAP0.44463.pt',\n        '/kaggle/input/siim-covid19-yolov5m/yolov5m6-res512-fold2-mAP0.4496.pt',\n        '/kaggle/input/siim-covid19-yolov5m/yolov5m6-res512-fold3-mAP0.4121.pt',\n        '/kaggle/input/siim-covid19-yolov5m/yolov5m6-res512-fold4-mAP0.42406.pt',\n        # YOLOv5s6\n        '/kaggle/input/siim-covid19-yolov5s6/yolov5s6-res512-fold0-mAP0.4885.pt',\n        '/kaggle/input/siim-covid19-yolov5s6/yolov5s6-res512-fold1-mAP0.4977.pt',\n        '/kaggle/input/siim-covid19-yolov5s6/yolov5s6-res512-fold2-mAP0.495.pt',\n        '/kaggle/input/siim-covid19-yolov5s6/yolov5s6-res512-fold3-mAP0.456.pt',\n        '/kaggle/input/siim-covid19-yolov5s6/yolov5s6-res512-fold4-mAP0.4746.pt',\n    ]\n\n    models = [\n        torch.load(model_path, map_location=device)['model'].to(device).float().eval()\n        for model_path in model_paths\n    ]\n\n    dataset = LoadImages('/kaggle/tmp/test/image', img_size=IMAGE_RES)\n\n    all_path = []\n    all_bboxes = []\n    all_score = []\n    for path, img, im0s, _ in dataset:\n        img = torch.from_numpy(img).to(device).float() / 255.\n\n        if img.ndimension() == 3:\n            img = img.unsqueeze(0)\n\n        bboxes_2, score_2 = [], []\n        for model in models:\n            pred = model(img, augment=True)[0]\n            pred = non_max_suppression(pred, 0.001, 0.5, classes=None, agnostic=False)\n\n            bboxes, score = [], []\n            for i, det in enumerate(pred):\n                # gain = torch.tensor(im0.shape)[[1, 0, 1, 0]]\n                if det is not None and len(det):\n                    det[:, :4] = scale_coords(img.shape[2:], det[:, :4], im0s.shape).round()\n                    for c in det[:, -1].unique():\n                        n = (det[:, -1] == c).sum()\n\n                    for *xyxy, conf, _ in det:\n                        bboxes.append(torch.tensor(xyxy).view(-1).numpy())\n                        score.append(conf.cpu().numpy().item())\n\n            bboxes_2.append(bboxes)\n            score_2.append(score)\n\n        all_path.append(path)\n        all_score.append(score_2)\n        all_bboxes.append(bboxes_2)\n\n    del models\n    del dataset\n    del model_paths\n\n    gc.collect()\n    torch.cuda.empty_cache()\n\n    return all_path, all_score, all_bboxes","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2021-08-01T07:44:33.526494Z","iopub.execute_input":"2021-08-01T07:44:33.526854Z","iopub.status.idle":"2021-08-01T07:44:33.541049Z","shell.execute_reply.started":"2021-08-01T07:44:33.526822Z","shell.execute_reply":"2021-08-01T07:44:33.540062Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Yolov5","metadata":{}},{"cell_type":"code","source":"# def ensemble_pp(boxes, scores, iou_thres: float, skip_box_thr: float):\n#     labels = [np.ones(len(scores[idx])) for idx in range(len(scores))]\n\n#     nms_boxes, nms_scores, nms_labels = nms(boxes, scores, labels, weights=None, iou_thr=iou_thres)\n#     snms_boxes, snms_scores, snms_labels = soft_nms(boxes, scores, labels, weights=None, iou_thr=iou_thres, sigma=0.1, thresh=skip_box_thr)\n#     nmw_boxes, nmw_scores, nmw_labels = non_maximum_weighted(boxes, scores, labels, weights=None, iou_thr=iou_thres, skip_box_thr=skip_box_thr)\n#     wbf_boxes, wbf_scores, wbf_labels = weighted_boxes_fusion(boxes, scores, labels, weights=None, iou_thr=iou_thres, skip_box_thr=skip_box_thr)\n\n#     del labels\n\n#     boxes, scores, _ = weighted_boxes_fusion(\n#         [nms_boxes, snms_boxes, nmw_boxes, wbf_boxes], \n#         [nms_scores, snms_scores, nmw_scores, wbf_scores],\n#         [nms_labels, snms_labels, nmw_labels, wbf_labels], \n#         weights=[2, 3, 4, 5], \n#         iou_thr=iou_thres, \n#         skip_box_thr=skip_box_thr\n#     )\n\n#     del nms_boxes, nms_scores, nms_labels\n#     del snms_boxes, snms_scores, snms_labels\n#     del nmw_boxes, nmw_scores, nmw_labels\n#     del wbf_boxes, wbf_scores, wbf_labels\n#     gc.collect()\n\n#     return boxes, scores\n\ndef ensemble_pp(boxes, scores, iou_thres: float, skip_box_thr: float, weights = None):\n    boxes, scores, _ = weighted_boxes_fusion(\n        boxes, \n        scores,\n        [np.ones(len(scores[idx])) for idx in range(len(scores))],\n        weights=weights,\n        iou_thr=iou_thres, \n        skip_box_thr=skip_box_thr,\n    )\n    return boxes, scores\n\n\n# def ensemble_pp(boxes, scores, iou_thres: float, skip_box_thr: float, weights = None):\n#     boxes, scores, _ = nms(\n#         boxes, \n#         scores,\n#         [np.ones(len(scores[idx])) for idx in range(len(scores))],\n#         weights=weights,\n#         iou_thr=iou_thres, \n#     )\n#     return boxes, scores","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2021-08-01T07:47:23.570518Z","iopub.execute_input":"2021-08-01T07:47:23.570895Z","iopub.status.idle":"2021-08-01T07:47:23.579958Z","shell.execute_reply.started":"2021-08-01T07:47:23.570863Z","shell.execute_reply":"2021-08-01T07:47:23.577655Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"with torch.no_grad():\n    yolov5_all_path, yolov5_all_score, yolov5_all_bboxes = yolov5_detect()","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"yolov5_preds = {}\nfor row in range(len(yolov5_all_path)):\n    image_id = yolov5_all_path[row].split('/')[-1].split('.')[0]\n    boxes = yolov5_all_bboxes[row]\n    scores = yolov5_all_score[row]\n\n    # normalized to [0, 1]\n    boxes = [[coord / (IMAGE_RES - 1) for coord in box] for box in boxes]\n\n    # solve_bbox_problems over the models\n    # for i in range(len(boxes)):\n    #     boxes, scores = solve_bbox_problems(boxes[i], scores[i])\n    boxes, scores = ensemble_pp(\n        boxes, \n        scores,\n        iou_thres=0.60, \n        skip_box_thr=0.01,\n    )\n\n    # unnormalized to [0, IMAGE_RES]\n    boxes = [np.asarray([int(coord * (IMAGE_RES - 1)) for coord in box]) for box in boxes]\n\n    yolov5_preds[image_id] = [boxes, scores]\n\n    del image_id, boxes, scores\n    gc.collect()","metadata":{"execution":{"iopub.status.busy":"2021-08-01T07:47:34.489252Z","iopub.execute_input":"2021-08-01T07:47:34.489597Z","iopub.status.idle":"2021-08-01T07:47:34.855557Z","shell.execute_reply.started":"2021-08-01T07:47:34.489559Z","shell.execute_reply":"2021-08-01T07:47:34.854713Z"},"_kg_hide-input":true,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"del yolov5_all_path\ndel yolov5_all_score\ndel yolov5_all_bboxes\ngc.collect()","metadata":{"_kg_hide-input":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Convert coordinates","metadata":{}},{"cell_type":"code","source":"image_ids = []\nPredictionStrings = []\nfor image_id, v in yolov5_preds.items():\n    w, h = test_df.loc[test_df['id'] == image_id, ['dim1', 'dim0']].values[0]\n\n    boxes, scores = v\n\n    normalized_boxes = [xyxy2xywh(box[None, :]) / IMAGE_RES for box in boxes]\n    rescaled_boxes = [np.round(yolo2voc(h, w, x)[0]) for x in normalized_boxes]\n    string_boxes = [\n        f'1 {score} {int(box[0])} {int(box[1])} {int(box[2])} {int(box[3])}' \n        for score, box in zip(scores, rescaled_boxes)\n    ]\n\n    image_ids.append(image_id)\n    PredictionStrings.append(' '.join(string_boxes))\n\n    del boxes, scores\n    del normalized_boxes\n    del rescaled_boxes\n    del string_boxes\n\npred_df = pd.DataFrame(\n    {\n        'id': image_ids, \n        'PredictionString': PredictionStrings\n    }\n)\n\ndel image_ids, PredictionStrings\ngc.collect()","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2021-08-01T07:26:40.008544Z","iopub.status.idle":"2021-08-01T07:26:40.009396Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_df = test_df.drop(['PredictionString'], axis=1)\nsub_df = pd.merge(test_df, pred_df, on='id', how='left').fillna('none 1 0 0 1 1')\nsub_df = sub_df[['id', 'PredictionString']]","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2021-08-01T07:26:40.01117Z","iopub.status.idle":"2021-08-01T07:26:40.012059Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for i in range(sub_df.shape[0]):\n    prediction_string: str = sub_df.at[i, 'PredictionString']\n    if prediction_string == 'none 1 0 0 1 1':\n        continue\n\n    sub_df_split = prediction_string.split()\n\n    sub_df_list = []\n    for j in range(len(sub_df_split) // 6):\n        sub_df_list.append('opacity')\n        sub_df_list.append(sub_df_split[6 * j + 1])\n        sub_df_list.append(sub_df_split[6 * j + 2])\n        sub_df_list.append(sub_df_split[6 * j + 3])\n        sub_df_list.append(sub_df_split[6 * j + 4])\n        sub_df_list.append(sub_df_split[6 * j + 5])\n\n    sub_df.at[i, 'PredictionString'] = ' '.join(sub_df_list)\n\n    del sub_df_list\n    del prediction_string","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2021-08-01T07:26:40.013751Z","iopub.status.idle":"2021-08-01T07:26:40.014538Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Post-Processing","metadata":{}},{"cell_type":"markdown","source":"### Utils","metadata":{}},{"cell_type":"code","source":"def clean_predictions(\n    preds_v, \n    iou_th: float,\n    mode: str = 'p_det_weight',\n):\n    ret_preds_v = []\n    for pred_d in preds_v:\n        cls_v = pred_d['cls']\n        bbox_v = pred_d['bbox']\n        p_det_v = pred_d['p_det']\n\n        new_cls_v = []\n        new_bbox_v = []\n        new_p_det_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                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            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\n                to_join_idxs_v = []\n                for i in range(n_c):\n                    idxs_s = set(np.argwhere(calc_iou(f_bbox_v[i], f_bbox_v) > iou_th).T[0])\n\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                    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                    if len(to_join_idxs) < 1:\n                        continue\n\n                    bbox, p_det = merge_preds(f_bbox_v[to_join_idxs], f_p_det_v[to_join_idxs], mode=mode)\n\n                    new_cls_v.append(i_c)\n                    new_bbox_v.append(bbox)\n                    new_p_det_v.append(p_det)\n\n        ret_preds_d = {\n            'cls': np.array(new_cls_v),\n            'bbox': np.array(new_bbox_v),\n            'p_det': np.array(new_p_det_v),\n        }\n\n        for k in pred_d.keys():\n            if k not in ['cls', 'bbox', 'p_det']:\n                ret_preds_d[k] = pred_d[k]\n\n        ret_preds_v.append(ret_preds_d)\n\n    return ret_preds_v","metadata":{"_kg_hide-input":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def pred_to_str(pred_d):\n    bbox_v = pred_d['bbox']\n    p_det_v = pred_d['p_det']\n\n    return ' '.join(\n        [\n            'opacity {:0.05} {} {} {} {}'.format(p_det, *bbox)\n            for p_det, bbox in zip(p_det_v, np.round(bbox_v).astype(np.int))\n        ]\n    )","metadata":{"_kg_hide-input":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Cleaning","metadata":{}},{"cell_type":"code","source":"# reference : https://www.kaggle.com/morizin/ensemble331-remake/notebook#Final-cleaning\npreds_v = read_prediction_csv(sub_df)\n\nfix_boxes(preds_v)\n\nclean_pred_v = clean_predictions(\n    preds_v,\n    iou_th=0.60,\n    mode='p_det_weight_psum'\n)\n\nnorm_clean_pred_v = norm_p_det(clean_pred_v)\n\ndel preds_v\ndel clean_pred_v\ngc.collect()","metadata":{"_kg_hide-input":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"pred_summary_d = {'image_id': [], 'PredictionString': []}\nfor pred_d in norm_clean_pred_v:\n    pred_str: str = pred_to_str(pred_d)\n\n    pred_summary_d['image_id'].append(pred_d['sample_id'])\n    pred_summary_d['PredictionString'].append(pred_str)\n\n    del pred_str\n\nsub_df = pd.DataFrame(pred_summary_d)\n\ndel pred_summary_d\ngc.collect()","metadata":{"_kg_hide-input":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Opacity","metadata":{}},{"cell_type":"code","source":"low_threshold: float = 0.00\nhigh_threshold: float = 1.00\n\nsub_df['none'] = df_2class['none']\n\nfor i in range(sub_df.shape[0]):\n    if sub_df.at[i, 'PredictionString'] != 'none 1 0 0 1 1':\n        none_prob: float = sub_df.at[i, 'none']\n\n        sub_df.at[i, 'PredictionString'] = sub_df.at[i, 'PredictionString'] + f' none {none_prob} 0 0 1 1'\n\n        # make sure bbox must be sorted by the confidence\n        # todo : threshold\n        # todo : remove bbox which has a confidence lower than a none confidence\n\n#         if none_prob < low_threshold:\n#             sub_df.at[i, 'PredictionString'] = sub_df.at[i, 'PredictionString']\n#             c0 += 1\n#         elif low_threshold <= none_prob and none_prob < high_threshold:\n#             sub_df.at[i, 'PredictionString'] = sub_df.at[i, 'PredictionString'] + f' none {none_prob} 0 0 1 1'\n#             c1 += 1\n#         else:\n#             sub_df.at[i, 'PredictionString'] = 'none 1 0 0 1 1'\n#             c2 += 1\n\n# sub_df = sub_df[['id', 'PredictionString']]\nsub_df = sub_df[['image_id', 'PredictionString']]\nsub_df = sub_df.rename(columns={'image_id': 'id'})","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Submission","metadata":{}},{"cell_type":"code","source":"df_study = df_study[:study_len]\ndf_study = df_study.append(sub_df).reset_index(drop=True)\ndf_study.to_csv('/kaggle/working/submission.csv', index=False)","metadata":{"_kg_hide-input":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_study","metadata":{"_kg_hide-input":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"shutil.rmtree('/kaggle/working/yolov5')","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2021-08-01T07:26:40.023379Z","iopub.status.idle":"2021-08-01T07:26:40.024253Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# EOF","metadata":{}}]}