{"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":"code","source":"!conda install '/kaggle/input/pydicom-conda-helper/libjpeg-turbo-2.1.0-h7f98852_0.tar.bz2' -c conda-forge -yq\n!conda install '/kaggle/input/pydicom-conda-helper/libgcc-ng-9.3.0-h2828fa1_19.tar.bz2' -c conda-forge -yq\n!conda install '/kaggle/input/pydicom-conda-helper/gdcm-2.8.9-py37h500ead1_1.tar.bz2' -c conda-forge -yq\n!conda install '/kaggle/input/pydicom-conda-helper/conda-4.10.1-py37h89c1867_0.tar.bz2' -c conda-forge -yq\n!conda install '/kaggle/input/pydicom-conda-helper/certifi-2020.12.5-py37h89c1867_1.tar.bz2' -c conda-forge -yq\n!conda install '/kaggle/input/pydicom-conda-helper/openssl-1.1.1k-h7f98852_0.tar.bz2' -c conda-forge -yq","metadata":{"execution":{"iopub.status.busy":"2021-07-21T04:46:13.748190Z","iopub.execute_input":"2021-07-21T04:46:13.748499Z","iopub.status.idle":"2021-07-21T04:47:26.688053Z","shell.execute_reply.started":"2021-07-21T04:46:13.748469Z","shell.execute_reply":"2021-07-21T04:47:26.687163Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import gc\nimport os\nfrom pathlib import Path\nimport random\nimport sys\n\nfrom tqdm.notebook import tqdm\nimport numpy as np\nimport pandas as pd\nimport scipy as sp\n\n\nimport matplotlib.pyplot as plt\nimport seaborn as sns\n\nfrom IPython.core.display import display, HTML\n\n# --- plotly ---\nfrom plotly import tools, subplots\nimport plotly.offline as py\npy.init_notebook_mode(connected=True)\nimport plotly.graph_objs as go\nimport plotly.express as px\nimport plotly.figure_factory as ff\nimport plotly.io as pio\npio.templates.default = \"plotly_dark\"\n\n# --- models ---\nfrom sklearn import preprocessing\nfrom sklearn.model_selection import KFold\nimport lightgbm as lgb\nimport xgboost as xgb\nimport catboost as cb\n\n# --- setup ---\npd.set_option('max_columns', 50)\n\nfrom fastai.vision.all import *","metadata":{"execution":{"iopub.status.busy":"2021-07-21T04:47:26.692239Z","iopub.execute_input":"2021-07-21T04:47:26.692556Z","iopub.status.idle":"2021-07-21T04:47:34.239810Z","shell.execute_reply.started":"2021-07-21T04:47:26.692513Z","shell.execute_reply":"2021-07-21T04:47:34.238998Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# DCM to PNG","metadata":{}},{"cell_type":"code","source":"sample_sub = pd.read_csv(\"../input/siim-covid19-detection/sample_submission.csv\")\ntest_dicom_files = get_files(\"../input/siim-covid19-detection/test/\")\nassert len(set(o.parent.parent.name for o in test_dicom_files)) + len(test_dicom_files) == sample_sub.shape[0]","metadata":{"execution":{"iopub.status.busy":"2021-07-21T04:47:34.241180Z","iopub.execute_input":"2021-07-21T04:47:34.241520Z","iopub.status.idle":"2021-07-21T04:47:38.715749Z","shell.execute_reply.started":"2021-07-21T04:47:34.241483Z","shell.execute_reply":"2021-07-21T04:47:38.714725Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"DEBUG  = True","metadata":{"execution":{"iopub.status.busy":"2021-07-21T04:47:38.717156Z","iopub.execute_input":"2021-07-21T04:47:38.717573Z","iopub.status.idle":"2021-07-21T04:47:38.724370Z","shell.execute_reply.started":"2021-07-21T04:47:38.717535Z","shell.execute_reply":"2021-07-21T04:47:38.723505Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"if len(test_dicom_files) == 1263 and DEBUG: test_dicom_files = test_dicom_files[:32]\ntest_image_ids = L(map(lambda o: o.stem, test_dicom_files)); len(test_image_ids)","metadata":{"execution":{"iopub.status.busy":"2021-07-21T04:47:38.728370Z","iopub.execute_input":"2021-07-21T04:47:38.728662Z","iopub.status.idle":"2021-07-21T04:47:38.770062Z","shell.execute_reply.started":"2021-07-21T04:47:38.728629Z","shell.execute_reply":"2021-07-21T04:47:38.769235Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import pydicom\nfrom pydicom.pixel_data_handlers.util import apply_voi_lut\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        \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    \n    return im","metadata":{"execution":{"iopub.status.busy":"2021-07-21T04:47:38.773450Z","iopub.execute_input":"2021-07-21T04:47:38.774077Z","iopub.status.idle":"2021-07-21T04:47:39.045635Z","shell.execute_reply.started":"2021-07-21T04:47:38.774033Z","shell.execute_reply":"2021-07-21T04:47:39.044504Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"RESIZE = 512\nsave_dir = Path(f'/kaggle/working/test_images_{RESIZE}')\nos.makedirs(save_dir, exist_ok=True)\n\nimageid2size = {} #save original shape\nstudyid2imageids = defaultdict(list) # save study ids to image ids for study level preds\n\nfor file in progress_bar(test_dicom_files):\n    # set keep_ratio=True to have original aspect ratio\n    image_id = file.stem\n    study_id = file.parent.parent.name\n    studyid2imageids[study_id].append(image_id)\n    xray = read_xray(file)\n    imageid2size[image_id] = xray.shape\n    im = resize(xray, size=RESIZE)  \n    im.save(save_dir/f\"{image_id}.png\")","metadata":{"execution":{"iopub.status.busy":"2021-07-21T04:47:39.047275Z","iopub.execute_input":"2021-07-21T04:47:39.047639Z","iopub.status.idle":"2021-07-21T04:48:00.375973Z","shell.execute_reply.started":"2021-07-21T04:47:39.047601Z","shell.execute_reply":"2021-07-21T04:48:00.374889Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# RESIZE = 384\n# save_dir = Path(f'/kaggle/working/test_images_{RESIZE}')\n# os.makedirs(save_dir, exist_ok=True)\n\n# for file in progress_bar(test_dicom_files):\n#     # set keep_ratio=True to have original aspect ratio\n#     image_id = file.stem\n#     xray = read_xray(file)\n#     im = resize(xray, size=RESIZE)  \n#     im.save(save_dir/f\"{image_id}.png\")","metadata":{"execution":{"iopub.status.busy":"2021-07-21T04:48:00.377317Z","iopub.execute_input":"2021-07-21T04:48:00.377696Z","iopub.status.idle":"2021-07-21T04:48:00.383406Z","shell.execute_reply.started":"2021-07-21T04:48:00.377656Z","shell.execute_reply":"2021-07-21T04:48:00.382564Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"image_id2study_id = {o.stem:o.parent.parent.name for o in test_dicom_files}; len(image_id2study_id)","metadata":{"execution":{"iopub.status.busy":"2021-07-21T04:48:00.384696Z","iopub.execute_input":"2021-07-21T04:48:00.385125Z","iopub.status.idle":"2021-07-21T04:48:00.407266Z","shell.execute_reply.started":"2021-07-21T04:48:00.385084Z","shell.execute_reply":"2021-07-21T04:48:00.406315Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Detection (Detectron2)","metadata":{}},{"cell_type":"code","source":"!nvcc --version","metadata":{"execution":{"iopub.status.busy":"2021-07-21T04:48:00.408659Z","iopub.execute_input":"2021-07-21T04:48:00.409088Z","iopub.status.idle":"2021-07-21T04:48:01.061409Z","shell.execute_reply.started":"2021-07-21T04:48:00.409008Z","shell.execute_reply":"2021-07-21T04:48:01.060084Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!pip install -q ../input/detectron2-whl/pycocotools-2.0.2/dist/pycocotools-2.0.2.tar # pycocotools\n!pip install -q ../input/detectron2-whl/omegaconf-2.0.6-py3-none-any.whl # omegaconf\n!pip install -q ../input/detectron2-whl/iopath-0.1.8-py3-none-any.whl # iopath\n!pip install -q ../input/detectron2-whl/fvcore-master/fvcore-master # fvcore\n!pip install -q ../input/detectron2-whl/detectron2-0.4cu102-cp37-cp37m-linux_x86_64.whl --no-deps","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2021-07-21T04:48:01.066664Z","iopub.execute_input":"2021-07-21T04:48:01.067092Z","iopub.status.idle":"2021-07-21T04:50:19.789600Z","shell.execute_reply.started":"2021-07-21T04:48:01.067044Z","shell.execute_reply":"2021-07-21T04:50:19.788561Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<a id=\"pred_method\"></a>\n## Prediction method implementations\n\nBasically we don't need to implement neural network part, `detectron2` already implements famous architectures and provides its pre-trained weights. We can finetune these pre-trained architectures.\n\nThese models are summarized in [MODEL_ZOO.md](https://github.com/facebookresearch/detectron2/blob/master/MODEL_ZOO.md).\n\nIn this competition, we need object detection model, I will choose [R50-FPN](https://github.com/facebookresearch/detectron2/blob/master/configs/COCO-Detection/faster_rcnn_R_50_FPN_3x.yaml) for this kernel.","metadata":{}},{"cell_type":"markdown","source":"## Data preparation\n\n`detectron2` provides high-level API for training custom dataset.\n\nTo define custom dataset, we need to create **list of dict** where each dict contains following:\n\n - file_name: file name of the image.\n - image_id: id of the image, index is used here.\n - height: height of the image.\n - width: width of the image.\n - annotation: This is the ground truth annotation data for object detection, which contains following\n     - bbox: bounding box pixel location with shape (n_boxes, 4)\n     - bbox_mode: `BoxMode.XYXY_ABS` is used here, meaning that absolute value of (xmin, ymin, xmax, ymax) annotation is used in the `bbox`.\n     - category_id: class label id for each bounding box, with shape (n_boxes,)\n\n`get_vinbigdata_dicts` is for train dataset preparation and `get_vinbigdata_dicts_test` is for test dataset preparation.","metadata":{}},{"cell_type":"markdown","source":"### Prepare Data","metadata":{}},{"cell_type":"code","source":"import pickle\nfrom pathlib import Path\nfrom typing import Optional\n\nimport cv2\nimport numpy as np\nimport pandas as pd\nfrom detectron2.structures import BoxMode\nfrom tqdm import tqdm\n\nfrom sklearn.model_selection import StratifiedKFold","metadata":{"execution":{"iopub.status.busy":"2021-07-21T04:50:19.793514Z","iopub.execute_input":"2021-07-21T04:50:19.793793Z","iopub.status.idle":"2021-07-21T04:50:19.994883Z","shell.execute_reply.started":"2021-07-21T04:50:19.793764Z","shell.execute_reply":"2021-07-21T04:50:19.993972Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_image_ids[:3]","metadata":{"execution":{"iopub.status.busy":"2021-07-21T04:50:19.996552Z","iopub.execute_input":"2021-07-21T04:50:19.996973Z","iopub.status.idle":"2021-07-21T04:50:20.006367Z","shell.execute_reply.started":"2021-07-21T04:50:19.996900Z","shell.execute_reply":"2021-07-21T04:50:20.005127Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_test_datasetdicts(test_image_ids, resized_height=512,resized_width=512):\n\n    dataset_dicts = []\n    for image_id in progress_bar(test_image_ids):\n        record = {}\n\n        record[\"file_name\"] = f\"/kaggle/working/test_images_512/{image_id}.png\"\n        record[\"image_id\"] = image_id\n        dataset_dicts.append(record)\n    return dataset_dicts","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2021-07-21T04:50:20.008074Z","iopub.execute_input":"2021-07-21T04:50:20.008570Z","iopub.status.idle":"2021-07-21T04:50:20.017707Z","shell.execute_reply.started":"2021-07-21T04:50:20.008517Z","shell.execute_reply":"2021-07-21T04:50:20.016320Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"datasetdicts = get_test_datasetdicts(test_image_ids)\ndatasetdicts[:3]","metadata":{"execution":{"iopub.status.busy":"2021-07-21T04:50:20.019520Z","iopub.execute_input":"2021-07-21T04:50:20.020023Z","iopub.status.idle":"2021-07-21T04:50:20.046273Z","shell.execute_reply.started":"2021-07-21T04:50:20.019981Z","shell.execute_reply":"2021-07-21T04:50:20.045241Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Methods for prediction for this competition","metadata":{}},{"cell_type":"code","source":"# Methods for prediction for this competition\nfrom math import ceil\nfrom typing import Any, Dict, List\n\nimport cv2\nimport detectron2\nimport numpy as np\nfrom numpy import ndarray\nimport pandas as pd\nimport torch\nfrom detectron2 import model_zoo\nfrom detectron2.config import get_cfg\nfrom detectron2.data import DatasetCatalog, MetadataCatalog, build_detection_test_loader\nfrom detectron2.engine import DefaultPredictor\nfrom detectron2.evaluation import COCOEvaluator, inference_on_dataset\nfrom detectron2.structures import BoxMode\nfrom detectron2.utils.logger import setup_logger\nfrom detectron2.utils.visualizer import ColorMode, Visualizer\nfrom tqdm import tqdm\n\n\ndef format_pred(labels: ndarray, boxes: ndarray, scores: ndarray) -> str:\n    pred_strings = []\n#     class_names = ['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} {score} {xmin} {ymin} {xmax} {ymax}\")\n        pred_strings.append(f\"opacity {score} {xmin} {ymin} {xmax} {ymax}\")\n    return \" \".join(pred_strings)\n\n\ndef predict_batch(predictor: DefaultPredictor, im_list: List[ndarray]) -> List:\n    with torch.no_grad():  # https://github.com/sphinx-doc/sphinx/issues/4258\n        inputs_list = []\n        for original_image in im_list:\n            # Apply pre-processing to image.\n            if predictor.input_format == \"RGB\":\n                # whether the model expects BGR inputs or RGB\n                original_image = original_image[:, :, ::-1]\n            height, width = original_image.shape[:2]\n            # Do not apply original augmentation, which is resize.\n            # image = predictor.aug.get_transform(original_image).apply_image(original_image)\n            image = original_image\n            image = torch.as_tensor(image.astype(\"float32\").transpose(2, 0, 1))\n            inputs = {\"image\": image, \"height\": height, \"width\": width}\n            inputs_list.append(inputs)\n        predictions = predictor.model(inputs_list)\n        return predictions\n    \ndef predict_batch(predictor: DefaultPredictor, im_list: List[ndarray]) -> List:\n    with torch.no_grad():  # https://github.com/sphinx-doc/sphinx/issues/4258\n        inputs_list = []\n        inputs_list_tta = []\n        for original_image in im_list:\n            # Apply pre-processing to image.\n            if predictor.input_format == \"RGB\":\n                # whether the model expects BGR inputs or RGB\n                original_image = original_image[:, :, ::-1]\n            height, width = original_image.shape[:2]\n            # Do not apply original augmentation, which is resize.\n            # image = predictor.aug.get_transform(original_image).apply_image(original_image)\n            image = original_image\n            image = torch.as_tensor(image.astype(\"float32\").transpose(2, 0, 1))\n            inputs = {\"image\": image, \"height\": height, \"width\": width}\n            inputs_list.append(inputs)\n            inputs_tta = {\"image\": image.flip(dims=[2]), \"height\": height, \"width\": width}\n            inputs_list_tta.append(inputs_tta)\n        \n        predictions     = predictor.model(inputs_list)\n        predictions_tta = predictor.model(inputs_list_tta)\n        return predictions, predictions_tta","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2021-07-21T04:50:20.047643Z","iopub.execute_input":"2021-07-21T04:50:20.048010Z","iopub.status.idle":"2021-07-21T04:50:20.167692Z","shell.execute_reply.started":"2021-07-21T04:50:20.047974Z","shell.execute_reply":"2021-07-21T04:50:20.167000Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# --- utils ---\nfrom pathlib import Path\nfrom typing import Any, Union\n\nimport yaml\n\n\ndef save_yaml(filepath: Union[str, Path], content: Any, width: int = 120):\n    with open(filepath, \"w\") as f:\n        yaml.dump(content, f, width=width)\n\n\ndef load_yaml(filepath: Union[str, Path]) -> Any:\n    with open(filepath, \"r\") as f:\n        content = yaml.full_load(f)\n    return content\n","metadata":{"_kg_hide-input":true,"_kg_hide-output":true,"execution":{"iopub.status.busy":"2021-07-21T04:50:20.169659Z","iopub.execute_input":"2021-07-21T04:50:20.169898Z","iopub.status.idle":"2021-07-21T04:50:20.180717Z","shell.execute_reply.started":"2021-07-21T04:50:20.169874Z","shell.execute_reply":"2021-07-21T04:50:20.179833Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# --- configs ---\nthing_classes = [\"opacity\"]\ncategory_name_to_id = {class_name: index for index, class_name in enumerate(thing_classes)}\ncategory_name_to_id","metadata":{"execution":{"iopub.status.busy":"2021-07-21T04:50:20.182229Z","iopub.execute_input":"2021-07-21T04:50:20.182642Z","iopub.status.idle":"2021-07-21T04:50:20.190406Z","shell.execute_reply.started":"2021-07-21T04:50:20.182604Z","shell.execute_reply":"2021-07-21T04:50:20.189268Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"This `Flags` class is to manage experiments. I will tune these parameters through the competition to improve model's performance.","metadata":{}},{"cell_type":"code","source":"# --- flags ---\nfrom dataclasses import dataclass, field\nfrom typing import Dict\n\n\n@dataclass\nclass Flags:\n    # General\n    debug: bool = True\n    outdir: str = \"results/det\"\n\n    # Data config\n    imgdir_name: str = \"siim-covid19-resized-to-512px-png\"\n    split_mode: str = \"all_train\"  # all_train or kfold\n    fold_num: int = 0\n    use_negative_class: bool = False\n    oversample_classes = False\n    seed: int = 111\n    train_data_type: str = \"original\"  # original or wbf\n    # Training config\n    iter: int = 10000\n    checkpoint_iter: int = 2000\n    ims_per_batch: int = 24 # images per batch, this corresponds to \"total batch size\"\n    num_workers: int = 4\n    lr_scheduler_name: str = \"WarmupMultiStepLR\"  # WarmupMultiStepLR (default) or WarmupCosineLR\n    base_lr: float = 0.00025\n    roi_batch_size_per_image: int = 512\n    eval_period: int = 10000\n    aug_kwargs: Dict = field(default_factory=lambda: {})\n\n    def update(self, param_dict: Dict) -> \"Flags\":\n        # Overwrite by `param_dict`\n        for key, value in param_dict.items():\n            if not hasattr(self, key):\n                raise ValueError(f\"[ERROR] Unexpected key for flag = {key}\")\n            setattr(self, key, value)\n        return self","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2021-07-21T04:50:20.192396Z","iopub.execute_input":"2021-07-21T04:50:20.192897Z","iopub.status.idle":"2021-07-21T04:50:20.208814Z","shell.execute_reply.started":"2021-07-21T04:50:20.192824Z","shell.execute_reply":"2021-07-21T04:50:20.207637Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<a id=\"pred_scripts\"></a>\n### Prediction scripts\n\nNow the methods are ready. Main training scripts starts from here.","metadata":{}},{"cell_type":"code","source":"inputdir = Path(\"/kaggle/input/\")\n# traineddir = inputdir / \"covid19-detectron2-models/RN101/results/RN101_with_negative_False\"\ntraineddir = inputdir / \"covid19-detectron2-models/RN101-full/RN101-full\"\n\n# flags = Flags()\nflags: Flags = Flags().update(load_yaml(str(traineddir/\"flags.yaml\")))\nprint(\"flags\", flags)\ndebug = flags.debug\n# flags_dict = dataclasses.asdict(flags)\noutdir = Path(flags.outdir)\nos.makedirs(str(outdir), exist_ok=True)\n\n# --- Read data ---\ndatadir = Path(\"/kaggle/working/\") \nimgdir = inputdir / \"test_images_512\"","metadata":{"execution":{"iopub.status.busy":"2021-07-21T04:50:21.096659Z","iopub.execute_input":"2021-07-21T04:50:21.097058Z","iopub.status.idle":"2021-07-21T04:50:21.122368Z","shell.execute_reply.started":"2021-07-21T04:50:21.097017Z","shell.execute_reply":"2021-07-21T04:50:21.121670Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"cfg = get_cfg()\noriginal_output_dir = cfg.OUTPUT_DIR\ncfg.OUTPUT_DIR = str(outdir)\nprint(f\"cfg.OUTPUT_DIR {original_output_dir} -> {cfg.OUTPUT_DIR}\")\n\ncfg.merge_from_file(model_zoo.get_config_file(\"COCO-Detection/faster_rcnn_R_101_FPN_3x.yaml\"))\ncfg.DATASETS.TRAIN = (\"siim_covid19_train\",)\ncfg.DATASETS.TEST = ()\n# cfg.DATASETS.TEST = (\"vinbigdata_train\",)\n# cfg.TEST.EVAL_PERIOD = 50\ncfg.DATALOADER.NUM_WORKERS = 2\n# Let training initialize from model zoo\ncfg.MODEL.WEIGHTS = model_zoo.get_checkpoint_url(\"COCO-Detection/faster_rcnn_R_101_FPN_3x.yaml\")\ncfg.SOLVER.IMS_PER_BATCH = 2\ncfg.SOLVER.BASE_LR = flags.base_lr  # pick a good LR\ncfg.SOLVER.MAX_ITER = flags.iter\ncfg.MODEL.ROI_HEADS.BATCH_SIZE_PER_IMAGE = flags.roi_batch_size_per_image\ncfg.MODEL.ROI_HEADS.NUM_CLASSES = len(thing_classes)\n# NOTE: this config means the number of classes, but a few popular unofficial tutorials incorrect uses num_classes+1 here.\n\n### --- Inference & Evaluation ---\n# Inference should use the config with parameters that are used in training\n# cfg now already contains everything we've set previously. We changed it a little bit for inference:\n# path to the model we just trained\ncfg.MODEL.WEIGHTS = str(traineddir/\"model_final.pth\")\nprint(\"Original thresh\", cfg.MODEL.ROI_HEADS.SCORE_THRESH_TEST)  # 0.05\ncfg.MODEL.ROI_HEADS.SCORE_THRESH_TEST = 0.0  # set a custom testing threshold\nprint(\"Changed  thresh\", cfg.MODEL.ROI_HEADS.SCORE_THRESH_TEST)\npredictor = DefaultPredictor(cfg)","metadata":{"execution":{"iopub.status.busy":"2021-07-21T04:50:21.123645Z","iopub.execute_input":"2021-07-21T04:50:21.124178Z","iopub.status.idle":"2021-07-21T04:50:34.287845Z","shell.execute_reply.started":"2021-07-21T04:50:21.124145Z","shell.execute_reply":"2021-07-21T04:50:34.286825Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"DatasetCatalog.register(\"siim_covid19_test\", lambda: get_test_datasetdicts(test_image_files))\nMetadataCatalog.get(\"siim_covid19_test\").set(thing_classes=thing_classes)\nmetadata = MetadataCatalog.get(\"siim_covid19_test\")","metadata":{"execution":{"iopub.status.busy":"2021-07-21T04:50:34.289448Z","iopub.execute_input":"2021-07-21T04:50:34.289835Z","iopub.status.idle":"2021-07-21T04:50:34.302738Z","shell.execute_reply.started":"2021-07-21T04:50:34.289792Z","shell.execute_reply":"2021-07-21T04:50:34.294805Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"dataset_dicts = get_test_datasetdicts(test_image_ids)\ndataset_dicts[:3]","metadata":{"execution":{"iopub.status.busy":"2021-07-21T04:50:34.304441Z","iopub.execute_input":"2021-07-21T04:50:34.304870Z","iopub.status.idle":"2021-07-21T04:50:34.332872Z","shell.execute_reply.started":"2021-07-21T04:50:34.304816Z","shell.execute_reply":"2021-07-21T04:50:34.332072Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"results_list = []\nindex = 0\nbatch_size = 4\n\nboxes,scores,labels,dims = [],[],[],[]\nboxes_tta,scores_tta,labels_tta,dims_tta = [],[],[],[]\n\nfor i in tqdm(range(ceil(len(dataset_dicts) / batch_size))):\n    \n    # predict batch\n    inds = list(range(batch_size * i, min(batch_size * (i + 1), len(dataset_dicts))))\n    dataset_dicts_batch = [dataset_dicts[i] for i in inds]\n    im_list       = [cv2.imread(d[\"file_name\"]) for d in dataset_dicts_batch]\n    image_id_list = [d[\"image_id\"] for d in dataset_dicts_batch]\n    outputs_list, outputs_list_tta = predict_batch(predictor, im_list)\n    \n    for im, image_id, outputs, outputs_tta, d in zip(im_list, image_id_list, outputs_list, outputs_list_tta, dataset_dicts_batch):\n        resized_height, resized_width, ch = im.shape\n        \n        # visualize few predictions\n        if index < 5:\n            # format is documented at https://detectron2.readthedocs.io/tutorials/models.html#model-output-format\n            v = Visualizer(\n                im[:, :, ::-1],\n                metadata=metadata,\n                scale=0.5,\n                instance_mode=ColorMode.IMAGE_BW\n                # remove the colors of unsegmented pixels. This option is only available for segmentation models\n            )\n            out = v.draw_instance_predictions(outputs[\"instances\"].to(\"cpu\"))\n            cv2.imwrite(str(outdir / f\"pred_{index}.jpg\"), out.get_image()[:, :, ::-1])\n\n        dim0, dim1 = imageid2size[image_id]\n        \n        # post-process\n        instances = outputs[\"instances\"]\n        instances_tta = outputs_tta[\"instances\"]\n\n        if len(instances) == 0:\n            # Negative/No Finding, let's set none 1 0 0 1 1.\n            result = {\"image_id\": image_id, \"PredictionString\": \"none 1 0 0 1 1\"}\n            \n        else:\n            # Find some bbox...\n            # print(f\"index={index}, find {len(instances)} bbox.\")\n            fields = instances.get_fields()\n            fields_tta = instances_tta.get_fields()\n                \n            pred_classes = fields[\"pred_classes\"]  # (n_boxes,)\n            pred_scores = fields[\"scores\"]\n            pred_boxes = fields[\"pred_boxes\"].tensor # shape (n_boxes, 4). (xmin, ymin, xmax, ymax)\n            \n            pred_classes_tta = fields_tta[\"pred_classes\"]  # (n_boxes,)\n            pred_scores_tta = fields_tta[\"scores\"]\n            pred_boxes_tta = fields_tta[\"pred_boxes\"].tensor # shape (n_boxes, 4). (xmin, ymin, xmax, ymax)\n            \n            h_ratio = dim0 / resized_height\n            w_ratio = dim1 / resized_width\n            pred_boxes[:, [0, 2]] *= w_ratio\n            pred_boxes[:, [1, 3]] *= h_ratio\n            pred_boxes_tta[:, [0, 2]] *= w_ratio\n            pred_boxes_tta[:, [1, 3]] *= h_ratio            \n            # revert flip tta\n            pred_boxes_tta[:, [0, 2]] = (dim1 - pred_boxes_tta[:, [0, 2]]).flip(dims=[1]) \n            \n            \n            pred_classes_array = pred_classes.cpu().numpy()\n            pred_boxes_array = pred_boxes.cpu().numpy()\n            pred_scores_array = pred_scores.cpu().numpy()\n            \n            pred_classes_tta_array = pred_classes_tta.cpu().numpy()\n            pred_boxes_tta_array = pred_boxes_tta.cpu().numpy()\n            pred_scores_tta_array = pred_scores_tta.cpu().numpy()\n            \n            pred_boxes_normalized_array = pred_boxes_array.copy()\n            pred_boxes_normalized_tta_array = pred_boxes_tta_array.copy()\n            pred_boxes_normalized_array[:, [0, 2]] /= dim1\n            pred_boxes_normalized_array[:, [1, 3]] /= dim0\n            pred_boxes_normalized_tta_array[:, [0, 2]] /= dim1\n            pred_boxes_normalized_tta_array[:, [1, 3]] /= dim0\n            \n            # append results for ensembling\n            boxes.append(pred_boxes_normalized_array)\n            scores.append(pred_scores_array)\n            labels.append(pred_classes_array)\n            dims.append([dim0, dim1])\n\n            boxes_tta.append(pred_boxes_normalized_tta_array)\n            scores_tta.append(pred_scores_tta_array)\n            labels_tta.append(pred_classes_tta_array)\n            dims_tta.append([dim0, dim1])\n            \n            result = {\n                \"id\": image_id,\n                \"PredictionString\": format_pred(\n                    pred_classes_array, pred_boxes_array, pred_scores_array\n                ),\n            }\n        \n        # append result for image\n        results_list.append(result)\n        index += 1","metadata":{"execution":{"iopub.status.busy":"2021-07-21T04:50:34.334547Z","iopub.execute_input":"2021-07-21T04:50:34.334897Z","iopub.status.idle":"2021-07-21T04:50:41.575482Z","shell.execute_reply.started":"2021-07-21T04:50:34.334861Z","shell.execute_reply":"2021-07-21T04:50:41.574442Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# all image detections before post-processing\nimage_sub_df = pd.DataFrame(results_list, columns=['id', 'PredictionString'])\nimage_sub_df['id'] = image_sub_df['id']+\"_image\"","metadata":{"execution":{"iopub.status.busy":"2021-07-21T04:50:41.577204Z","iopub.execute_input":"2021-07-21T04:50:41.577876Z","iopub.status.idle":"2021-07-21T04:50:41.589069Z","shell.execute_reply.started":"2021-07-21T04:50:41.577829Z","shell.execute_reply":"2021-07-21T04:50:41.588100Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"image_sub_df.shape","metadata":{"execution":{"iopub.status.busy":"2021-07-21T04:50:41.590562Z","iopub.execute_input":"2021-07-21T04:50:41.590934Z","iopub.status.idle":"2021-07-21T04:50:41.601467Z","shell.execute_reply.started":"2021-07-21T04:50:41.590883Z","shell.execute_reply":"2021-07-21T04:50:41.600401Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"image_sub_df.head()","metadata":{"execution":{"iopub.status.busy":"2021-07-21T04:50:41.603006Z","iopub.execute_input":"2021-07-21T04:50:41.603374Z","iopub.status.idle":"2021-07-21T04:50:41.622323Z","shell.execute_reply.started":"2021-07-21T04:50:41.603337Z","shell.execute_reply":"2021-07-21T04:50:41.621605Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"pred_images = get_image_files(\"/kaggle/working/results/\")\nshow_images(L(map(PILImage.create, pred_images)),nrows=1,figsize=(50,10))","metadata":{"execution":{"iopub.status.busy":"2021-07-21T04:50:41.625068Z","iopub.execute_input":"2021-07-21T04:50:41.625313Z","iopub.status.idle":"2021-07-21T04:50:42.725544Z","shell.execute_reply.started":"2021-07-21T04:50:41.625288Z","shell.execute_reply":"2021-07-21T04:50:42.724520Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"gc.collect()\ntorch.cuda.empty_cache()","metadata":{"execution":{"iopub.status.busy":"2021-07-21T04:50:42.726861Z","iopub.execute_input":"2021-07-21T04:50:42.727253Z","iopub.status.idle":"2021-07-21T04:50:42.964105Z","shell.execute_reply.started":"2021-07-21T04:50:42.727215Z","shell.execute_reply":"2021-07-21T04:50:42.962990Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#### Weighted Boxes Fusion (TTA)","metadata":{}},{"cell_type":"code","source":"sys.path.append(\"../input/weightedboxesfusion/\")","metadata":{"execution":{"iopub.status.busy":"2021-07-21T04:50:42.966008Z","iopub.execute_input":"2021-07-21T04:50:42.966801Z","iopub.status.idle":"2021-07-21T04:50:42.973709Z","shell.execute_reply.started":"2021-07-21T04:50:42.966754Z","shell.execute_reply":"2021-07-21T04:50:42.972899Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from ensemble_boxes import *","metadata":{"execution":{"iopub.status.busy":"2021-07-21T04:50:42.982566Z","iopub.execute_input":"2021-07-21T04:50:42.982945Z","iopub.status.idle":"2021-07-21T04:50:43.034584Z","shell.execute_reply.started":"2021-07-21T04:50:42.982891Z","shell.execute_reply":"2021-07-21T04:50:43.033946Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fusion_prediction_string = []\ndetectron_boxes = []\ndetectron_scores = []\ndetectron_labels = []\n\nfor i in progress_bar(range((len(boxes)))):\n    fusion_boxes, fusion_scores, fusion_labels = weighted_boxes_fusion([boxes[i], boxes_tta[i]],\n                                                                       [scores[i], scores_tta[i]],\n                                                                       [labels[i], labels_tta[i]], iou_thr=0.6, skip_box_thr=0)\n    detectron_boxes.append(fusion_boxes.copy())\n    detectron_scores.append(fusion_scores.copy())\n    detectron_labels.append(fusion_labels.copy())\n    \n    fusion_boxes[:, [0, 2]] *= dims[i][1]\n    fusion_boxes[:, [1, 3]] *= dims[i][0]\n    fusion_prediction_string.append(format_pred(fusion_labels, fusion_boxes, fusion_scores))","metadata":{"execution":{"iopub.status.busy":"2021-07-21T04:50:43.037967Z","iopub.execute_input":"2021-07-21T04:50:43.038212Z","iopub.status.idle":"2021-07-21T04:50:48.466858Z","shell.execute_reply.started":"2021-07-21T04:50:43.038188Z","shell.execute_reply":"2021-07-21T04:50:48.466187Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"image_sub_df['PredictionString'] = fusion_prediction_string","metadata":{"execution":{"iopub.status.busy":"2021-07-21T04:50:48.468115Z","iopub.execute_input":"2021-07-21T04:50:48.468455Z","iopub.status.idle":"2021-07-21T04:50:48.473229Z","shell.execute_reply.started":"2021-07-21T04:50:48.468417Z","shell.execute_reply":"2021-07-21T04:50:48.472146Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"image_sub_df.head()","metadata":{"execution":{"iopub.status.busy":"2021-07-21T04:50:48.474370Z","iopub.execute_input":"2021-07-21T04:50:48.474717Z","iopub.status.idle":"2021-07-21T04:50:48.493790Z","shell.execute_reply.started":"2021-07-21T04:50:48.474681Z","shell.execute_reply":"2021-07-21T04:50:48.492782Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"assert not image_sub_df.isna().any().any()","metadata":{"execution":{"iopub.status.busy":"2021-07-21T04:50:48.495042Z","iopub.execute_input":"2021-07-21T04:50:48.495457Z","iopub.status.idle":"2021-07-21T04:50:48.503221Z","shell.execute_reply.started":"2021-07-21T04:50:48.495394Z","shell.execute_reply":"2021-07-21T04:50:48.502473Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Detection (YOLO-V5)\n\nhttps://www.kaggle.com/h053473666/siim-cov19-yolov5-train (opacity and none classes trained together)","metadata":{}},{"cell_type":"code","source":"yolo_weights_dir = \"/kaggle/input/siim-cov19-yolov5-train/yolov5/runs/train/exp/weights/best.pt\"\nimgdir = \"/kaggle/working/test_images_512/\"","metadata":{"execution":{"iopub.status.busy":"2021-07-21T04:50:48.504564Z","iopub.execute_input":"2021-07-21T04:50:48.504942Z","iopub.status.idle":"2021-07-21T04:50:48.511171Z","shell.execute_reply.started":"2021-07-21T04:50:48.504881Z","shell.execute_reply":"2021-07-21T04:50:48.510444Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!python /kaggle/input/yolov5-official-v31-dataset/yolov5/detect.py --weights {yolo_weights_dir}\\\n--img 512\\\n--conf 0.001\\\n--iou 0.5\\\n--source {imgdir}\\\n--save-txt --save-conf --exist-ok ","metadata":{"execution":{"iopub.status.busy":"2021-07-21T04:50:48.512562Z","iopub.execute_input":"2021-07-21T04:50:48.512983Z","iopub.status.idle":"2021-07-21T04:51:00.525938Z","shell.execute_reply.started":"2021-07-21T04:50:48.512946Z","shell.execute_reply":"2021-07-21T04:51:00.524861Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"image_ids = image_sub_df['id'].values","metadata":{"execution":{"iopub.status.busy":"2021-07-21T04:51:00.527659Z","iopub.execute_input":"2021-07-21T04:51:00.528092Z","iopub.status.idle":"2021-07-21T04:51:00.536050Z","shell.execute_reply.started":"2021-07-21T04:51:00.528047Z","shell.execute_reply":"2021-07-21T04:51:00.535012Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"len(detectron_boxes), len(detectron_scores), len(detectron_labels), len(dims), len(image_ids)","metadata":{"execution":{"iopub.status.busy":"2021-07-21T04:51:00.537442Z","iopub.execute_input":"2021-07-21T04:51:00.537799Z","iopub.status.idle":"2021-07-21T04:51:00.548186Z","shell.execute_reply.started":"2021-07-21T04:51:00.537768Z","shell.execute_reply":"2021-07-21T04:51:00.546815Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fusion_prediction_string = []\nfor i in progress_bar(range(len(image_ids))):\n\n    # read and convert to xmin,ymin,xmax,ymax\n    pred_path = Path(f\"/kaggle/working/runs/detect/exp/labels/{image_ids[i][:-6]}.txt\")\n    if pred_path.exists():\n        pred = np.loadtxt(pred_path).reshape(-1,6)\n        yolo_labels, yolo_scores, yolo_boxes = pred[:,0], pred[:,5], pred[:,1:5]\n        yolo_boxes[..., [0, 1]] = yolo_boxes[..., [0, 1]] - yolo_boxes[..., [2, 3]]/2\n        yolo_boxes[..., [2, 3]] = yolo_boxes[..., [0, 1]] + yolo_boxes[..., [2, 3]]\n\n        # weighted boxes fusion\n        fusion_boxes, fusion_scores, fusion_labels = weighted_boxes_fusion([detectron_boxes[i], yolo_boxes],\n                                                                           [detectron_scores[i], yolo_scores],\n                                                                           [detectron_labels[i], yolo_labels], iou_thr=0.6, skip_box_thr=0)\n    else:\n        fusion_boxes, fusion_scores, fusion_labels = detectron_boxes[i], detectron_scores[i], detectron_labels[i]\n    \n    fusion_boxes[:, [0, 2]] *= dims[i][1]\n    fusion_boxes[:, [1, 3]] *= dims[i][0]\n    fusion_prediction_string.append(format_pred(fusion_labels, fusion_boxes, fusion_scores))","metadata":{"execution":{"iopub.status.busy":"2021-07-21T04:51:00.550122Z","iopub.execute_input":"2021-07-21T04:51:00.550639Z","iopub.status.idle":"2021-07-21T04:51:05.156586Z","shell.execute_reply.started":"2021-07-21T04:51:00.550598Z","shell.execute_reply":"2021-07-21T04:51:05.155875Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"len(fusion_prediction_string)","metadata":{"execution":{"iopub.status.busy":"2021-07-21T04:51:05.158879Z","iopub.execute_input":"2021-07-21T04:51:05.159637Z","iopub.status.idle":"2021-07-21T04:51:05.165717Z","shell.execute_reply.started":"2021-07-21T04:51:05.159580Z","shell.execute_reply":"2021-07-21T04:51:05.164735Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"image_sub_df['PredictionString'] = fusion_prediction_string","metadata":{"execution":{"iopub.status.busy":"2021-07-21T04:51:05.167641Z","iopub.execute_input":"2021-07-21T04:51:05.168159Z","iopub.status.idle":"2021-07-21T04:51:05.175867Z","shell.execute_reply.started":"2021-07-21T04:51:05.168117Z","shell.execute_reply":"2021-07-21T04:51:05.175111Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"image_sub_df.head()","metadata":{"execution":{"iopub.status.busy":"2021-07-21T04:51:05.177768Z","iopub.execute_input":"2021-07-21T04:51:05.178235Z","iopub.status.idle":"2021-07-21T04:51:05.195203Z","shell.execute_reply.started":"2021-07-21T04:51:05.178189Z","shell.execute_reply":"2021-07-21T04:51:05.194310Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"assert not image_sub_df.isna().any().any()","metadata":{"execution":{"iopub.status.busy":"2021-07-21T04:51:05.196582Z","iopub.execute_input":"2021-07-21T04:51:05.196989Z","iopub.status.idle":"2021-07-21T04:51:05.205475Z","shell.execute_reply.started":"2021-07-21T04:51:05.196948Z","shell.execute_reply":"2021-07-21T04:51:05.204704Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"gc.collect()\ntorch.cuda.empty_cache()","metadata":{"execution":{"iopub.status.busy":"2021-07-21T04:51:05.207259Z","iopub.execute_input":"2021-07-21T04:51:05.207800Z","iopub.status.idle":"2021-07-21T04:51:05.404201Z","shell.execute_reply.started":"2021-07-21T04:51:05.207762Z","shell.execute_reply":"2021-07-21T04:51:05.403344Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Classification","metadata":{}},{"cell_type":"code","source":"from kornia.augmentation import augmentation as korniatfm\nimport torchvision.transforms as tvtfm\nimport kornia\nfrom PIL import ImageOps\nclass RandomGaussianBlur(RandTransform):\n    \"Randomly apply gaussian blur with probability `p` with a value of s\"\n    order = 11\n    def __init__(self, p=0.5, s=(8,32), same_on_batch=False, **kwargs): \n        store_attr()\n        super().__init__(p=p, **kwargs)\n        \n    def encodes(self, x:TensorImage):\n        if isinstance(self.s, tuple): s = np.random.randint(*self.s)\n        if isinstance(self.s, list):  s = np.random.randint(*self.s)\n        if isinstance(self.s, int):   s = self.s\n        s2 = int(s/4)*2+1\n        tfm = korniatfm.GaussianBlur((s2,s2),(s,s),same_on_batch=self.same_on_batch,p=1.)\n        return tfm(x)\n\n@delegates(to=korniatfm.RandomAffine)\nclass RandomAffineGeometric(RandTransform):\n    \"Randomly apply rotation,translation,scale, with probability `p`\"\n    order = 11\n    def __init__(self, p=0.5, **kwargs): \n        store_attr()\n        super().__init__(p=p)\n        self.tfm = korniatfm.RandomAffine(p=1, **kwargs)\n        \n    def encodes(self, x:TensorImage): return self.tfm(x)\n    \nclass RandHistEqualize(RandTransform):\n    \"Randomly flip with probability `p`\"\n    def __init__(self, p=0.5): super().__init__(p=p)\n    def encodes(self, x:(Image.Image)): return ImageOps.equalize(x)","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2021-07-21T04:51:05.406000Z","iopub.execute_input":"2021-07-21T04:51:05.406667Z","iopub.status.idle":"2021-07-21T04:51:05.641748Z","shell.execute_reply.started":"2021-07-21T04:51:05.406623Z","shell.execute_reply":"2021-07-21T04:51:05.640964Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sys.path.append(\"/kaggle/input/timm-pytorch-image-models/pytorch-image-models-master/\")\nimport timm\nfrom torch.utils.checkpoint import checkpoint, checkpoint_sequential\n\n# from: https://github.com/KeremTurgutlu/self_supervised/blob/main/nbs/02%20-%20layers.ipynb\n\nmk_class('PoolingType', **{o:o.lower() for o in ['Fast', 'Avg', 'AvgMax', 'CatAvgMax', 'Max']},\n         doc=\"All possible pooling types as attributes to get tab-completion and typo-proofing\")\n\ndef create_fastai_encoder(arch:str, pretrained=False, n_in=3, pool_type=PoolingType.CatAvgMax):\n    \"Create timm encoder from a given arch backbone\"\n    encoder = create_body(arch, n_in, pretrained, cut=None)\n    pool = AdaptiveConcatPool2d() if pool_type == \"catavgmax\" else nn.AdaptiveAvgPool2d(1)\n    return nn.Sequential(*encoder, pool, Flatten())\n\ndef create_timm_encoder(arch:str, pretrained=False, n_in=3, pool_type=PoolingType.CatAvgMax):\n    \"Creates a body from any model in the `timm` library. If pool_type is None then it uses timm default\"\n    if ('vit' in arch) or (pool_type is None):\n        model = timm.create_model(arch, pretrained=pretrained, in_chans=n_in, num_classes=0)\n    else:\n        model = timm.create_model(arch, pretrained=pretrained, in_chans=n_in, num_classes=0, global_pool=pool_type)\n    return model\n\ndef create_encoder(arch:str, pretrained=True, n_in=3, pool_type=PoolingType.CatAvgMax):\n    \"A utility for creating encoder without specifying the package\"\n    if arch in globals(): return create_fastai_encoder(globals()[arch], pretrained, n_in, pool_type)\n    else:                 return create_timm_encoder(arch, pretrained, n_in, pool_type)\n\ndef create_cls_module(nf, n_out, lin_ftrs=None, ps=0.5, use_bn=True, first_bn=True, bn_final=False, lin_first=False, y_range=None):\n    \"Creates classification layer which takes nf flatten features and outputs n_out logits\"\n    lin_ftrs = [nf, 512, n_out] if lin_ftrs is None else [nf] + lin_ftrs + [n_out]\n    bns = [first_bn] + [use_bn]*len(lin_ftrs[1:])\n    ps = L(ps)\n    if len(ps) == 1: ps = [ps[0]/2] * (len(lin_ftrs)-2) + ps\n    actns = [nn.ReLU(inplace=True)] * (len(lin_ftrs)-2) + [None]\n    layers = []\n    if lin_first: layers.append(nn.Dropout(ps.pop(0)))\n    for ni,no,bn,p,actn in zip(lin_ftrs[:-1], lin_ftrs[1:], bns, ps, actns):\n        layers += LinBnDrop(ni, no, bn=bn, p=p, act=actn, lin_first=lin_first)\n    if lin_first: layers.append(nn.Linear(lin_ftrs[-2], n_out))\n    if bn_final: layers.append(nn.BatchNorm1d(lin_ftrs[-1], momentum=0.01))\n    if y_range is not None: layers.append(SigmoidRange(*y_range))\n    return nn.Sequential(*layers)\n\ndef create_model(arch, n_out, **kwargs):\n    encoder = create_encoder(arch, **kwargs)\n    with torch.no_grad(): out = encoder(torch.randn((2,3,384,384))) \n    classifier = create_cls_module(out.size(-1), n_out, **kwargs)\n    return nn.Sequential(encoder, classifier)\n\ndef model_splitter(m): return L(m[0], m[1]).map(params)\n\n\nclass CheckpointResNet(Module):\n    def __init__(self, resnet_model, checkpoint_nchunks=2):\n        \"A gradient checkpoint wrapper for timm ResNet\"\n        self.checkpoint_nchunks = checkpoint_nchunks\n        self.resnet_model = resnet_model\n        self.forward_layers = nn.Sequential(*[\n            self.resnet_model.layer1,\n            self.resnet_model.layer2,\n            self.resnet_model.layer3,\n            self.resnet_model.layer4\n        ])\n    \n    def forward(self, x):\n        x = self.resnet_model.conv1(x)\n        x = self.resnet_model.bn1(x)\n        x = self.resnet_model.act1(x)\n        x = self.resnet_model.maxpool(x)\n            \n        x = checkpoint_sequential(self.forward_layers, self.checkpoint_nchunks, x)\n        x = self.resnet_model.global_pool(x)\n        \n        if self.resnet_model.drop_rate:\n            x = F.dropout(x, p=float(self.resnet_model.drop_rate), training=self.resnet_model.training)\n        x = self.resnet_model.fc(x)\n        return x\n    \nclass CheckpointEfficientNet(Module):\n    def __init__(self, effnet_model, checkpoint_nchunks=2):\n        \"A gradient checkpoint wrapper for timm EfficientNet\"\n        self.checkpoint_nchunks = checkpoint_nchunks\n        self.effnet_model = effnet_model\n    \n    def forward_features(self, x):\n        x = self.effnet_model.conv_stem(x)\n        x = self.effnet_model.bn1(x)\n        x = self.effnet_model.act1(x)\n        x = checkpoint_sequential(self.effnet_model.blocks, self.checkpoint_nchunks, x)\n        x = self.effnet_model.conv_head(x)\n        x = self.effnet_model.bn2(x)\n        x = self.effnet_model.act2(x)\n        return x\n\n    def forward(self, x):\n        x = self.forward_features(x)\n        x = self.effnet_model.global_pool(x)\n        if self.effnet_model.drop_rate > 0.:\n            x = F.dropout(x, p=self.effnet_model.drop_rate, training=self.effnet_model.training)\n        return self.effnet_model.classifier(x)\n    \n\nclass CheckpointVisionTransformer(Module):\n    def __init__(self, vit_model, checkpoint_nchunks=2):\n        \"A gradient checkpoint wrapper for timm VisionTransformer\"\n        self.checkpoint_nchunks = checkpoint_nchunks\n        self.vit_model = vit_model\n    \n    def forward_features(self, x):\n        B = x.shape[0]\n        x = self.vit_model.patch_embed(x)\n\n        cls_tokens = self.vit_model.cls_token.expand(B, -1, -1)  # stole cls_tokens impl from Phil Wang, thanks\n        x = torch.cat((cls_tokens, x), dim=1)\n        x = x + self.vit_model.pos_embed\n        x = self.vit_model.pos_drop(x)\n        x = checkpoint_sequential(self.vit_model.blocks, self.checkpoint_nchunks, x)\n        x = self.vit_model.norm(x)[:, 0]\n        x = self.vit_model.pre_logits(x)\n        return x\n\n    def forward(self, x):\n        x = self.forward_features(x)\n        x = self.vit_model.head(x)\n        return x\n    \n    \nclass CheckpointNFNet(Module):\n    def __init__(self, nfnet_model, checkpoint_nchunks=2):\n        \"A gradient checkpoint wrapper for timm NFNet\"\n        self.checkpoint_nchunks = checkpoint_nchunks\n        self.nfnet_model = nfnet_model\n    \n    def forward_features(self, x):\n        x = self.nfnet_model.stem(x)\n        x = checkpoint_sequential(self.nfnet_model.stages, self.checkpoint_nchunks, x)\n        x = self.nfnet_model.final_conv(x)\n        x = self.nfnet_model.final_act(x)\n        return x\n    \n    def forward(self, x):\n        x = self.forward_features(x)\n        x = self.nfnet_model.head(x)\n        return x\n\n\ndef get_classification_model(arch, n_out=4):\n    \n    if \"res\" in arch:\n        if \"200d\" in arch:\n            encoder = CheckpointResNet(create_timm_encoder(arch), checkpoint_nchunks=4)    \n        else:\n            encoder = CheckpointResNet(create_timm_encoder(arch), checkpoint_nchunks=2)\n        \n    elif (\"eff\" in arch) and (arch != \"tf_efficientnet_b0_ns\") :\n        if (\"b7\" in arch or \"l2\" in arch):\n            encoder = CheckpointEfficientNet(create_timm_encoder(arch), checkpoint_nchunks=4)\n        else:\n            encoder = CheckpointEfficientNet(create_timm_encoder(arch), checkpoint_nchunks=2)\n            \n    elif (\"vit\" in arch):\n        if (\"base\" in arch):\n            encoder = CheckpointVisionTransformer(create_timm_encoder(arch), checkpoint_nchunks=2)\n        elif (\"large\" in arch):\n            encoder = CheckpointVisionTransformer(create_timm_encoder(arch), checkpoint_nchunks=8)\n        else:\n            encoder = CheckpointVisionTransformer(create_timm_encoder(arch), checkpoint_nchunks=4)\n            \n    elif (\"nfnet\" in arch):\n        if (\"f2\" in arch or \"f3\" in arch or \"f4\" in arch or \"f5\" in arch):\n            encoder = CheckpointNFNet(create_timm_encoder(arch), checkpoint_nchunks=4)\n        \n    elif (\"cait\" in arch):\n        encoder = CheckpointVisionTransformer(create_timm_encoder(arch), checkpoint_nchunks=6)\n            \n    else:\n        encoder = create_timm_encoder(arch)\n        \n    with torch.no_grad(): out = encoder(torch.randn((2,3,384,384))) \n    classifier = create_cls_module(out.size(-1), n_out=n_out)\n    model = nn.Sequential(encoder, classifier)\n    return model","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2021-07-21T04:51:05.643124Z","iopub.execute_input":"2021-07-21T04:51:05.643481Z","iopub.status.idle":"2021-07-21T04:51:07.422261Z","shell.execute_reply.started":"2021-07-21T04:51:05.643444Z","shell.execute_reply":"2021-07-21T04:51:07.421073Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sys.path.append(\"/kaggle/input/effdet024/effdet-0.2.4/\")\nimport effdet\nfrom effdet.efficientdet import *\nfrom effdet.config.model_config import *\n\ndef get_efficientdet_config(model_name='tf_efficientdet_d7'):\n    \"\"\"Get the default config for EfficientDet based on model name.\"\"\"\n    h = default_detection_model_configs()\n    h.update(efficientdet_model_param_dict[model_name])\n    h.num_levels = h.max_level - h.min_level + 1\n    h = deepcopy(h)  # may be unnecessary, ensure no references to param dict values\n    # OmegaConf.set_struct(h, True)  # FIXME good idea?\n    return h\n\nclass CheckpointEfficientNetFeatures(Module):\n    def __init__(self, backbone):\n        \n        self.backbone = backbone\n        \n    def forward(self, x):\n        x = self.backbone.conv_stem(x)\n        x = self.backbone.bn1(x)\n        x = self.backbone.act1(x)\n        if self.backbone.feature_hooks is None:\n            features = []\n            if 0 in self.backbone._stage_out_idx:\n                features.append(x)  # add stem out\n            for i, b in enumerate(self.backbone.blocks):\n#                 x = b(x)\n                x = checkpoint(b,x)\n                if i + 1 in self.backbone._stage_out_idx:\n                    features.append(x)\n            return features\n        else:\n#             self.blocks(x)\n            checkpoint_sequential(self.backbone.blocks,7,x)\n            out = self.backbone.feature_hooks.get_output(x.device)\n            return list(out.values())\n        \nclass EffDetAuxModel(Module):\n    def __init__(self, model):\n        self.model = model\n        self.backbone = CheckpointEfficientNetFeatures(model.backbone)\n        self.pooling = nn.Sequential(AdaptiveConcatPool2d(), nn.Flatten())\n        \n        nf = list(model.backbone.blocks[-1][-1].children())[-1].num_features\n        self.cls_head = create_cls_module(nf*2, n_out=4)\n\n        nc = list(list(model.class_net.children())[-1].children())[-1].out_channels\n        self.conv1x1 = nn.Conv2d(nc,1,1)\n        \n    def forward(self, x):\n        # effnet classification \n        x = self.backbone(x)\n        x_pooled = self.pooling(x[-1]) # last block output\n        cls_out = self.cls_head(x_pooled)\n\n        # effdet segmentation (output resolution: image_size/2^2)\n        x = self.model.fpn(x)\n        x = self.model.class_net(x)\n        seg_out = self.conv1x1(x[0]) # top bifpn output\n        \n        return cls_out, seg_out\n    \ndef create_aux_model(arch='tf_efficientnet_b7_ns'):\n    config = get_efficientdet_config()\n    config['backbone_name'] = arch\n    config['backbone_indices'] = (1,2,3,4)\n    config['min_level'] = 2\n    config['max_level'] = 7\n    config['num_levels'] = 6\n    config['url'] = ''\n    config['fpn_channels'] = 64\n    config['fpn_cell_repeats'] = 3\n    config['box_class_repeats'] = 3\n    model = EfficientDet(config, pretrained_backbone=False)\n    return EffDetAuxModel(model)\n\nclass ClassificationWrapper(Module):\n    def __init__(self, model):\n        self.model = model\n        \n    def forward(self, x):\n        x = self.model.backbone(x)\n        x_pooled = self.model.pooling(x[-1]) # last block output\n        return self.model.cls_head(x_pooled)","metadata":{"execution":{"iopub.status.busy":"2021-07-21T04:51:07.423861Z","iopub.execute_input":"2021-07-21T04:51:07.424328Z","iopub.status.idle":"2021-07-21T04:51:07.998657Z","shell.execute_reply.started":"2021-07-21T04:51:07.424277Z","shell.execute_reply":"2021-07-21T04:51:07.997522Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def read_image(image_id):  return PILImage.create(f\"/kaggle/working/test_images_512/{image_id}.png\")\ndef dummy_label(image_id): return 0\n\n# TEST DL\nsource = test_image_ids\ntfms = [[read_image, ToTensor], [dummy_label]]\ndsets = Datasets(source, tfms=tfms, splits=None)\nbatch_tfms = [IntToFloatTensor] \ndls = dsets.dataloaders(bs=128, num_workers=None, after_batch=batch_tfms)\ntest_dl_512 = dls.test_dl(test_image_ids, bs=16)","metadata":{"execution":{"iopub.status.busy":"2021-07-21T04:51:08.000497Z","iopub.execute_input":"2021-07-21T04:51:08.001168Z","iopub.status.idle":"2021-07-21T04:51:08.051127Z","shell.execute_reply.started":"2021-07-21T04:51:08.001119Z","shell.execute_reply":"2021-07-21T04:51:08.043311Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# def read_image(image_id):  return PILImage.create(f\"/kaggle/working/test_images_384/{image_id}.png\")\n# def dummy_label(image_id): return 0\n\n# # TEST DL\n# source = test_image_ids\n# tfms = [[read_image, ToTensor], [dummy_label]]\n# dsets = Datasets(source, tfms=tfms, splits=None)\n# batch_tfms = [IntToFloatTensor] \n# dls = dsets.dataloaders(bs=128, num_workers=None, after_batch=batch_tfms)\n# test_dl_384 = dls.test_dl(test_image_ids, bs=16)","metadata":{"execution":{"iopub.status.busy":"2021-07-21T04:51:08.055634Z","iopub.execute_input":"2021-07-21T04:51:08.056098Z","iopub.status.idle":"2021-07-21T04:51:08.060825Z","shell.execute_reply.started":"2021-07-21T04:51:08.056043Z","shell.execute_reply":"2021-07-21T04:51:08.059958Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# TTA\nrotate = Rotate(p=1., max_deg=25, pad_mode='zeros')\nzoom = Zoom(p=1., min_zoom=0.75, max_zoom=1.35, pad_mode='zeros')\nnormalize = Normalize.from_stats(*imagenet_stats)","metadata":{"execution":{"iopub.status.busy":"2021-07-21T04:51:08.062154Z","iopub.execute_input":"2021-07-21T04:51:08.062742Z","iopub.status.idle":"2021-07-21T04:51:08.073414Z","shell.execute_reply.started":"2021-07-21T04:51:08.062695Z","shell.execute_reply":"2021-07-21T04:51:08.072364Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"torch.cuda.empty_cache()","metadata":{"execution":{"iopub.status.busy":"2021-07-21T04:51:08.075011Z","iopub.execute_input":"2021-07-21T04:51:08.075586Z","iopub.status.idle":"2021-07-21T04:51:08.096874Z","shell.execute_reply.started":"2021-07-21T04:51:08.075549Z","shell.execute_reply":"2021-07-21T04:51:08.090491Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#### Predictions","metadata":{}},{"cell_type":"code","source":"import gc","metadata":{"execution":{"iopub.status.busy":"2021-07-21T04:51:08.098543Z","iopub.execute_input":"2021-07-21T04:51:08.099087Z","iopub.status.idle":"2021-07-21T04:51:08.110966Z","shell.execute_reply.started":"2021-07-21T04:51:08.099043Z","shell.execute_reply":"2021-07-21T04:51:08.107483Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"all_models_512 = []\nall_models_384 = []\nmodels_dir = Path(\"/kaggle/input/covid19-classification-models/\")\nmodels_dir2 = Path(\"/kaggle/input/covid19-classification-models2/\")","metadata":{"execution":{"iopub.status.busy":"2021-07-21T04:51:08.118329Z","iopub.execute_input":"2021-07-21T04:51:08.118734Z","iopub.status.idle":"2021-07-21T04:51:08.127815Z","shell.execute_reply.started":"2021-07-21T04:51:08.118691Z","shell.execute_reply":"2021-07-21T04:51:08.126925Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# for fold_idx in range(8):\n#     use_norm = False\n#     model = create_aux_model(\"tf_efficientnet_b7_ns\")\n#     state_dict = torch.load(models_dir/f\"tf_efficientnet_b7-sz384-ricord-nih_pretrained-aux_seg_loss0.75-fold{fold_idx}.pth\") # sigmoid - no normalization\n#     model.load_state_dict(state_dict)\n#     model = ClassificationWrapper(model)\n#     all_models_384.append((model, use_norm)) # model, use_norm","metadata":{"execution":{"iopub.status.busy":"2021-07-17T23:13:28.652076Z","iopub.execute_input":"2021-07-17T23:13:28.65235Z","iopub.status.idle":"2021-07-17T23:13:28.656767Z","shell.execute_reply.started":"2021-07-17T23:13:28.652322Z","shell.execute_reply":"2021-07-17T23:13:28.655849Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for fold_idx in range(8):\n    use_norm = False\n    model = create_aux_model(\"tf_efficientnet_b7_ns\")\n    state_dict = torch.load(models_dir/f\"tf_efficientnet_b7-sz512-ricord-aux_seg_loss0.75-fold{fold_idx}.pth\") # sigmoid - no normalization\n    model.load_state_dict(state_dict)\n    model = ClassificationWrapper(model)\n    all_models_512.append((model, use_norm)) # model, use_norm","metadata":{"execution":{"iopub.status.busy":"2021-07-21T04:51:08.129267Z","iopub.execute_input":"2021-07-21T04:51:08.129724Z","iopub.status.idle":"2021-07-21T04:51:57.282423Z","shell.execute_reply.started":"2021-07-21T04:51:08.129689Z","shell.execute_reply":"2021-07-21T04:51:57.281412Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for fold_idx in range(8):\n    use_norm = False\n    model = create_aux_model(\"tf_efficientnet_b7_ns\")\n    state_dict = torch.load(models_dir/f\"tf_efficientnet_b7_ns-sz512-ricord-aux_seg_loss0.5-fold{fold_idx}.pth\") # sigmoid - no normalization\n    model.load_state_dict(state_dict)\n    model = ClassificationWrapper(model)\n    all_models_512.append((model, use_norm)) # model, use_norm","metadata":{"execution":{"iopub.status.busy":"2021-07-21T04:51:57.283823Z","iopub.execute_input":"2021-07-21T04:51:57.284233Z","iopub.status.idle":"2021-07-21T04:52:45.389550Z","shell.execute_reply.started":"2021-07-21T04:51:57.284195Z","shell.execute_reply":"2021-07-21T04:52:45.388624Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# use_norm = False\n# model = create_aux_model(\"tf_efficientnet_b7_ns\")\n# state_dict = torch.load(models_dir2/f\"tf_efficientnet_b7-sz512-ricord-nih_pretrained-aux_seg_loss0.5-foldfull_data.pth\") # sigmoid - no normalization\n# model.load_state_dict(state_dict)\n# model = ClassificationWrapper(model)\n# all_models_512.append((model, use_norm)) # model, use_norm","metadata":{"execution":{"iopub.status.busy":"2021-07-21T04:52:45.391115Z","iopub.execute_input":"2021-07-21T04:52:45.391511Z","iopub.status.idle":"2021-07-21T04:52:45.398865Z","shell.execute_reply.started":"2021-07-21T04:52:45.391471Z","shell.execute_reply":"2021-07-21T04:52:45.395813Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for fold_idx in range(5):\n    use_norm = True\n    model = get_classification_model(\"tf_efficientnet_b7_ns\")\n    state_dict = torch.load(models_dir/f\"tf_efficientnet_b7_ns-re-mixup-fold{fold_idx}.pth\") # softmax\n    model.load_state_dict(state_dict)\n    all_models_512.append((model, use_norm))","metadata":{"execution":{"iopub.status.busy":"2021-07-21T04:52:45.400464Z","iopub.execute_input":"2021-07-21T04:52:45.400874Z","iopub.status.idle":"2021-07-21T04:53:36.120366Z","shell.execute_reply.started":"2021-07-21T04:52:45.400832Z","shell.execute_reply":"2021-07-21T04:53:36.119551Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"len(all_models_512), len(all_models_384)","metadata":{"execution":{"iopub.status.busy":"2021-07-21T04:53:36.121589Z","iopub.execute_input":"2021-07-21T04:53:36.121960Z","iopub.status.idle":"2021-07-21T04:53:36.127391Z","shell.execute_reply.started":"2021-07-21T04:53:36.121897Z","shell.execute_reply":"2021-07-21T04:53:36.126568Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# all_preds_384 = []\n\n# # TEST PREDS (384)\n# with torch.no_grad():\n#     all_models_384 = [(model.eval().cuda(), use_norm) for model, use_norm in all_models_384]\n\n#     for xb, in progress_bar(test_dl_384):\n#         tta_preds = []\n#         for model, use_norm in all_models_384:\n#             # original\n#             out1 = to_detach(model(normalize(xb) if use_norm else xb))\n#             # flip lr\n#             out2 = to_detach(model(normalize(xb.flip_lr()) if use_norm else xb.flip_lr()))\n#             # rotate\n#             out3 = to_detach(model(normalize(rotate(xb)) if use_norm else rotate(xb)))\n#             # zoom\n#             out4 = to_detach(model(normalize(zoom(xb)) if use_norm else zoom(xb)))\n            \n#             tta_preds += [torch.stack([out1, out2, out3, out4]).permute(1,0,2)]\n#         tta_preds = torch.stack(tta_preds).permute(1,0,2,3) # bs x models x n_tta x n_classes\n#         all_preds_384 += [tta_preds]\n\n        \nall_preds_512 = []\n# TEST PREDS (512)\nwith torch.no_grad():\n    all_models_512 = [(model.eval().cuda(), use_norm) for model, use_norm in all_models_512]\n\n    for xb, in progress_bar(test_dl_512):\n        tta_preds = []\n        for model, use_norm in all_models_512:\n            # original\n            out1 = to_detach(model(normalize(xb) if use_norm else xb))\n            # flip lr\n            out2 = to_detach(model(normalize(xb.flip_lr()) if use_norm else xb.flip_lr()))\n            # rotate\n            out3 = to_detach(model(normalize(rotate(xb)) if use_norm else rotate(xb)))\n            # zoom\n            out4 = to_detach(model(normalize(zoom(xb)) if use_norm else zoom(xb)))\n            \n            tta_preds += [torch.stack([out1, out2, out3, out4]).permute(1,0,2)]\n#             tta_preds += [torch.stack([out1, out2, out3]).permute(1,0,2)]\n        tta_preds = torch.stack(tta_preds).permute(1,0,2,3) # bs x models x n_tta x n_classes\n        all_preds_512 += [tta_preds]","metadata":{"execution":{"iopub.status.busy":"2021-07-21T04:53:36.128817Z","iopub.execute_input":"2021-07-21T04:53:36.129352Z","iopub.status.idle":"2021-07-21T04:54:56.065196Z","shell.execute_reply.started":"2021-07-21T04:53:36.129312Z","shell.execute_reply":"2021-07-21T04:54:56.064282Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# # single sigmoid model\n# all_preds = torch.cat(all_preds).sigmoid(); all_preds.shape\n# mean_preds = all_preds.mean((1,2))","metadata":{"execution":{"iopub.status.busy":"2021-07-16T04:09:12.187221Z","iopub.status.idle":"2021-07-16T04:09:12.1878Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# multi model power average\n# all_preds_384 = torch.cat(all_preds_384)\nall_preds_512 = torch.cat(all_preds_512)\n\n# preds1 = all_preds_384.sigmoid().mean((1,2))\npreds1 = all_preds_512[:,:8].sigmoid().mean((1,2))\npreds2 = all_preds_512[:,8:16].sigmoid().mean((1,2))\npreds3 = all_preds_512[:,16:21].softmax(-1).mean((1,2))\n\np = 2\nmean_preds = (preds1**p)*0.4 + (preds2**p)*0.4 + (preds3**p)*0.2","metadata":{"execution":{"iopub.status.busy":"2021-07-21T04:54:56.066883Z","iopub.execute_input":"2021-07-21T04:54:56.067258Z","iopub.status.idle":"2021-07-21T04:54:56.080607Z","shell.execute_reply.started":"2021-07-21T04:54:56.067213Z","shell.execute_reply":"2021-07-21T04:54:56.079771Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def generate_study_submission(test_image_ids, preds, image_id2study_id):\n    \"Aggregate image preds for each study, take mean if multiple, return submission df\"\n    study_preds_dict = defaultdict(list)\n    for img_id, probas in zip(test_image_ids, to_np(preds)):\n        sid = image_id2study_id[img_id]\n        study_preds_dict[sid].append(probas)\n    \n    study_classes = [\"negative\", \"typical\", \"indeterminate\", \"atypical\"]\n    row1,row2 = [],[]\n    for sid, probas in study_preds_dict.items(): \n        row1.append(f\"{sid}_study\")\n        probas = np.vstack(probas).mean(0) # take mean if multiple images per study\n        s = []\n        for class_id,proba in enumerate(probas):\n            s += [f\"{study_classes[class_id]} {proba} 0 0 1 1\"]\n        row2.append(\" \".join(s))\n    study_sub_df = pd.DataFrame()\n    study_sub_df['id'] = row1\n    study_sub_df['PredictionString'] = row2\n    return study_sub_df","metadata":{"execution":{"iopub.status.busy":"2021-07-21T04:54:56.082755Z","iopub.execute_input":"2021-07-21T04:54:56.083316Z","iopub.status.idle":"2021-07-21T04:54:56.095011Z","shell.execute_reply.started":"2021-07-21T04:54:56.083251Z","shell.execute_reply":"2021-07-21T04:54:56.094067Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"study_sub_df = generate_study_submission(test_image_ids, mean_preds, image_id2study_id); study_sub_df.shape","metadata":{"execution":{"iopub.status.busy":"2021-07-21T04:54:56.096235Z","iopub.execute_input":"2021-07-21T04:54:56.096643Z","iopub.status.idle":"2021-07-21T04:54:56.113147Z","shell.execute_reply.started":"2021-07-21T04:54:56.096607Z","shell.execute_reply":"2021-07-21T04:54:56.112200Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"study_sub_df.head()","metadata":{"execution":{"iopub.status.busy":"2021-07-21T04:54:56.114653Z","iopub.execute_input":"2021-07-21T04:54:56.115052Z","iopub.status.idle":"2021-07-21T04:54:56.129350Z","shell.execute_reply.started":"2021-07-21T04:54:56.115016Z","shell.execute_reply":"2021-07-21T04:54:56.128616Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"image_sub_df.head()","metadata":{"execution":{"iopub.status.busy":"2021-07-21T04:54:56.130467Z","iopub.execute_input":"2021-07-21T04:54:56.130816Z","iopub.status.idle":"2021-07-21T04:54:56.143038Z","shell.execute_reply.started":"2021-07-21T04:54:56.130779Z","shell.execute_reply":"2021-07-21T04:54:56.142093Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Post-Process","metadata":{}},{"cell_type":"code","source":"# add none to all opacity preds CV: 0.682 * 1/3 = 0.227\nnone_probas = mean_preds[:,0].numpy()\nimage_sub_postproc = image_sub_df.copy()\nrows = []\nfor p,s in zip(none_probas, image_sub_postproc['PredictionString']):\n    rows.append(f'none {p} 0 0 1 1' + ' ' + s)\nimage_sub_postproc['PredictionString'] = rows","metadata":{"execution":{"iopub.status.busy":"2021-07-21T04:54:56.144711Z","iopub.execute_input":"2021-07-21T04:54:56.145224Z","iopub.status.idle":"2021-07-21T04:54:56.152072Z","shell.execute_reply.started":"2021-07-21T04:54:56.145187Z","shell.execute_reply":"2021-07-21T04:54:56.151044Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"image_sub_df = image_sub_postproc","metadata":{"execution":{"iopub.status.busy":"2021-07-21T04:54:56.153369Z","iopub.execute_input":"2021-07-21T04:54:56.153951Z","iopub.status.idle":"2021-07-21T04:54:56.161170Z","shell.execute_reply.started":"2021-07-21T04:54:56.153882Z","shell.execute_reply":"2021-07-21T04:54:56.160433Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# # set negative predictions as none with their probas CV: 0.597 * 1/3 = 0.198\n# max_vals_idxs = mean_preds.max(dim=-1)\n# max_vals = max_vals_idxs.values[max_vals_idxs.indices == 0].numpy()\n# none_prediction_string = [f'none {proba} 0 0 1 1' for proba in max_vals]\n# image_sub_df.loc[(max_vals_idxs.indices == 0).numpy(), 'PredictionString'] = none_prediction_string","metadata":{"execution":{"iopub.status.busy":"2021-07-21T04:54:56.162692Z","iopub.execute_input":"2021-07-21T04:54:56.163114Z","iopub.status.idle":"2021-07-21T04:54:56.170003Z","shell.execute_reply.started":"2021-07-21T04:54:56.163076Z","shell.execute_reply":"2021-07-21T04:54:56.169240Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Submit","metadata":{}},{"cell_type":"code","source":"sub_df = pd.concat([study_sub_df,image_sub_df])\nsub_df.to_csv(\"submission.csv\",index=False)\n!rm -r /kaggle/working/test_images*\n!rm -r /kaggle/working/results\n!rm -r /kaggle/working/runs","metadata":{"execution":{"iopub.status.busy":"2021-07-21T04:54:56.173302Z","iopub.execute_input":"2021-07-21T04:54:56.173586Z","iopub.status.idle":"2021-07-21T04:54:58.678580Z","shell.execute_reply.started":"2021-07-21T04:54:56.173558Z","shell.execute_reply":"2021-07-21T04:54:58.677595Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sub_df","metadata":{"execution":{"iopub.status.busy":"2021-07-21T04:54:58.680269Z","iopub.execute_input":"2021-07-21T04:54:58.680627Z","iopub.status.idle":"2021-07-21T04:54:58.698137Z","shell.execute_reply.started":"2021-07-21T04:54:58.680595Z","shell.execute_reply":"2021-07-21T04:54:58.697277Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### fin","metadata":{}},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}