{"cells":[{"metadata":{},"cell_type":"markdown","source":"# Table of Contents\n\n** [Dataset preparation](#dataset)** <br/>\n** [Installation](#installation)** <br/>\n** [EDA: distribution between normal & abnormal class](#eda)** <br/>\n** [Image visualizaion & augmentation with albumentations](#aug)** <br/>\n** [Defining CNN models](#model)** <br/>\n** [Training utils](#trainutil)** <br/>\n** [Training scripts](#trainscript)** <br/>\n** [Prediction on validation & test dataset](#prediction)** <br/>\n** [Next step](#nextstep)** <br/>"},{"metadata":{},"cell_type":"markdown","source":"<a id=\"dataset\"></a>\n# Dataset preparation\n\nPreprocessing x-ray image format (dicom) into normal png image format is already done by @xhlulu in the below discussion:\n - [Multiple preprocessed datasets: 256/512/1024px, PNG and JPG, modified and original ratio](https://www.kaggle.com/c/vinbigdata-chest-xray-abnormalities-detection/discussion/207955).\n\nHere I will just use the dataset [VinBigData Chest X-ray Resized PNG (256x256)](https://www.kaggle.com/xhlulu/vinbigdata-chest-xray-resized-png-256x256) to skip the preprocessing and focus on modeling part. Please upvote the dataset as well!"},{"metadata":{"_kg_hide-input":true,"trusted":true},"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\nimport torch\n\n# --- setup ---\npd.set_option('max_columns', 50)\n","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"<a id=\"installation\"></a>\n# Installation\n\ndetectron2 is not pre-installed in this kaggle docker, so let's install it. \nWe can follow [installation instruction](https://github.com/facebookresearch/detectron2/blob/master/INSTALL.md), we need to know CUDA and pytorch version to install correct `detectron2`."},{"metadata":{"_kg_hide-output":true,"trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"!pip install detectron2 -f \\\n  https://dl.fbaipublicfiles.com/detectron2/wheels/cu102/torch1.7/index.html\n!pip install pytorch-pfn-extras timm","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"This `Flags` class summarizes all the configuratoin available during the training.\n\nAs I will show later, you can change various hyperparameters to experiment improving your models!"},{"metadata":{"_kg_hide-input":true,"trusted":true},"cell_type":"code","source":"from typing import Any\nimport yaml\n\ndef save_yaml(filepath: str, content: Any, width: int = 120):\n    with open(filepath, \"w\") as f:\n        yaml.dump(content, f, width=width)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"from dataclasses import dataclass, field\nfrom typing import Dict, Any, Tuple, Union, List\n\n\n@dataclass\nclass Flags:\n    # General\n    debug: bool = True\n    outdir: str = \"results/det\"\n    device: str = \"cuda:0\"\n\n    # Data config\n    imgdir_name: str = \"vinbigdata-chest-xray-resized-png-256x256\"\n    # split_mode: str = \"all_train\"  # all_train or valid20\n    seed: int = 1024\n    target_fold: int = 0  # 0~4\n    label_smoothing: float = 0.0\n    # Model config\n    model_name: str = \"resnet18\"\n    model_mode: str = \"normal\"  # normal, cnn_fixed supported\n    # Training config\n    epoch: int = 60\n    batchsize: int = 8\n    valid_batchsize: int = 16\n    num_workers: int = 4\n    snapshot_freq: int = 5\n    ema_decay: float = 0.999  # negative value is to inactivate ema.\n    scheduler_type: str = \"\"\n    scheduler_kwargs: Dict[str, Any] = field(default_factory=lambda: {})\n    scheduler_trigger: List[Union[int, str]] = field(default_factory=lambda: [1, \"iteration\"])\n    aug_kwargs: Dict[str, Dict[str, Any]] = field(default_factory=lambda: {})\n    mixup_prob: float = -1.0  # Apply mixup augmentation when positive value is set.\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","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"flags_dict = {\n    \"debug\": False,  # Change to True for fast debug run!\n    \"outdir\": \"results/tmp_debug\",\n    # Data\n    \"imgdir_name\": \"vinbigdata-chest-xray-resized-png-256x256\",\n    # Model\n    \"model_name\": \"resnet18\",\n    # Training\n    \"num_workers\": 4,\n    \"epoch\": 30,\n    \"batchsize\": 8,\n    \"scheduler_type\": \"CosineAnnealingWarmRestarts\",\n    \"scheduler_kwargs\": {\"T_0\": 28125},  # 15000 * 15 epoch // (batchsize=8)\n    \"scheduler_trigger\": [1, \"iteration\"],\n    \"aug_kwargs\": {\n        \"HorizontalFlip\": {\"p\": 0.5},\n        \"ShiftScaleRotate\": {\"scale_limit\": 0.15, \"rotate_limit\": 10, \"p\": 0.5},\n        \"RandomBrightnessContrast\": {\"p\": 0.5},\n        \"CoarseDropout\": {\"max_holes\": 8, \"max_height\": 25, \"max_width\": 25, \"p\": 0.5},\n        \"Blur\": {\"blur_limit\": [3, 7], \"p\": 0.5},\n        \"Downscale\": {\"scale_min\": 0.25, \"scale_max\": 0.9, \"p\": 0.3},\n        \"RandomGamma\": {\"gamma_limit\": [80, 120], \"p\": 0.6},\n    }\n}","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"import dataclasses\n\n# args = parse()\nprint(\"torch\", torch.__version__)\nflags = Flags().update(flags_dict)\nprint(\"flags\", flags)\ndebug = flags.debug\noutdir = Path(flags.outdir)\nos.makedirs(str(outdir), exist_ok=True)\nflags_dict = dataclasses.asdict(flags)\nsave_yaml(str(outdir / \"flags.yaml\"), flags_dict)\n\n# --- Read data ---\ninputdir = Path(\"/kaggle/input\")\ndatadir = inputdir / \"vinbigdata-chest-xray-abnormalities-detection\"\nimgdir = inputdir / flags.imgdir_name\n\n# Read in the data CSV files\ntrain = pd.read_csv(datadir / \"train.csv\")\n# sample_submission = pd.read_csv(datadir / 'sample_submission.csv')","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"<a id=\"eda\"></a>\n# EDA: distribution between normal & abnormal class\n\nAt first, let's check how many normal class exist in the training data.\nIt is classified as \"class_name = No finding\" and \"class_id = 14\".\n\nHowever you need to be careful that 3 radiologists annotated for each image, so you can find 3 annotations as you can see below."},{"metadata":{"trusted":true},"cell_type":"code","source":"train.query(\"image_id == '50a418190bc3fb1ef1633bf9678929b3'\")","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"So the question arises, is there an image that the 3 radiologists' opinions differ?\n\nLet's check number of \"No finding\" annotations for each image, if the opinions are in complete agreement the number of \"No finding\" annotations should be **0 -> Abnormal(all radiologists does not think this is normal)\" or \"1 -> Normal(all radiologists think this is normal)\"**."},{"metadata":{"trusted":true},"cell_type":"code","source":"is_normal_df = train.groupby(\"image_id\")[\"class_id\"].agg(lambda s: (s == 14).sum()).reset_index().rename({\"class_id\": \"num_normal_annotations\"}, axis=1)\nis_normal_df.head()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"We could confirm that **always 3 radiologists opinions match** for normal - abnormal diagnosis.\n\n[Note] I noticed that it does not apply for the other classes. i.e., 3 radiologists opinions sometimes do not match for the other class of thoracic abnormalities."},{"metadata":{"trusted":true},"cell_type":"code","source":"num_normal_anno_counts = is_normal_df[\"num_normal_annotations\"].value_counts()\nnum_normal_anno_counts.plot(kind=\"bar\")\nplt.title(\"The number of 'No finding' annotations in each image\")","execution_count":null,"outputs":[]},{"metadata":{"_kg_hide-input":true,"_kg_hide-output":true,"trusted":true},"cell_type":"code","source":"num_normal_anno_counts_df = num_normal_anno_counts.reset_index()\nnum_normal_anno_counts_df[\"name\"] = num_normal_anno_counts_df[\"index\"].map({0: \"Abnormal\", 3: \"Normal\"})\nnum_normal_anno_counts_df","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"So almost 70% of the data is actually \"Normal\" X-ray images.\n\nOnly 30% of the images need thoracic abnormality location detection."},{"metadata":{"trusted":true},"cell_type":"code","source":"px.pie(num_normal_anno_counts_df, values=\"num_normal_annotations\", names=\"name\", title=\"Normal/Abnormal ratio\")","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"<a id=\"aug\"></a>\n# Image visualizaion & augmentation with albumentations\n\nWhen you train CNN models, image augmentation is important to avoid model to overfit.<br/>\nI'll show examples to use Albumentations to run image augmentation very easily.<br/>\nAt first, I will define pytorch Dataset class for this competition, which can be also used later in the training."},{"metadata":{"trusted":true,"_kg_hide-input":true},"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\n\ndef get_vinbigdata_dicts(\n    imgdir: Path,\n    train_df: pd.DataFrame,\n    train_data_type: str = \"original\",\n    use_cache: bool = True,\n    debug: bool = True,\n    target_indices: Optional[np.ndarray] = None,\n):\n    debug_str = f\"_debug{int(debug)}\"\n    train_data_type_str = f\"_{train_data_type}\"\n    cache_path = Path(\".\") / f\"dataset_dicts_cache{train_data_type_str}{debug_str}.pkl\"\n    if not use_cache or not cache_path.exists():\n        print(\"Creating data...\")\n        train_meta = pd.read_csv(imgdir / \"train_meta.csv\")\n        if debug:\n            train_meta = train_meta.iloc[:500]  # For debug....\n\n        # Load 1 image to get image size.\n        image_id = train_meta.loc[0, \"image_id\"]\n        image_path = str(imgdir / \"train\" / f\"{image_id}.png\")\n        image = cv2.imread(image_path)\n        resized_height, resized_width, ch = image.shape\n        print(f\"image shape: {image.shape}\")\n\n        dataset_dicts = []\n        for index, train_meta_row in tqdm(train_meta.iterrows(), total=len(train_meta)):\n            record = {}\n\n            image_id, height, width = train_meta_row.values\n            filename = str(imgdir / \"train\" / f\"{image_id}.png\")\n            record[\"file_name\"] = filename\n            record[\"image_id\"] = image_id\n            record[\"height\"] = resized_height\n            record[\"width\"] = resized_width\n            objs = []\n            for index2, row in train_df.query(\"image_id == @image_id\").iterrows():\n                # print(row)\n                # print(row[\"class_name\"])\n                # class_name = row[\"class_name\"]\n                class_id = row[\"class_id\"]\n                if class_id == 14:\n                    # It is \"No finding\"\n                    # This annotator does not find anything, skip.\n                    pass\n                else:\n                    # bbox_original = [int(row[\"x_min\"]), int(row[\"y_min\"]), int(row[\"x_max\"]), int(row[\"y_max\"])]\n                    h_ratio = resized_height / height\n                    w_ratio = resized_width / width\n                    bbox_resized = [\n                        int(row[\"x_min\"]) * w_ratio,\n                        int(row[\"y_min\"]) * h_ratio,\n                        int(row[\"x_max\"]) * w_ratio,\n                        int(row[\"y_max\"]) * h_ratio,\n                    ]\n                    obj = {\n                        \"bbox\": bbox_resized,\n                        \"bbox_mode\": BoxMode.XYXY_ABS,\n                        \"category_id\": class_id,\n                    }\n                    objs.append(obj)\n            record[\"annotations\"] = objs\n            dataset_dicts.append(record)\n        with open(cache_path, mode=\"wb\") as f:\n            pickle.dump(dataset_dicts, f)\n\n    print(f\"Load from cache {cache_path}\")\n    with open(cache_path, mode=\"rb\") as f:\n        dataset_dicts = pickle.load(f)\n    if target_indices is not None:\n        dataset_dicts = [dataset_dicts[i] for i in target_indices]\n    return dataset_dicts\n\n\ndef get_vinbigdata_dicts_test(\n    imgdir: Path, test_meta: pd.DataFrame, use_cache: bool = True, debug: bool = True,\n):\n    debug_str = f\"_debug{int(debug)}\"\n    cache_path = Path(\".\") / f\"dataset_dicts_cache_test{debug_str}.pkl\"\n    if not use_cache or not cache_path.exists():\n        print(\"Creating data...\")\n        # test_meta = pd.read_csv(imgdir / \"test_meta.csv\")\n        if debug:\n            test_meta = test_meta.iloc[:500]  # For debug....\n\n        # Load 1 image to get image size.\n        image_id = test_meta.loc[0, \"image_id\"]\n        image_path = str(imgdir / \"test\" / f\"{image_id}.png\")\n        image = cv2.imread(image_path)\n        resized_height, resized_width, ch = image.shape\n        print(f\"image shape: {image.shape}\")\n\n        dataset_dicts = []\n        for index, test_meta_row in tqdm(test_meta.iterrows(), total=len(test_meta)):\n            record = {}\n\n            image_id, height, width = test_meta_row.values\n            filename = str(imgdir / \"test\" / f\"{image_id}.png\")\n            record[\"file_name\"] = filename\n            # record[\"image_id\"] = index\n            record[\"image_id\"] = image_id\n            record[\"height\"] = resized_height\n            record[\"width\"] = resized_width\n            # objs = []\n            # record[\"annotations\"] = objs\n            dataset_dicts.append(record)\n        with open(cache_path, mode=\"wb\") as f:\n            pickle.dump(dataset_dicts, f)\n\n    print(f\"Load from cache {cache_path}\")\n    with open(cache_path, mode=\"rb\") as f:\n        dataset_dicts = pickle.load(f)\n    return dataset_dicts\n","execution_count":null,"outputs":[]},{"metadata":{"_kg_hide-input":true,"trusted":true},"cell_type":"code","source":"\"\"\"\nReferenced `chainer.dataset.DatasetMixin` to work with pytorch Dataset.\n\"\"\"\nimport numpy\nimport six\nimport torch\nfrom torch.utils.data.dataset import Dataset\n\n\nclass DatasetMixin(Dataset):\n\n    def __init__(self, transform=None):\n        self.transform = transform\n\n    def __getitem__(self, index):\n        \"\"\"Returns an example or a sequence of examples.\"\"\"\n        if torch.is_tensor(index):\n            index = index.tolist()\n        if isinstance(index, slice):\n            current, stop, step = index.indices(len(self))\n            return [self.get_example_wrapper(i) for i in\n                    six.moves.range(current, stop, step)]\n        elif isinstance(index, list) or isinstance(index, numpy.ndarray):\n            return [self.get_example_wrapper(i) for i in index]\n        else:\n            return self.get_example_wrapper(index)\n\n    def __len__(self):\n        \"\"\"Returns the number of data points.\"\"\"\n        raise NotImplementedError\n\n    def get_example_wrapper(self, i):\n        \"\"\"Wrapper of `get_example`, to apply `transform` if necessary\"\"\"\n        example = self.get_example(i)\n        if self.transform:\n            example = self.transform(example)\n        return example\n\n    def get_example(self, i):\n        \"\"\"Returns the i-th example.\n\n        Implementations should override it. It should raise :class:`IndexError`\n        if the index is invalid.\n\n        Args:\n            i (int): The index of the example.\n\n        Returns:\n            The i-th example.\n\n        \"\"\"\n        raise NotImplementedError\n","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"[Update] \nHere I mixup augmentation in the dataset. It makes interpolation of 2 images, with the label is also modified according to the mix ratio. \nmixup augmentation is expecially useful when the number of data is limited.\nBecause it can make **combination of any 2 images**, instead of just using 1 image.\n\nI also added label smoothing feature. Sometimes it is difficult to learn label is 0, 1. \nLabel smoothing changes its label 0 -> 0.01 & 1 -> 0.99. By smoothing the label the loss surface becomes more \"soft\", and sometimes model can learn well."},{"metadata":{"trusted":true},"cell_type":"code","source":"import cv2\nimport numpy as np\n\n\nclass VinbigdataTwoClassDataset(DatasetMixin):\n    def __init__(self, dataset_dicts, image_transform=None, transform=None, train: bool = True,\n                 mixup_prob: float = -1.0, label_smoothing: float = 0.0):\n        super(VinbigdataTwoClassDataset, self).__init__(transform=transform)\n        self.dataset_dicts = dataset_dicts\n        self.image_transform = image_transform\n        self.train = train\n        self.mixup_prob = mixup_prob\n        self.label_smoothing = label_smoothing\n\n    def _get_single_example(self, i):\n        d = self.dataset_dicts[i]\n        filename = d[\"file_name\"]\n\n        img = cv2.imread(filename)\n        if self.image_transform:\n            img = self.image_transform(img)\n        img = torch.tensor(np.transpose(img, (2, 0, 1)).astype(np.float32))\n\n        if self.train:\n            label = int(len(d[\"annotations\"]) > 0)  # 0 normal, 1 abnormal\n            if self.label_smoothing > 0:\n                if label == 0:\n                    return img, float(label) + self.label_smoothing\n                else:\n                    return img, float(label) - self.label_smoothing\n            else:\n                return img, float(label)\n        else:\n            # Only return img\n            return img, None\n\n    def get_example(self, i):\n        img, label = self._get_single_example(i)\n        if self.mixup_prob > 0. and np.random.uniform() < self.mixup_prob:\n            j = np.random.randint(0, len(self.dataset_dicts))\n            p = np.random.uniform()\n            img2, label2 = self._get_single_example(j)\n            img = img * p + img2 * (1 - p)\n            if self.train:\n                label = label * p + label2 * (1 - p)\n\n        if self.train:\n            label_logit = torch.tensor([1 - label, label], dtype=torch.float32)\n            return img, label_logit\n        else:\n            # Only return img\n            return img\n\n    def __len__(self):\n        return len(self.dataset_dicts)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Now creating the dataset is just easy as following:"},{"metadata":{"_kg_hide-output":true,"trusted":true},"cell_type":"code","source":"dataset_dicts = get_vinbigdata_dicts(imgdir, train, debug=debug)\ndataset = VinbigdataTwoClassDataset(dataset_dicts)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"You can access each image and its label (0=Normal, 1=Abnormal) by just access `dataset` with index."},{"metadata":{"trusted":true},"cell_type":"code","source":"index = 0\nimg, label = dataset[index]\nplt.imshow(img.cpu().numpy().transpose((1, 2, 0)) / 255.)\nplt.title(f\"{index}-th image: label {label}\")","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"To run augmentation on this image, I will define `Transform` class which is applied each time the data is accessed.\n\nYou can refer [albumentations](https://github.com/albumentations-team/albumentations) page, that various kinds of augmentation is already implemented and can be used very easily!"},{"metadata":{"trusted":true},"cell_type":"code","source":"import albumentations as A\n\n\nclass Transform:\n    def __init__(\n        self, hflip_prob: float = 0.5, ssr_prob: float = 0.5, random_bc_prob: float = 0.5\n    ):\n        self.transform = A.Compose(\n            [\n                A.HorizontalFlip(p=hflip_prob),\n                A.ShiftScaleRotate(\n                    shift_limit=0.0625, scale_limit=0.1, rotate_limit=10, p=ssr_prob\n                ),\n                A.RandomBrightnessContrast(p=random_bc_prob),\n            ]\n        )\n\n    def __call__(self, image):\n        image = self.transform(image=image)[\"image\"]\n        return image\n","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"To use augmentation, you can just define dataset with the `Transform` function."},{"metadata":{"trusted":true},"cell_type":"code","source":"aug_dataset = VinbigdataTwoClassDataset(dataset_dicts, image_transform=Transform())","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Let's visualize, looks good. <br/>\nYou can see each image looks different (rotated, brightness is different etc...) even if it is generated from the same image :)"},{"metadata":{"_kg_hide-input":true,"trusted":true},"cell_type":"code","source":"index = 0\n\nn_images = 4\n\nfig, axes = plt.subplots(1, n_images, figsize=(16, 5))\nfor i in range(n_images):\n    # Each time the data is accessed, the result is different due to random augmentation!\n    img, label = aug_dataset[index]\n    ax = axes[i]\n    ax.imshow(img.cpu().numpy().transpose((1, 2, 0)) / 255.)\n    ax.set_title(f\"{index}-th image: label {label}\")\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"**Extend to more general form**\n\nAugmentation is very important hyperparameter to improve model's performance, and you want to experiment with various configurations.<br/>\nBelow updated `Transform` function is written to **support all the augmentations implemented in albumentations**.<br/>\nYou can specify `aug_kwargs` from external configuration inside `flag` as follows:\n\n```\naug_kwargs:\n  HorizontalFlip: {\"p\": 0.5}\n  ShiftScaleRotate: {\"scale_limit\": 0.15, \"rotate_limit\": 10, \"p\": 0.5}\n  RandomBrightnessContrast: {\"p\": 0.5}\n  CoarseDropout: {\"max_holes\": 8, \"max_height\": 25, \"max_width\": 25, \"p\": 0.5}\n  Blur: {\"blur_limit\": [3, 7], \"p\": 0.5}\n  Downscale: {\"scale_min\": 0.25, \"scale_max\": 0.9, \"p\": 0.3}\n  RandomGamma: {\"gamma_limit\": [80, 120], \"p\": 0.6}\n```"},{"metadata":{"trusted":true},"cell_type":"code","source":"from typing import Dict\n\nimport albumentations as A\n\n\nclass Transform:\n    def __init__(self, aug_kwargs: Dict):\n        self.transform = A.Compose(\n            [getattr(A, name)(**kwargs) for name, kwargs in aug_kwargs.items()]\n        )\n\n    def __call__(self, image):\n        image = self.transform(image=image)[\"image\"]\n        return image","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"<a id=\"model\"></a>\n# Defining CNN models\n\nRecently, several libraries of CNN-collection are available on public.\n\nI will use `timm` this time. You don't need to impelment deep CNN models by yourself, you can just re-use latest research results without hustle.<br/>\nYou can focus on more about looking data and try experiment now."},{"metadata":{"_kg_hide-input":true,"_kg_hide-output":true,"trusted":true},"cell_type":"code","source":"from torch import nn\nfrom torch.nn import Linear\n\n\nclass CNNFixedPredictor(nn.Module):\n    def __init__(self, cnn: nn.Module, num_classes: int = 2):\n        super(CNNFixedPredictor, self).__init__()\n        self.cnn = cnn\n        self.lin = Linear(cnn.num_features, num_classes)\n        print(\"cnn.num_features\", cnn.num_features)\n\n        # We do not learn CNN parameters.\n        # https://pytorch.org/tutorials/beginner/finetuning_torchvision_models_tutorial.html\n        for param in self.cnn.parameters():\n            param.requires_grad = False\n\n    def forward(self, x):\n        feat = self.cnn(x)\n        return self.lin(feat)\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import timm\n\n\ndef build_predictor(model_name: str, model_mode: str = \"normal\"):\n    if model_mode == \"normal\":\n        # normal configuration. train all parameters.\n        return timm.create_model(model_name, pretrained=True, num_classes=2, in_chans=3)\n    elif model_mode == \"cnn_fixed\":\n        # normal configuration. train all parameters.\n        # https://rwightman.github.io/pytorch-image-models/feature_extraction/\n        timm_model = timm.create_model(model_name, pretrained=True, num_classes=0, in_chans=3)\n        return CNNFixedPredictor(timm_model, num_classes=2)\n    else:\n        raise ValueError(f\"[ERROR] Unexpected value model_mode={model_mode}\")\n","execution_count":null,"outputs":[]},{"metadata":{"_kg_hide-input":true,"trusted":true},"cell_type":"code","source":"import torch\n\n\ndef accuracy(y: torch.Tensor, t: torch.Tensor) -> torch.Tensor:\n    \"\"\"Computes multi-class classification accuracy\"\"\"\n    assert y.shape[:-1] == t.shape, f\"y {y.shape}, t {t.shape} is inconsistent.\"\n    pred_label = torch.max(y.detach(), dim=-1)[1]\n    count = t.nelement()\n    correct = (pred_label == t).sum().float()\n    acc = correct / count\n    return acc\n\n\ndef accuracy_with_logits(y: torch.Tensor, t: torch.Tensor) -> torch.Tensor:\n    \"\"\"Computes multi-class classification accuracy\"\"\"\n    assert y.shape == t.shape\n    gt_label = torch.max(t.detach(), dim=-1)[1]\n    return accuracy(y, gt_label)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import torch\nimport torch.nn.functional as F\n\n\ndef cross_entropy_with_logits(input, target, dim=-1):\n    loss = torch.sum(- target * F.log_softmax(input, dim), dim)\n    return loss.mean()\n","execution_count":null,"outputs":[]},{"metadata":{"_kg_hide-input":true,"trusted":true},"cell_type":"code","source":"import torch\nimport torch.nn.functional as F\nfrom torch import nn\nimport pytorch_pfn_extras as ppe\n\n\nclass Classifier(nn.Module):\n    \"\"\"two class classfication\"\"\"\n\n    def __init__(self, predictor, lossfun=cross_entropy_with_logits):\n        super().__init__()\n        self.predictor = predictor\n        self.lossfun = lossfun\n        self.prefix = \"\"\n\n    def forward(self, image, targets):\n        outputs = self.predictor(image)\n        loss = self.lossfun(outputs, targets)\n        metrics = {\n            f\"{self.prefix}loss\": loss.item(),\n            f\"{self.prefix}acc\": accuracy_with_logits(outputs, targets).item()\n        }\n        ppe.reporting.report(metrics, self)\n        return loss, metrics\n\n    def predict(self, data_loader):\n        pred = self.predict_proba(data_loader)\n        label = torch.argmax(pred, dim=1)\n        return label\n\n    def predict_proba(self, data_loader):\n        device: torch.device = next(self.parameters()).device\n        y_list = []\n        self.eval()\n        with torch.no_grad():\n            for batch in data_loader:\n                if isinstance(batch, (tuple, list)):\n                    # Assumes first argument is \"image\"\n                    batch = batch[0].to(device)\n                else:\n                    batch = batch.to(device)\n                y = self.predictor(batch)\n                y = torch.softmax(y, dim=-1)\n                y_list.append(y)\n        pred = torch.cat(y_list)\n        return pred\n","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"What kind of models are supported in the `timm` library?"},{"metadata":{"trusted":true},"cell_type":"code","source":"supported_models = timm.list_models()\nprint(f\"{len(supported_models)} models are supported in timm.\")\nprint(supported_models)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Wow more than 300 models are supported!<br/>\nIt of course includes **resnet** related models, **efficientnet**, etc.<br/>\nYou may wonder which model should be used?<br/>\nI will go with `resnet18` as a baseline at first, and try using more deeper/latest models in the experiment."},{"metadata":{},"cell_type":"markdown","source":"<a id=\"trainutil\"></a>\n# Training utils\n\nHere are training util methods. You can just copy these to use in other projects."},{"metadata":{"_kg_hide-input":true,"trusted":true},"cell_type":"code","source":"\"\"\"\nFrom https://github.com/pfnet-research/kaggle-lyft-motion-prediction-4th-place-solution\n\"\"\"\nfrom logging import getLogger\n\nfrom torch import nn\n\n\nclass EMA(object):\n    \"\"\"Exponential moving average of model parameters.\n\n    Ref\n     - https://github.com/tensorflow/addons/blob/v0.10.0/tensorflow_addons/optimizers/moving_average.py#L26-L103\n     - https://anmoljoshi.com/Pytorch-Dicussions/\n\n    Args:\n        model (nn.Module): Model with parameters whose EMA will be kept.\n        decay (float): Decay rate for exponential moving average.\n        strict (bool): Apply strict check for `assign` & `resume`.\n        use_dynamic_decay (bool): Dynamically change decay rate. If `True`, small decay rate is\n            used at the beginning of training to move moving average faster.\n    \"\"\"  # NOQA\n\n    def __init__(\n        self,\n        model: nn.Module,\n        decay: float,\n        strict: bool = True,\n        use_dynamic_decay: bool = True,\n    ):\n        self.decay = decay\n        self.model = model\n        self.strict = strict\n        self.use_dynamic_decay = use_dynamic_decay\n        self.logger = getLogger(__name__)\n        self.n_step = 0\n\n        self.shadow = {}\n        self.original = {}\n\n        # Flag to manage which parameter is assigned.\n        # When `False`, original model's parameter is used.\n        # When `True` (`assign` method is called), `shadow` parameter (ema param) is used.\n        self._assigned = False\n\n        # Register model parameters\n        for name, param in model.named_parameters():\n            if param.requires_grad:\n                self.shadow[name] = param.data.clone()\n\n    def step(self):\n        self.n_step += 1\n        if self.use_dynamic_decay:\n            _n_step = float(self.n_step)\n            decay = min(self.decay, (1.0 + _n_step) / (10.0 + _n_step))\n        else:\n            decay = self.decay\n\n        for name, param in self.model.named_parameters():\n            if param.requires_grad:\n                assert name in self.shadow\n                new_average = (1.0 - decay) * param.data + decay * self.shadow[name]\n                self.shadow[name] = new_average.clone()\n\n    # alias\n    __call__ = step\n\n    def assign(self):\n        \"\"\"Assign exponential moving average of parameter values to the respective parameters.\"\"\"\n        if self._assigned:\n            if self.strict:\n                raise ValueError(\"[ERROR] `assign` is called again before `resume`.\")\n            else:\n                self.logger.warning(\n                    \"`assign` is called again before `resume`.\"\n                    \"shadow parameter is already assigned, skip.\"\n                )\n                return\n\n        for name, param in self.model.named_parameters():\n            if param.requires_grad:\n                assert name in self.shadow\n                self.original[name] = param.data.clone()\n                param.data = self.shadow[name]\n        self._assigned = True\n\n    def resume(self):\n        \"\"\"Restore original parameters to a model.\n\n        That is, put back the values that were in each parameter at the last call to `assign`.\n        \"\"\"\n        if not self._assigned:\n            if self.strict:\n                raise ValueError(\"[ERROR] `resume` is called before `assign`.\")\n            else:\n                self.logger.warning(\"`resume` is called before `assign`, skip.\")\n                return\n\n        for name, param in self.model.named_parameters():\n            if param.requires_grad:\n                assert name in self.shadow\n                param.data = self.original[name]\n        self._assigned = False\n","execution_count":null,"outputs":[]},{"metadata":{"_kg_hide-input":true,"trusted":true},"cell_type":"code","source":"\"\"\"\nFrom https://github.com/pfnet-research/kaggle-lyft-motion-prediction-4th-place-solution\n\"\"\"\nfrom typing import Mapping, Any\n\nfrom torch import optim\n\nfrom pytorch_pfn_extras.training.extension import Extension, PRIORITY_READER\nfrom pytorch_pfn_extras.training.manager import ExtensionsManager\n\n\nclass LRScheduler(Extension):\n    \"\"\"A thin wrapper to resume the lr_scheduler\"\"\"\n\n    trigger = 1, 'iteration'\n    priority = PRIORITY_READER\n    name = None\n\n    def __init__(self, optimizer: optim.Optimizer, scheduler_type: str, scheduler_kwargs: Mapping[str, Any]) -> None:\n        super().__init__()\n        self.scheduler = getattr(optim.lr_scheduler, scheduler_type)(optimizer, **scheduler_kwargs)\n\n    def __call__(self, manager: ExtensionsManager) -> None:\n        self.scheduler.step()\n\n    def state_dict(self) -> None:\n        return self.scheduler.state_dict()\n\n    def load_state_dict(self, to_load) -> None:\n        self.scheduler.load_state_dict(to_load)\n","execution_count":null,"outputs":[]},{"metadata":{"_kg_hide-input":true,"trusted":true},"cell_type":"code","source":"from ignite.engine import Engine\n\n\ndef create_trainer(model, optimizer, device) -> Engine:\n    model.to(device)\n\n    def update_fn(engine, batch):\n        model.train()\n        optimizer.zero_grad()\n        loss, metrics = model(*[elem.to(device) for elem in batch])\n        loss.backward()\n        optimizer.step()\n        return metrics\n    trainer = Engine(update_fn)\n    return trainer\n","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"<a id=\"trainscript\"></a>\n# Training scripts"},{"metadata":{"_kg_hide-input":true,"trusted":true},"cell_type":"code","source":"import dataclasses\nimport os\nimport sys\nfrom pathlib import Path\n\nimport numpy as np\nimport pandas as pd\nimport pytorch_pfn_extras.training.extensions as E\nimport torch\nfrom ignite.engine import Events\nfrom pytorch_pfn_extras.training import IgniteExtensionsManager\nfrom sklearn.model_selection import StratifiedKFold\nfrom torch import nn, optim\nfrom torch.utils.data.dataloader import DataLoader","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Preparing data by 5-fold cross validation\n\nWhen we have few data, running stable evaluation is very important. \nWe can use cross validation to reduce validation error standard deviation.\n\nHere, I will use **[`StratifiedKFold`](https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.StratifiedKFold.html)** to keep the balance between normal/abnormal ratio same for the train & validation dataset.\n\nAccording to [this discussion](https://www.kaggle.com/c/vinbigdata-chest-xray-abnormalities-detection/discussion/208837#1139712), using multi label stratified kfold https://github.com/trent-b/iterative-stratification may be more stable."},{"metadata":{"trusted":true},"cell_type":"code","source":"skf = StratifiedKFold(n_splits=5, shuffle=True, random_state=flags.seed)\n# skf.get_n_splits(None, None)\ny = np.array([int(len(d[\"annotations\"]) > 0) for d in dataset_dicts])\nsplit_inds = list(skf.split(dataset_dicts, y))\ntrain_inds, valid_inds = split_inds[flags.target_fold]  # 0th fold\ntrain_dataset = VinbigdataTwoClassDataset(\n    [dataset_dicts[i] for i in train_inds],\n    image_transform=Transform(flags.aug_kwargs),\n    mixup_prob=flags.mixup_prob,\n    label_smoothing=flags.label_smoothing,\n)\nvalid_dataset = VinbigdataTwoClassDataset([dataset_dicts[i] for i in valid_inds])\n","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Write training code\n\npytorch-ignite & pytorch-pfn-extras are used here.\n\n - [pytorch/ignite](https://github.com/pytorch/ignite): It provides abstraction for writing training loop.\n - [pfnet/pytorch-pfn-extras](https://github.com/pfnet/pytorch-pfn-extras): It provides several \"extensions\" useful for training. Useful for **logging, printing, evaluating, saving the model, scheduling the learning rate** during training.\n \n**[Note] Why training abstraction library is used?**\n\nYou may feel understanding training abstraction code below is a bit unintuitive compared to writing \"raw\" training loop.<br/>\nThe advantage of abstracting the code is that we can re-use implemented handler class for other training, other competition.<br/>\nYou don't need to write code for saving models, logging training loss/metric, show progressbar etc.\nThese are done by provided util classes in `pytorch-pfn-extras` library!\n\nYou may refer my other kernel in previous competition too:\n - [Bengali: SEResNeXt training with pytorch](https://www.kaggle.com/corochann/bengali-seresnext-training-with-pytorch)\n - [Lyft: Training with multi-mode confidence](https://www.kaggle.com/corochann/lyft-training-with-multi-mode-confidence)"},{"metadata":{"trusted":true},"cell_type":"code","source":"train_loader = DataLoader(\n    train_dataset,\n    batch_size=flags.batchsize,\n    num_workers=flags.num_workers,\n    shuffle=True,\n    pin_memory=True,\n)\nvalid_loader = DataLoader(\n    valid_dataset,\n    batch_size=flags.valid_batchsize,\n    num_workers=flags.num_workers,\n    shuffle=False,\n    pin_memory=True,\n)\n\ndevice = torch.device(flags.device)\n\npredictor = build_predictor(model_name=flags.model_name, model_mode=flags.model_mode)\nclassifier = Classifier(predictor)\nmodel = classifier\n# optimizer = optim.Adam(model.parameters(), lr=1e-3)\noptimizer = optim.Adamax([param for param in model.parameters() if param.requires_grad], lr=1e-3)\n\n# Train setup\ntrainer = create_trainer(model, optimizer, device)\n\nema = EMA(predictor, decay=flags.ema_decay)\n\ndef eval_func(*batch):\n    loss, metrics = model(*[elem.to(device) for elem in batch])\n    # HACKING: report ema value with prefix.\n    if flags.ema_decay > 0:\n        classifier.prefix = \"ema_\"\n        ema.assign()\n        loss, metrics = model(*[elem.to(device) for elem in batch])\n        ema.resume()\n        classifier.prefix = \"\"\n\nvalid_evaluator = E.Evaluator(\n    valid_loader, model, progress_bar=False, eval_func=eval_func, device=device\n)\n\n# log_trigger = (10 if debug else 1000, \"iteration\")\nlog_trigger = (1, \"epoch\")\nlog_report = E.LogReport(trigger=log_trigger)\nextensions = [\n    log_report,\n    E.ProgressBarNotebook(update_interval=10 if debug else 100),  # Show progress bar during training\n    E.PrintReportNotebook(),  # Show \"log\" on jupyter notebook  \n    # E.ProgressBar(update_interval=10 if debug else 100),  # Show progress bar during training\n    # E.PrintReport(),  # Print \"log\" to terminal\n    E.FailOnNonNumber(),  # Stop training when nan is detected.\n]\nepoch = flags.epoch\nmodels = {\"main\": model}\noptimizers = {\"main\": optimizer}\nmanager = IgniteExtensionsManager(\n    trainer, models, optimizers, epoch, extensions=extensions, out_dir=str(outdir),\n)\n# Run evaluation for valid dataset in each epoch.\nmanager.extend(valid_evaluator)\n\n# Save predictor.pt every epoch\nmanager.extend(\n    E.snapshot_object(predictor, \"predictor.pt\"), trigger=(flags.snapshot_freq, \"epoch\")\n)\n# Check & Save best validation predictor.pt every epoch\n# manager.extend(E.snapshot_object(predictor, \"best_predictor.pt\"),\n#                trigger=MinValueTrigger(\"validation/module/nll\",\n#                trigger=(flags.snapshot_freq, \"iteration\")))\n\n# --- lr scheduler ---\nif flags.scheduler_type != \"\":\n    scheduler_type = flags.scheduler_type\n    print(f\"using {scheduler_type} scheduler with kwargs {flags.scheduler_kwargs}\")\n    manager.extend(\n        LRScheduler(optimizer, scheduler_type, flags.scheduler_kwargs),\n        trigger=flags.scheduler_trigger,\n    )\n\nmanager.extend(E.observe_lr(optimizer=optimizer), trigger=log_trigger)\n\nif flags.ema_decay > 0:\n    # Exponential moving average\n    manager.extend(lambda manager: ema(), trigger=(1, \"iteration\"))\n\n    def save_ema_model(manager):\n        ema.assign()\n        torch.save(predictor.state_dict(), outdir / \"predictor_ema.pt\")\n        ema.resume()\n\n    manager.extend(save_ema_model, trigger=(flags.snapshot_freq, \"epoch\"))\n\n_ = trainer.run(train_loader, max_epochs=epoch)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"So what is happening in above training abstraction? Let's understand what each extension did.\n\n**Extensions** - Each role:\n - **`ProgressBar` (`ProgressBarNotebook`)**: Shows training progress in formatted style.\n - **`LogReport`**: Logging metrics reported by `ppe.reporter.report` (see `LyftMultiRegressor` for reporting point) method and save to **log** file. It automatically collects reported value in each iteration and saves the \"mean\" of reported value for regular frequency (for example every 1 epoch).\n - **`PrintReport` (`PrintReportNotebook`)**: Prints the value which `LogReport` collected in formatted style.\n - **`Evaluator`**: Evaluate on validation dataset.\n - **`snapshot_object`**: Saves the object. Here the `model` is saved in regular interval `flags.snapshot_freq`. Even you quit training using Ctrl+C without finishing all the epoch, the intermediate trained model is saved and you can use it for inference.\n - **`LRScheduler`**: You can insert learning rate scheduling with this extension, together with the regular interval call specified by `trigger`. Here cosine annealing is applied (configured by Flags) by calling `scheduler.step()` every iteration.\n - **`observe_lr`**: `LogReport` will check optimizer's learning rate using this extension. So you can follow how the learning rate changed through the training.\n\n\nSuch many functionalities can be \"added\" easily using extensions!"},{"metadata":{},"cell_type":"markdown","source":"Also **Exponential Moving Average of model weights** is calculated by `EMA` class during training, together with showing its validation loss. We can usually obtrain more stable models with EMA."},{"metadata":{},"cell_type":"markdown","source":"You can obtrain training history results really easily by just accessing `LogReport` class, which is useful for managing a lot of experiments during kaggle competitions."},{"metadata":{"trusted":true},"cell_type":"code","source":"torch.save(predictor.state_dict(), outdir / \"predictor_last.pt\")\ndf = log_report.to_dataframe()\ndf.to_csv(outdir / \"log.csv\", index=False)\ndf","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"<a id=\"prediction\"></a>\n# Prediction on validation & test dataset"},{"metadata":{"trusted":true},"cell_type":"code","source":"# --- Prediction ---\nprint(\"Training done! Start prediction...\")\n# valid data\nvalid_pred = classifier.predict_proba(valid_loader).cpu().numpy()\nvalid_pred_df = pd.DataFrame({\n    \"image_id\": [dataset_dicts[i][\"image_id\"] for i in valid_inds],\n    \"class0\": valid_pred[:, 0],\n    \"class1\": valid_pred[:, 1]\n})\nvalid_pred_df.to_csv(outdir/\"valid_pred.csv\", index=False)\n\n# test data\ntest_meta = pd.read_csv(inputdir / \"vinbigdata-testmeta\" / \"test_meta.csv\")\ndataset_dicts_test = get_vinbigdata_dicts_test(imgdir, test_meta, debug=debug)\ntest_dataset = VinbigdataTwoClassDataset(dataset_dicts_test, train=False)\ntest_loader = DataLoader(\n    test_dataset,\n    batch_size=flags.valid_batchsize,\n    num_workers=flags.num_workers,\n    shuffle=False,\n    pin_memory=True,\n)\ntest_pred = classifier.predict_proba(test_loader).cpu().numpy()\ntest_pred_df = pd.DataFrame({\n    \"image_id\": [d[\"image_id\"] for d in dataset_dicts_test],\n    \"class0\": test_pred[:, 0],\n    \"class1\": test_pred[:, 1]\n})\ntest_pred_df.to_csv(outdir/\"test_pred.csv\", index=False)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# --- Test dataset prediction result ---\ntest_pred_df","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"sns.distplot(valid_pred_df[\"class0\"].values, color='green', label='valid pred')\nsns.distplot(test_pred_df[\"class0\"].values, color='orange', label='test pred')\nplt.title(\"Prediction results histogram\")\nplt.xlim([0., 1.])\nplt.legend()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Apply 2 class filter on detection prediction\n\nI will use detection prediction from the kernel:\n - [📸VinBigData detectron2 train](https://www.kaggle.com/corochann/vinbigdata-detectron2-train)\n - [📸VinBigData detectron2 prediction](https://www.kaggle.com/corochann/vinbigdata-detectron2-prediction)\n\nAnd 2class prediction is updated as dataset: [vinbigdata-2class-pred](https://www.kaggle.com/corochann/vinbigdata2classpred).\n\nAs mentioned in [VinBigData 🌟2 Class Filter🌟](https://www.kaggle.com/awsaf49/vinbigdata-2-class-filter) by @awsaf49, applying 2-class filter improves LB score significantly. (Please upvote his kernel as well!)<br/>\nAlso, it is mentioned that we can submit **14 prob 1 1 0 0** where the `prob` is the normal probability in the discussion [[Scoring bug] Improve your LB score by 0.053, just adding \"14 1 0 0 1 1\"](https://www.kaggle.com/c/vinbigdata-chest-xray-abnormalities-detection/discussion/211971)!\n\nHere, I will propose new post processing (similar to [this](https://www.kaggle.com/c/vinbigdata-chest-xray-abnormalities-detection/discussion/211971#1157809) by @pestipeti):\n\nHere `p` is the **normal probability**.\n\n1. `p < low_threshold`                   -> Do nothing, Keep det prediction.\n2. `low_threshold <= p < high_threshold` -> Just \"Add\" Normal prediction, **keep** detection prediction.\n3. `high_threshold <= p`                 -> Replace with Normal prediction with normal score 1.0, **remove** all detection predictoin.\n\n\n[Note] I also wrote another kernel to train 2-class model: [📸VinBigData 2-class classifier complete pipeline](https://www.kaggle.com/corochann/vinbigdata-2-class-classifier-complete-pipeline) to train these 2-class classifier model!"},{"metadata":{"trusted":true},"cell_type":"code","source":"# pred_2class = pd.read_csv(inputdir/\"vinbigdata-2class-prediction/2-cls test pred.csv\")  # LB 0.230\n# low_threshold = 0.0\n# high_threshold = 0.95\n\npred_2class = pd.read_csv(inputdir/\"vinbigdata2classpred/test_pred.csv\")\nlow_threshold = 0.0\nhigh_threshold = 0.976\npred_2class","execution_count":null,"outputs":[]},{"metadata":{"_kg_hide-input":true,"trusted":true},"cell_type":"code","source":"NORMAL = \"14 1 0 0 1 1\"\n\npred_det_df = pd.read_csv(inputdir/\"vinbigdata-detectron2-prediction/results/20210125_all_alb_aug_512_cos/submission.csv\")  # You can load from another submission.csv here too.\nn_normal_before = len(pred_det_df.query(\"PredictionString == @NORMAL\"))\nmerged_df = pd.merge(pred_det_df, pred_2class, on=\"image_id\", how=\"left\")\n\n# 1. p < low_threshold                   -> \"Keep\": Do nothing, Keep det prediction.\n# 2. low_threshold <= p < high_threshold -> \"Add\": Just \"Add\" Normal prediction\n# 3. high_threshold <= p                 -> \"Replace\": Replace with Normal prediction\n\nif \"target\" in merged_df.columns:\n    merged_df[\"class0\"] = 1 - merged_df[\"target\"]\n\nc0, c1, c2 = 0, 0, 0\nfor i in range(len(merged_df)):\n    p0 = merged_df.loc[i, \"class0\"]\n    if p0 < low_threshold:\n        # Keep, do nothing.\n        c0 += 1\n    elif low_threshold <= p0 and p0 < high_threshold:\n        # Add, keep \"det\" preds and add normal pred.\n        merged_df.loc[i, \"PredictionString\"] += f\" 14 {p0} 0 0 1 1\"\n        c1 += 1\n    else:\n        # Replace, remove all \"det\" preds.\n        merged_df.loc[i, \"PredictionString\"] = NORMAL\n        c2 += 1\n\nn_normal_after = len(merged_df.query(\"PredictionString == @NORMAL\"))\nprint(\n    f\"n_normal: {n_normal_before} -> {n_normal_after} with threshold {low_threshold} & {high_threshold}\"\n)\nprint(f\"Keep {c0} Add {c1} Replace {c2}\")\nsubmission_filepath = str(outdir / \"submission.csv\")\nsubmission_df = merged_df[[\"image_id\", \"PredictionString\"]]\nsubmission_df.to_csv(submission_filepath, index=False)\nprint(f\"Saved to {submission_filepath}\")","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"In my experiment:\n - The baseline submission: score 0.141\n - Just replace by threshold ([version3](https://www.kaggle.com/corochann/vinbigdata-detectron2-prediction?scriptVersionId=52412540) ): score 0.206\n - This post process (combine replace & add): **0.221**\n\nSo the score improved by about **0.8, which is significant**!\n\nIn more detail, I tried to change several `low_threshold` value and lower `low_threshold` achieved better results. So it may be okay to set `low_threshold=0.0` which means **always add \"No finding\" prediction with the predicted probability.**<br/>\nI also noticed that setting `high_threshold` value less than 1 is important, which means we have a benefit to **remove abnormality predictions** for the images which is highly likely to be normal.<br/>\nThis may be because my [training kernel](https://www.kaggle.com/corochann/vinbigdata-detectron2-train) currently only uses abnormal image during training and model tend to produce more abnormal boxes. I'm now thinking that it's better to include normal images for training to learn where there is **no** abnormality.<br/>\nAlso, I think it's nice to try **including \"No finding\" class during detection training** (by adding virtual \"No finding\" boxes, or by adding global classifier together with the detection)."},{"metadata":{},"cell_type":"markdown","source":"That's all!\n\n<h3 style=\"color:red\">If this kernel helps you, please upvote to keep me motivated 😁<br>Thanks!</h3>"},{"metadata":{},"cell_type":"markdown","source":"<a id=\"nextstep\"></a>\n# Next step\n\nI explained EDA - Training - Prediction pipeline for 2-class image classification in this kernel.<br/>\nYou can try changing training configurations by just changing `Flags` (`flags_dict`) configuration.\n\nFor example, you can change these paramters:\n\n - **Data**\n   - `imgdir_name`: You can use different preprocessed image introduced in [Multiple preprocessed datasets: 256/512/1024px, PNG and JPG, modified and original ratio](https://www.kaggle.com/c/vinbigdata-chest-xray-abnormalities-detection/discussion/207955) by @xhlulu.\n - **Model**\n   - `model_name`: You can try various kinds of models `timm` library support, by just changing model_name.\n - **Training**\n   - `epoch`, `batch_size`, `scheduler_type` etc: Try changing these hyperparamters, to see the difference!\n   - Augmentation: Please modify `Transform` class to add your augmentation, it's easy to support more augmentations with `albumentations` library.\n\n\nMy basic strategy is as follows:\n - Check training loss/training accuracy: If it is almost same with validation loss/accuracy and it is not accurate enough, model's representation power may be not enough, or data augmentation is too strong. You can try more deeper models, decrease data augmentation or using more rich data (high-resolution image).\n - Check training loss/validation loss difference: If validation loss is very high compared to training loss, it is a sign of overfitting. Try using smaller models, increase data augmentation or apply regularization (dropout etc)."},{"metadata":{},"cell_type":"markdown","source":"## Using other datasets?\n\nThere are several other X-ray images in this research field.<br/>\nThe paper of this competition dataset [\"VinDr-CXR: An open dataset of chest X-rays with radiologist's annotations”.](https://arxiv.org/pdf/2012.15029.pdf)\nsummarizes the existing public datasets.\n![image.png](attachment:image.png)\n\n\n[CheXpert](https://stanfordmlgroup.github.io/competitions/chexpert/) is one of the biggest dataset in this area. <br/>\nEven if local label (for detection) is not available, it helps to create more accurate model by combining to use this dataset.<br/>\nYou can register your name and E-mail address to Download this Dataset!","attachments":{"image.png":{"image/png":"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"}}},{"metadata":{},"cell_type":"markdown","source":"# Next to read\n\n[📸VinBigData detectron2 train](https://www.kaggle.com/corochann/vinbigdata-detectron2-train) kernel explains how to run object detection training, using `detectron2` library.\n\n[📸VinBigData detectron2 prediction](https://www.kaggle.com/corochann/vinbigdata-detectron2-prediction) kernel explains how to use trained model for the prediction and submisssion for this competition."},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]}],"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":4,"nbformat_minor":4}