{"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":"![](https://i.ibb.co/Zm9Rmdb/lung-nb4-short.jpg)\n\n<p style='text-align: center;'><span style=\"color: #000508; font-family: Segoe UI; font-size: 2.5em; font-weight: 300;\">SIIM COVID-19 EffNetV2 CascadeRCNN MMDetection Inference</span></p>\n\n<span style=\"color: #00857e; font-family: Segoe UI; font-size: 1.8em; font-weight: 300;\">Overview</span>\n\n&nbsp;&nbsp;✅&nbsp;&nbsp;EfficientNetV2 TF Model Study Level Inference on GPU with Keras<br>\n&nbsp;&nbsp;✅&nbsp;&nbsp;CascadeRCNN Image Level Inference on GPU with MMDetection<br>\n\n<br>\n<p style='text-align: left;'><span style=\"color: #000508; font-family: Segoe UI; font-size: 1.1em; font-weight: 600;\"> 🏷️ Dataset with EffNetV2 TfHub Weights used in this notebook:</span></p>\n\n\n>  [EfficientNetV2 TFHub Weight Files](https://www.kaggle.com/sreevishnudamodaran/efficientnetv2-tfhub-weight-files?select=tfhub_models)<br>\n  Official EfficientNetV2 Saved Model Files from tfhub.dev\n\n<br>\n<p style='text-align: left;'><span style=\"color: #000508; font-family: Segoe UI; font-size: 1.1em; font-weight: 600;\"> 🏷️ EffNetV2 Keras Study Level Train notebook:</span></p>\n\n\n>  [SIIM EffNetV2 Keras Study Train [TPU CV0.805+]🎏](https://www.kaggle.com/sreevishnudamodaran/siim-effnetv2-keras-study-train-tpu-cv0-805)<br>\n  Official EfficientNetV2 Saved Model Files from tfhub.dev\n\n<br>\n<p style='text-align: left;'><span style=\"color: #000508; font-family: Segoe UI; font-size: 1.1em; font-weight: 600;\"> 🏷️ MMDetection CascadeRCNN Image Level Train notebook:</span></p>\n\n\n>  [SIIM MMDetection+CascadeRCNN+Weight&Bias☄️🔮](https://www.kaggle.com/sreevishnudamodaran/siim-mmdetection-cascadercnn-weight-bias)<br>\n  Official EfficientNetV2 Saved Model Files from tfhub.dev\n\n<br>\n\n\n<span style=\"color: #000508; font-family: Segoe UI; font-size: 1.8em;\">References:</span>\n\n- https://www.kaggle.com/h053473666/siim-cov19-efnb7-yolov5-infer\n- https://github.com/tensorflow/hub\n- https://github.com/open-mmlab/mmdetection\n\n<br>\n<a href=\"https://www.kaggle.com/sreevishnudamodaran\"><center><img border=\"0\" alt=\"Ask Me Something\" src=\"https://img.shields.io/badge/Ask%20me-something-1abc9c.svg?style=flat-square&logo=kaggle\" width=\"130\" height=\"10\"></center></a>\n<br>\n<center><img border=\"0\" alt=\"Ask Me Something\" src=\"https://img.shields.io/badge/Please-Upvote%20If%20you%20like%20this-07b3c8?style=for-the-badge&logo=kaggle\" width=\"260\" height=\"20\"></center>","metadata":{"papermill":{"duration":0.026785,"end_time":"2021-07-17T18:53:20.688374","exception":false,"start_time":"2021-07-17T18:53:20.661589","status":"completed"},"tags":[]}},{"cell_type":"code","source":"%load_ext autoreload\n%autoreload 2\n\n!conda install '/kaggle/input/pydicom-conda-helper/libjpeg-turbo-2.1.0-h7f98852_0.tar.bz2' -y --offline\n!conda install '/kaggle/input/pydicom-conda-helper/libgcc-ng-9.3.0-h2828fa1_19.tar.bz2' -y --offline\n!conda install '/kaggle/input/pydicom-conda-helper/gdcm-2.8.9-py37h500ead1_1.tar.bz2' -y --offline\n!conda install '/kaggle/input/pydicom-conda-helper/conda-4.10.1-py37h89c1867_0.tar.bz2' -y --offline\n!conda install '/kaggle/input/pydicom-conda-helper/certifi-2020.12.5-py37h89c1867_1.tar.bz2' -y --offline\n!conda install '/kaggle/input/pydicom-conda-helper/openssl-1.1.1k-h7f98852_0.tar.bz2' -y --offline\n\n!pip install '/kaggle/input/kerasapplications' --no-deps\n!pip install '/kaggle/input/efficientnet-keras-source-code' --no-deps\n!pip install '/kaggle/input/effdet-latestvinbigdata-wbf-fused/ensemble_boxes-1.0.4-py3-none-any.whl' --no-deps\n\n## MMDetection compatible torch installation\n!pip install '/kaggle/input/pytorch-170-cuda-toolkit-110221/torch-1.7.0+cu110-cp37-cp37m-linux_x86_64.whl' --no-deps\n!pip install '/kaggle/input/pytorch-170-cuda-toolkit-110221/torchvision-0.8.1+cu110-cp37-cp37m-linux_x86_64.whl' --no-deps\n!pip install '/kaggle/input/pytorch-170-cuda-toolkit-110221/torchaudio-0.7.0-cp37-cp37m-linux_x86_64.whl' --no-deps\n\n## Compatible Cuda Toolkit installation\n!mkdir -p /kaggle/tmp && cp /kaggle/input/pytorch-170-cuda-toolkit-110221/cudatoolkit-11.0.221-h6bb024c_0 /kaggle/tmp/cudatoolkit-11.0.221-h6bb024c_0.tar.bz2 && conda install /kaggle/tmp/cudatoolkit-11.0.221-h6bb024c_0.tar.bz2 -y --offline\n\n## MMDetection Offline Installation\n!pip install '/kaggle/input/mmdetectionv2140/addict-2.4.0-py3-none-any.whl' --no-deps\n!pip install '/kaggle/input/mmdetectionv2140/yapf-0.31.0-py2.py3-none-any.whl' --no-deps\n!pip install '/kaggle/input/mmdetectionv2140/terminal-0.4.0-py3-none-any.whl' --no-deps\n!pip install '/kaggle/input/mmdetectionv2140/terminaltables-3.1.0-py3-none-any.whl' --no-deps\n!pip install '/kaggle/input/mmdetectionv2140/mmcv_full-1_3_8-cu110-torch1_7_0/mmcv_full-1.3.8-cp37-cp37m-manylinux1_x86_64.whl' --no-deps\n!pip install '/kaggle/input/mmdetectionv2140/pycocotools-2.0.2/pycocotools-2.0.2' --no-deps\n!pip install '/kaggle/input/mmdetectionv2140/mmpycocotools-12.0.3/mmpycocotools-12.0.3' --no-deps\n\n!cp -r /kaggle/input/mmdetectionv2140/mmdetection-2.14.0 /kaggle/working/\n!mv /kaggle/working/mmdetection-2.14.0 /kaggle/working/mmdetection\n%cd /kaggle/working/mmdetection\n!pip install -e . --no-deps\n%cd /kaggle/working/","metadata":{"papermill":{"duration":589.21781,"end_time":"2021-07-17T19:03:09.933611","exception":false,"start_time":"2021-07-17T18:53:20.715801","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2021-11-24T21:37:27.116981Z","iopub.execute_input":"2021-11-24T21:37:27.117331Z","iopub.status.idle":"2021-11-24T21:47:27.682715Z","shell.execute_reply.started":"2021-11-24T21:37:27.117300Z","shell.execute_reply":"2021-11-24T21:47:27.681714Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import sys\nsys.path.append('/kaggle/working/mmdetection')\n\nimport os\nfrom PIL import Image\nimport pandas as pd\nfrom tqdm.auto import tqdm\nimport gc\nimport glob\nimport numpy as np","metadata":{"_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","papermill":{"duration":0.104274,"end_time":"2021-07-17T19:03:10.131834","exception":false,"start_time":"2021-07-17T19:03:10.02756","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2021-11-24T21:47:27.684354Z","iopub.execute_input":"2021-11-24T21:47:27.684620Z","iopub.status.idle":"2021-11-24T21:47:27.832024Z","shell.execute_reply.started":"2021-11-24T21:47:27.684589Z","shell.execute_reply":"2021-11-24T21:47:27.831177Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<span style=\"color: #00857e; font-family: Segoe UI; font-size: 1.8em; font-weight: 300;\">Create Study and Image Level Dataframes</span>","metadata":{"papermill":{"duration":0.092535,"end_time":"2021-07-17T19:03:10.317337","exception":false,"start_time":"2021-07-17T19:03:10.224802","status":"completed"},"tags":[]}},{"cell_type":"code","source":"sub_df = pd.read_csv('/kaggle/input/siim-covid19-detection/sample_submission.csv')\n\n# Form study and image dataframes\nsub_df['level'] = sub_df.id.map(lambda idx: idx[-5:])\nstudy_df = sub_df[sub_df.level=='study'].rename({'id':'study_id'}, axis=1)\nimage_df = sub_df[sub_df.level=='image'].rename({'id':'image_id'}, axis=1)\n\ndcm_path = glob.glob('/kaggle/input/siim-covid19-detection/test/**/*dcm', recursive=True)\ntest_meta = pd.DataFrame({'dcm_path':dcm_path})\ntest_meta['image_id'] = test_meta.dcm_path.map(lambda x: x.split('/')[-1].replace('.dcm', '')+'_image')\ntest_meta['study_id'] = test_meta.dcm_path.map(lambda x: x.split('/')[-3].replace('.dcm', '')+'_study')\n\nstudy_df = study_df.merge(test_meta, on='study_id', how='left')\nimage_df = image_df.merge(test_meta, on='image_id', how='left')\n\n# Remove duplicates study_ids from study_df\nstudy_df.drop_duplicates(subset=\"study_id\",keep='first', inplace=True)","metadata":{"papermill":{"duration":5.695531,"end_time":"2021-07-17T19:03:16.105354","exception":false,"start_time":"2021-07-17T19:03:10.409823","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2021-11-24T21:47:27.836638Z","iopub.execute_input":"2021-11-24T21:47:27.838636Z","iopub.status.idle":"2021-11-24T21:47:33.821006Z","shell.execute_reply.started":"2021-11-24T21:47:27.838594Z","shell.execute_reply":"2021-11-24T21:47:33.820070Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<span style=\"color: #00857e; font-family: Segoe UI; font-size: 1.8em; font-weight: 300;\">Fast or Full Predictions</span>\n\nIn case of non-competetion submission commits, we run the notebook with just two images each for image level and study level inference from the public test data.","metadata":{"papermill":{"duration":0.154867,"end_time":"2021-07-17T19:03:16.415952","exception":false,"start_time":"2021-07-17T19:03:16.261085","status":"completed"},"tags":[]}},{"cell_type":"code","source":"fast_sub = False\n\nif sub_df.shape[0] == 2477:\n    fast_sub = True\n    study_df = study_df.sample(2)\n    image_df = image_df.sample(2)\n    \n    print(\"\\nstudy_df\")\n    display(study_df.head(2))\n    print(\"\\nimage_df\")\n    display(image_df.head(2))\n    print(\"\\ntest_meta\")\n    display(test_meta.head(2))","metadata":{"papermill":{"duration":0.28084,"end_time":"2021-07-17T19:03:16.86864","exception":false,"start_time":"2021-07-17T19:03:16.5878","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2021-11-24T21:20:16.800520Z","iopub.execute_input":"2021-11-24T21:20:16.800964Z","iopub.status.idle":"2021-11-24T21:20:16.988410Z","shell.execute_reply.started":"2021-11-24T21:20:16.800933Z","shell.execute_reply":"2021-11-24T21:20:16.987209Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import pydicom\nfrom pydicom.pixel_data_handlers.util import apply_voi_lut\n\nSTUDY_DIMS = (768, 768)\nIMAGE_DIMS = (512, 512)\n\nstudy_dir = f'/kaggle/tmp/test/study/'\nos.makedirs(study_dir, exist_ok=True)\n\nimage_dir = f'/kaggle/tmp/test/image/'\nos.makedirs(image_dir, exist_ok=True)\n\ndef read_xray(path, voi_lut = True, fix_monochrome = True):\n    # Original from: https://www.kaggle.com/raddar/convert-dicom-to-np-array-the-correct-way\n    dicom = pydicom.read_file(path)\n    \n    # VOI LUT (if available by DICOM device) is used to transform raw DICOM data to \n    # \"human-friendly\" view\n    if voi_lut:\n        data = apply_voi_lut(dicom.pixel_array, dicom)\n    else:\n        data = dicom.pixel_array\n               \n    # depending on this value, X-ray may look inverted - fix that:\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    return data\n\ndef resize(array, size, keep_ratio=False, resample=Image.LANCZOS):\n    # Original from: https://www.kaggle.com/xhlulu/vinbigdata-process-and-resize-to-image\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    return im\n\nfor index, row in tqdm(study_df[['study_id', 'dcm_path']].iterrows(), total=study_df.shape[0]):\n    # set keep_ratio=True to have original aspect ratio\n    xray = read_xray(row['dcm_path'])\n    im = resize(xray, size=STUDY_DIMS[0])\n    im.save(os.path.join(study_dir, row['study_id']+'.png'))\n\nimage_df['dim0'] = -1\nimage_df['dim1'] = -1\n\nfor index, row in tqdm(image_df[['image_id', 'dcm_path', 'dim0', 'dim1']].iterrows(), total=image_df.shape[0]):\n    # set keep_ratio=True to have original aspect ratio\n    xray = read_xray(row['dcm_path'])\n    im = resize(xray, size=IMAGE_DIMS[0])  \n    im.save(os.path.join(image_dir, row['image_id']+'.png'))\n    image_df.loc[image_df.image_id==row.image_id, 'dim0'] = xray.shape[0]\n    image_df.loc[image_df.image_id==row.image_id, 'dim1'] = xray.shape[1]","metadata":{"papermill":{"duration":4.178244,"end_time":"2021-07-17T19:03:21.225656","exception":false,"start_time":"2021-07-17T19:03:17.047412","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2021-11-24T21:20:20.950782Z","iopub.execute_input":"2021-11-24T21:20:20.951134Z","iopub.status.idle":"2021-11-24T21:20:25.065472Z","shell.execute_reply.started":"2021-11-24T21:20:20.951103Z","shell.execute_reply":"2021-11-24T21:20:25.064234Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"study_df['image_path'] = study_dir+study_df['study_id']+'.png'\nimage_df['image_path'] = image_dir+image_df['image_id']+'.png'","metadata":{"execution":{"iopub.status.busy":"2021-11-24T21:20:35.603741Z","iopub.execute_input":"2021-11-24T21:20:35.604129Z","iopub.status.idle":"2021-11-24T21:20:35.661636Z","shell.execute_reply.started":"2021-11-24T21:20:35.604098Z","shell.execute_reply":"2021-11-24T21:20:35.660672Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<span style=\"color: #00857e; font-family: Segoe UI; font-size: 1.8em; font-weight: 300;\">Custom Wrapper for Loading TFHub Model trained in TPU</span>\n\nSince the EffNetV2 Classifier models were trained on a TPU with the `tfhub.KerasLayer` formed with the handle argument as a GCS path, while loading the saved model for inference, the method tries to download the pre-trained weights from the definition of the layer from training i.e a GCS path.\n\nSince, inference notebooks don't have GCS and internet access, it is not possible to load the model without the pretrained weights explicitly loaded from the local directory.\n\nIf the models were trained on a GPU, we can use the cache location method to load the pre-trained weights by storing them in a cache folder with the hashed key of the model location, as the folder name. I tried this method here but, it doesn't seem to work as the model was trained with a GCS path defined in the `tfhub.KerasLayer` and the method kept on hitting the GCS path rather than loading the weights from the cache location.\n\nThe only solution was to create a wrapper class to correct the handle argument to load the right pretrained weights explicitly from the local directory.","metadata":{"papermill":{"duration":0.096404,"end_time":"2021-07-17T19:03:21.416262","exception":false,"start_time":"2021-07-17T19:03:21.319858","status":"completed"},"tags":[]}},{"cell_type":"code","source":"import tensorflow as tf\nimport tensorflow_hub as tfhub\n\nMODEL_ARCH = 'efficientnetv2-l-21k-ft1k'\n# Get the TensorFlow Hub model URL\nhub_type = 'feature_vector' # ['classification', 'feature_vector']\nMODEL_ARCH_PATH = f'/kaggle/input/efficientnetv2-tfhub-weight-files/tfhub_models/{MODEL_ARCH}/{hub_type}'\n\n# Custom wrapper class to load the right pretrained weights explicitly from the local directory\nclass KerasLayerWrapper(tfhub.KerasLayer):\n    def __init__(self, handle, **kwargs):\n        handle = tfhub.KerasLayer(tfhub.load(MODEL_ARCH_PATH))\n        super().__init__(handle, **kwargs)","metadata":{"papermill":{"duration":4.259738,"end_time":"2021-07-17T19:03:25.768808","exception":false,"start_time":"2021-07-17T19:03:21.50907","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2021-11-24T21:47:33.822640Z","iopub.execute_input":"2021-11-24T21:47:33.822967Z","iopub.status.idle":"2021-11-24T21:47:37.898666Z","shell.execute_reply.started":"2021-11-24T21:47:33.822934Z","shell.execute_reply":"2021-11-24T21:47:37.897688Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<span style=\"color: #00857e; font-family: Segoe UI; font-size: 1.8em; font-weight: 300;\">Predict Study Level</span>","metadata":{"papermill":{"duration":0.087465,"end_time":"2021-07-17T19:03:25.943841","exception":false,"start_time":"2021-07-17T19:03:25.856376","status":"completed"},"tags":[]}},{"cell_type":"code","source":"MODEL_PATH = '/kaggle/input/siim-effnetv2-keras-study-train-tpu-cv0-805'\ntest_paths = study_df.image_path.tolist()\nBATCH_SIZE = 16\n\ndef build_decoder(with_labels=True, target_size=(300, 300), ext='jpg'):\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    def decode_with_labels(path, label):\n        return decode(path), label\n\n    return decode_with_labels if with_labels else decode\n\ndef build_augmenter(with_labels=True):\n    def augment(img):\n        img = tf.image.random_flip_left_right(img)\n        img = tf.image.random_flip_up_down(img)\n        return img\n\n    def augment_with_labels(img, label):\n        return augment(img), label\n\n    return augment_with_labels if with_labels else augment\n\ndef build_dataset(paths, labels=None, bsize=32, cache=True,\n                  decode_fn=None, augment_fn=None,\n                  augment=True, repeat=True, shuffle=1024, \n                  cache_dir=\"\"):\n    if cache_dir != \"\" and cache is True:\n        os.makedirs(cache_dir, exist_ok=True)\n\n    if decode_fn is None:\n        decode_fn = build_decoder(labels is not None)\n\n    if augment_fn is None:\n        augment_fn = build_augmenter(labels is not None)\n\n    AUTO = tf.data.experimental.AUTOTUNE\n    slices = paths if labels is None else (paths, labels)\n\n    dset = tf.data.Dataset.from_tensor_slices(slices)\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(bsize).prefetch(AUTO)\n\n    return dset\n\n# strategy = auto_select_accelerator()\n# BATCH_SIZE = strategy.num_replicas_in_sync * 16\n\nlabel_cols = ['negative', 'typical', 'indeterminate', 'atypical']\nstudy_df[label_cols] = 0\n\ntest_decoder = build_decoder(with_labels=False,\n                             target_size=(STUDY_DIMS[0],\n                                          STUDY_DIMS[0]), ext='png')\ntest_dataset = build_dataset(\n    test_paths, bsize=BATCH_SIZE, repeat=False, \n    shuffle=False, augment=False, cache=False,\n    decode_fn=test_decoder\n)\n\nwith tf.device('/device:GPU:0'):\n    models = []\n    models0 = tf.keras.models.load_model(f'{MODEL_PATH}/model0.h5',\n                                         custom_objects={'KerasLayer': KerasLayerWrapper})\n    models1 = tf.keras.models.load_model(f'{MODEL_PATH}/model1.h5',\n                                         custom_objects={'KerasLayer': KerasLayerWrapper})\n    models2 = tf.keras.models.load_model(f'{MODEL_PATH}/model2.h5',\n                                         custom_objects={'KerasLayer': KerasLayerWrapper})\n    models3 = tf.keras.models.load_model(f'{MODEL_PATH}/model3.h5',\n                                         custom_objects={'KerasLayer': KerasLayerWrapper})\n    models4 = tf.keras.models.load_model(f'{MODEL_PATH}/model4.h5',\n                                         custom_objects={'KerasLayer': KerasLayerWrapper})\n    models.append(models0)\n    models.append(models1)\n    models.append(models2)\n    models.append(models3)\n    models.append(models4)\n\nstudy_df[label_cols] = sum([model.predict(test_dataset, verbose=1) for model in models]) / len(models)\nstudy_df['PredictionString'] = study_df[label_cols].apply(lambda row: f'negative {row.negative} 0 0 1 1 typical {row.typical} 0 0 1 1 indeterminate {row.indeterminate} 0 0 1 1 atypical {row.atypical} 0 0 1 1', axis=1)\n\ndel models\ndel models0, models1, models2, models3, models4\ndel test_dataset, test_decoder\ngc.collect()","metadata":{"execution":{"iopub.status.busy":"2021-11-24T21:20:44.868300Z","iopub.execute_input":"2021-11-24T21:20:44.869402Z","iopub.status.idle":"2021-11-24T21:25:20.285962Z","shell.execute_reply.started":"2021-11-24T21:20:44.869326Z","shell.execute_reply":"2021-11-24T21:25:20.284613Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"execution":{"iopub.status.busy":"2021-11-24T21:25:20.602176Z","iopub.execute_input":"2021-11-24T21:25:20.603238Z","iopub.status.idle":"2021-11-24T21:25:20.691152Z","shell.execute_reply.started":"2021-11-24T21:25:20.603156Z","shell.execute_reply":"2021-11-24T21:25:20.689747Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<span style=\"color: #00857e; font-family: Segoe UI; font-size: 1.8em; font-weight: 300;\">Predict 2Class Image Level</span>\n\nUsing [@Alien](https://www.kaggle.com/h053473666) 2class model.","metadata":{"papermill":{"duration":0.096091,"end_time":"2021-07-17T19:04:41.039546","exception":false,"start_time":"2021-07-17T19:04:40.943455","status":"completed"},"tags":[]}},{"cell_type":"code","source":"import efficientnet.tfkeras as efn\n\nMODEL_PATH = '/kaggle/input/siim-covid19-efnb7-train-fold0-5-2class'\n\ntest_paths = image_df.image_path.tolist()\nimage_df['none'] = 0\nlabel_cols = ['none']\n\ntest_decoder = build_decoder(with_labels=False,\n                             target_size=(IMAGE_DIMS[0],\n                                          IMAGE_DIMS[0]), ext='png')\ntest_dataset = build_dataset(\n    test_paths, bsize=BATCH_SIZE, repeat=False, \n    shuffle=False, augment=False, cache=False,\n    decode_fn=test_decoder\n)\n\nwith tf.device('/device:GPU:0'):\n    models = []\n    models0 = tf.keras.models.load_model(f'{MODEL_PATH}/model0.h5')\n    models1 = tf.keras.models.load_model(f'{MODEL_PATH}/model1.h5')\n    models2 = tf.keras.models.load_model(f'{MODEL_PATH}/model2.h5')\n    models3 = tf.keras.models.load_model(f'{MODEL_PATH}/model3.h5')\n    models4 = tf.keras.models.load_model(f'{MODEL_PATH}/model4.h5')\n    models.append(models0)\n    models.append(models1)\n    models.append(models2)\n    models.append(models3)\n    models.append(models4)\n\nimage_df[label_cols] = sum([model.predict(test_dataset, verbose=1) for model in models]) / len(models)\n\ndel models\ndel models0, models1, models2, models3, models4\ndel test_dataset, test_decoder\ngc.collect()","metadata":{"papermill":{"duration":123.226242,"end_time":"2021-07-17T19:06:44.363338","exception":false,"start_time":"2021-07-17T19:04:41.137096","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2021-11-24T21:47:37.900011Z","iopub.execute_input":"2021-11-24T21:47:37.900401Z","iopub.status.idle":"2021-11-24T21:47:38.900566Z","shell.execute_reply.started":"2021-11-24T21:47:37.900363Z","shell.execute_reply":"2021-11-24T21:47:38.898634Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"image_df","metadata":{"execution":{"iopub.status.busy":"2021-11-24T21:47:38.901825Z","iopub.status.idle":"2021-11-24T21:47:38.902560Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<span style=\"color: #00857e; font-family: Segoe UI; font-size: 1.8em; font-weight: 300;\">Predict Image Level</span>","metadata":{"papermill":{"duration":0.094734,"end_time":"2021-07-17T19:06:44.55103","exception":false,"start_time":"2021-07-17T19:06:44.456296","status":"completed"},"tags":[]}},{"cell_type":"code","source":"from numba import cuda\nimport torch\ncuda.select_device(0)\ncuda.close()\ncuda.select_device(0)","metadata":{"papermill":{"duration":2.426508,"end_time":"2021-07-17T19:06:47.070269","exception":false,"start_time":"2021-07-17T19:06:44.643761","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2021-11-24T21:47:38.903806Z","iopub.status.idle":"2021-11-24T21:47:38.904423Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from tqdm.notebook import tqdm\n\nimport torch\ndevice = torch.device(\"cuda\") if torch.cuda.is_available() else torch.device(\"cpu\")\nprint(device.type)\n\nimport 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\n\nimport mmcv\nfrom mmcv import Config\nfrom mmcv.runner import load_checkpoint\nfrom mmcv.parallel import MMDataParallel\nfrom mmdet.apis import inference_detector, init_detector, show_result_pyplot\nfrom mmdet.apis import single_gpu_test\nfrom mmdet.datasets import build_dataloader, build_dataset","metadata":{"papermill":{"duration":24.187988,"end_time":"2021-07-17T19:07:11.351071","exception":false,"start_time":"2021-07-17T19:06:47.163083","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2021-11-24T21:47:38.905655Z","iopub.status.idle":"2021-11-24T21:47:38.906343Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import cv2\nimport matplotlib.pyplot as plt\n\nlabel2color = [[59, 238, 119]]\n\nviz_labels =  [\"Covid_Abnormality\"]\n\ndef plot_img(img, size=(18, 18), is_rgb=True, title=\"\", cmap=None):\n    plt.figure(figsize=size)\n    plt.imshow(img, cmap=cmap)\n    plt.suptitle(title)\n    plt.show()\n    \ndef plot_imgs(imgs, cols=2, size=10, is_rgb=True, title=\"\", cmap=None, img_size=None):\n    rows = len(imgs)//cols + 1\n    fig = plt.figure(figsize=(cols*size, rows*size))\n    for i, img in enumerate(imgs):\n        if img_size is not None:\n            img = cv2.resize(img, img_size)\n        fig.add_subplot(rows, cols, i+1)\n        plt.imshow(img, cmap=cmap)\n    plt.suptitle(title)\n    return fig\n    \ndef draw_bbox(image, box, label, color):   \n    alpha = 0.1\n    alpha_font = 0.6\n    thickness = 8\n    font_size = 2.0\n    font_weight = 1\n    overlay_bbox = image.copy()\n    overlay_text = image.copy()\n    output = image.copy()\n\n    text_width, text_height = cv2.getTextSize(label.upper(), cv2.FONT_HERSHEY_SIMPLEX, font_size, font_weight)[0]\n    cv2.rectangle(overlay_bbox, (box[0], box[1]), (box[2], box[3]),\n                color, -1)\n    cv2.addWeighted(overlay_bbox, alpha, output, 1 - alpha, 0, output)\n    cv2.rectangle(overlay_text, (box[0], box[1]-18-text_height), (box[0]+text_width+8, box[1]),\n                (0, 0, 0), -1)\n    cv2.addWeighted(overlay_text, alpha_font, output, 1 - alpha_font, 0, output)\n    cv2.rectangle(output, (box[0], box[1]), (box[2], box[3]),\n                    color, thickness)\n    cv2.putText(output, label.upper(), (box[0], box[1]-12),\n            cv2.FONT_HERSHEY_SIMPLEX, font_size, (255, 255, 255), font_weight, cv2.LINE_AA)\n    return output\n\ndef draw_bbox_small(image, box, label, color):   \n    alpha = 0.1\n    alpha_text = 0.3\n    thickness = 1\n    font_size = 0.4\n    overlay_bbox = image.copy()\n    overlay_text = image.copy()\n    output = image.copy()\n\n    text_width, text_height = cv2.getTextSize(label.upper(), cv2.FONT_HERSHEY_SIMPLEX, font_size, thickness)[0]\n    cv2.rectangle(overlay_bbox, (box[0], box[1]), (box[2], box[3]),\n                color, -1)\n    cv2.addWeighted(overlay_bbox, alpha, output, 1 - alpha, 0, output)\n    cv2.rectangle(overlay_text, (box[0], box[1]-7-text_height), (box[0]+text_width+2, box[1]),\n                (0, 0, 0), -1)\n    cv2.addWeighted(overlay_text, alpha_text, output, 1 - alpha_text, 0, output)\n    cv2.rectangle(output, (box[0], box[1]), (box[2], box[3]),\n                    color, thickness)\n    cv2.putText(output, label.upper(), (box[0], box[1]-5),\n            cv2.FONT_HERSHEY_SIMPLEX, font_size, (255, 255, 255), thickness, cv2.LINE_AA)\n    return output","metadata":{"papermill":{"duration":0.117768,"end_time":"2021-07-17T19:07:28.313348","exception":false,"start_time":"2021-07-17T19:07:28.19558","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2021-11-24T21:47:38.907640Z","iopub.status.idle":"2021-11-24T21:47:38.908283Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"baseline_cfg_path = \"/kaggle/input/siim-mmdetection-cascadercnn-weight-bias/job4_cascade_rcnn_x101_32x4d_fpn_1x_fold0/job4_cascade_rcnn_x101_32x4d_fpn_1x_coco.py\"\ncfg = Config.fromfile(baseline_cfg_path)\n\ncfg.classes = (\"Covid_Abnormality\")\ncfg.data.test.img_prefix = ''\ncfg.data.test.classes = cfg.classes\n\n# cfg.model.roi_head.bbox_head.num_classes = 1\n# cfg.model.bbox_head.num_classes = 1\nfor head in cfg.model.roi_head.bbox_head:\n    head.num_classes = 1\n\n# Set seed thus the results are more reproducible\ncfg.seed = 211\nset_random_seed(211, deterministic=False)\ncfg.gpu_ids = [0]\n\ncfg.data.test.pipeline=[\n            dict(type='LoadImageFromFile'),\n            dict(\n                type='MultiScaleFlipAug',\n                img_scale=(1333, 800),\n                flip=False,\n                transforms=[\n                    dict(type='Resize', keep_ratio=True),\n                    dict(type='RandomFlip', direction='horizontal'),\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'])\n                ])\n        ]\n\ncfg.test_pipeline = [\n            dict(type='LoadImageFromFile'),\n            dict(\n                type='MultiScaleFlipAug',\n                img_scale=(1333, 800),\n                flip=False,\n                transforms=[\n                    dict(type='Resize', keep_ratio=True),\n                    dict(type='RandomFlip', direction='horizontal'),\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'])\n                ])\n        ]\n\n# cfg.data.samples_per_gpu = 4\n# cfg.data.workers_per_gpu = 4\n# cfg.model.test_cfg.nms.iou_threshold = 0.3\ncfg.model.test_cfg.rcnn.score_thr = 0.001\n\nWEIGHTS_FILE = '/kaggle/input/siim-mmdetection-cascadercnn-weight-bias/job4_cascade_rcnn_x101_32x4d_fpn_1x_fold0/epoch_10.pth'\noptions = dict(classes = (\"Covid_Abnormality\"))\nmodel = init_detector(cfg, WEIGHTS_FILE, device='cuda:0')","metadata":{"papermill":{"duration":16.649888,"end_time":"2021-07-17T19:07:28.101611","exception":false,"start_time":"2021-07-17T19:07:11.451723","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2021-11-24T21:47:38.909642Z","iopub.status.idle":"2021-11-24T21:47:38.910394Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from ensemble_boxes import weighted_boxes_fusion, nms\n\nviz_images = []\nresults = []\nscore_threshold = cfg.model.test_cfg.rcnn.score_thr\n\ndef format_pred(boxes: np.ndarray, scores: np.ndarray, labels: np.ndarray) -> str:\n    pred_strings = []\n    label_str = ['opacity']\n    for label, score, bbox in zip(labels, scores, boxes):\n        xmin, ymin, xmax, ymax = bbox.astype(np.int64)\n        pred_strings.append(f\"{label_str[int(label)]} {score:.16f} {xmin} {ymin} {xmax} {ymax}\")\n    return \" \".join(pred_strings)\n\nmodel.to(device)\nmodel.eval()\n\nviz_images = []\n\nwith torch.no_grad():\n    for index, row in tqdm(image_df.iterrows(), total=image_df.shape[0]):\n        original_H, original_W = (int(row.dim0), int(row.dim1))\n        predictions = inference_detector(model, row.image_path)\n        boxes, scores, labels = (list(), list(), list())\n\n        for k, cls_result in enumerate(predictions):\n#             print(\"cls_result\", cls_result)\n            if cls_result.size != 0:\n                if len(labels)==0:\n                    boxes = np.array(cls_result[:, :4])\n                    scores = np.array(cls_result[:, 4])\n                    labels = np.array([k]*len(cls_result[:, 4]))\n                else:    \n                    boxes = np.concatenate((boxes, np.array(cls_result[:, :4])))\n                    scores = np.concatenate((scores, np.array(cls_result[:, 4])))\n                    labels = np.concatenate((labels, [k]*len(cls_result[:, 4])))\n                    \n            if fast_sub:\n                img_viz = cv2.imread(row.image_path)\n                for box, label, score in zip(boxes, labels, scores):\n                    color = label2color[int(label)]\n                    img_viz = draw_bbox_small(img_viz, box.astype(np.int32), f'opacity_{score:.4f}', color)\n                viz_images.append(img_viz)\n\n        indexes = np.where(scores > score_threshold)\n#         print(indexes)\n        boxes = boxes[indexes]\n        scores = scores[indexes]\n        labels = labels[indexes]\n\n        if len(labels) != 0:\n            h_ratio = original_H/IMAGE_DIMS[0]\n            w_ratio = original_W/IMAGE_DIMS[1]\n            boxes[:, [0, 2]] *= w_ratio\n            boxes[:, [1, 3]] *= h_ratio\n\n            result = {\n                \"id\": row.image_id,\n                \"PredictionString\": format_pred(\n                    boxes, scores, labels\n                ),\n            }\n\n            results.append(result)\ndel model\ngc.collect()\n\ndetection_df = pd.DataFrame(results, columns=['id', 'PredictionString'])\n\nif fast_sub:\n    display(detection_df.sample(2))\n    # Plot sample images\n    plot_imgs(viz_images, cmap=None)\n    plt.savefig('viz_fig_siim.png', bbox_inches='tight')\n    plt.show()","metadata":{"papermill":{"duration":2.481425,"end_time":"2021-07-17T19:07:30.8895","exception":false,"start_time":"2021-07-17T19:07:28.408075","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2021-11-24T21:47:38.912809Z","iopub.status.idle":"2021-11-24T21:47:38.913607Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"detection_df = detection_df.merge(image_df[['image_id', 'none']].rename({'image_id':'id'}, axis=1),\n                                  on='id', how='left')\n\nfor i in range(detection_df.shape[0]):\n    if detection_df.loc[i,'PredictionString'] != 'none 1 0 0 1 1':\n        detection_df.loc[i,'PredictionString'] = detection_df.loc[i,'PredictionString'] + ' none ' + str(detection_df.loc[i,'none']) + ' 0 0 1 1'\ndetection_df = detection_df[['id', 'PredictionString']]\n\nresults_df = study_df[['study_id', 'PredictionString']].rename({'study_id':'id'}, axis=1)\nresults_df = results_df.append(detection_df[['id', 'PredictionString']])","metadata":{"papermill":{"duration":0.130739,"end_time":"2021-07-17T19:07:31.131057","exception":false,"start_time":"2021-07-17T19:07:31.000318","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2021-11-24T21:47:38.914802Z","iopub.status.idle":"2021-11-24T21:47:38.915599Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sub_df = pd.read_csv('/kaggle/input/siim-covid19-detection/sample_submission.csv')\nsub_df['PredictionString'] = np.nan\nsub_df = sub_df.set_index('id')\nresults_df = results_df.set_index('id')\nsub_df.update(results_df)\nsub_df = sub_df.reset_index()\nsub_df = sub_df.fillna(\"none 1 0 0 1 1\")\nsub_df.to_csv('/kaggle/working/submission.csv', index=False)\n\nif fast_sub:\n    display(sub_df.head(2))","metadata":{"papermill":{"duration":0.305787,"end_time":"2021-07-17T19:07:31.547349","exception":false,"start_time":"2021-07-17T19:07:31.241562","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2021-11-24T21:47:38.916817Z","iopub.status.idle":"2021-11-24T21:47:38.917601Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sub_df = pd.read_csv('/kaggle/input/siim-covid19-detection/sample_submission.csv')\nsub_df['PredictionString'] = np.nan\n# sub_df = sub_df.set_index('id')\nsub_df.head(5)","metadata":{"execution":{"iopub.status.busy":"2021-11-24T21:47:38.918860Z","iopub.status.idle":"2021-11-24T21:47:38.919769Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!rm -r /kaggle/working/mmdetection","metadata":{"papermill":{"duration":0.363451,"end_time":"2021-07-17T19:07:32.023003","exception":false,"start_time":"2021-07-17T19:07:31.659552","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2021-11-24T21:47:38.921058Z","iopub.status.idle":"2021-11-24T21:47:38.921932Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<p style='text-align: center;'><span style=\"color: #000508; font-family: Segoe UI; font-size: 2.4em; font-weight: 300;\">HAVE A GREAT DAY!</span></p>\n\n<p style='text-align: center;'><span style=\"color: #000508; font-family: Segoe UI; font-size: 1.4em; font-weight: 300;\">Let me know if you have any suggestions!</span></p>","metadata":{}}]}