{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"**Solution overview:** https://www.kaggle.com/c/hpa-single-cell-image-classification/discussion/241637\n\nThis notebook contains 4 main stages:\n1. Cell Segmentation\n2. Image Level Prediction\n3. Cell Level Prediction\n4. Ensemble & Final Prediction","metadata":{}},{"cell_type":"code","source":"!pip install /kaggle/input/efficientnet-keras-source-code\n!pip install /kaggle/input/pycocotools202/pycocotools-2.0.2-cp37-cp37m-linux_x86_64.whl\n!pip install /kaggle/input/hpapytorchzoozip/pytorch_zoo-master\n!pip install /kaggle/input/kerasapplications\n!pip install /kaggle/input/efficientnet-keras-source-code/ -q --no-deps\n!pip install /kaggle/input/hpacellsegmentatormaster/HPA-Cell-Segmentation-master/\n!pip install /kaggle/input/gputil/","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import sys\nsys.path.append('../input/efficientnet-pytorch/EfficientNet-PyTorch/EfficientNet-PyTorch-master')\nimport os\nimport gc\nimport shutil\nfrom tqdm.notebook import tqdm\nimport pickle\nimport math\nimport numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport cv2\nimport tensorflow as tf\nimport tensorflow.keras.backend as K\nimport tensorflow as tfa\nimport tensorflow_addons as tfa\nfrom tensorflow.keras.applications import densenet\nfrom tensorflow.keras.applications import ResNet50V2\nfrom tensorflow.keras.applications import InceptionV3\nfrom tensorflow.keras.applications import MobileNetV2\nfrom tensorflow.keras.applications import Xception\nimport efficientnet.tfkeras as efn\nimport torch\nfrom fastai.vision.all import *\nfrom efficientnet_pytorch import EfficientNet\nfrom pycocotools import mask as coco_mask\nimport base64\nimport typing as t\nimport zlib\nfrom GPUtil import showUtilization as gpu_usage\n\nimport os.path\nimport urllib\nimport zipfile\n\nimport scipy.ndimage as ndi\nfrom skimage import filters, measure, segmentation\nfrom skimage.morphology import (binary_erosion, closing, disk,\n                                remove_small_holes, remove_small_objects)\nfrom hpacellseg.cellsegmentator import *\nfrom glob import glob","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"os.makedirs('/root/.cache/torch/hub/checkpoints/', exist_ok=True)\n\n!cp '../input/resnet50/resnet50.pth' '/root/.cache/torch/hub/checkpoints/resnet50-19c8e357.pth'\n\n!cp '../input/efficientnet-pytorch-pretrained/adv-efficientnet-b1-0f3ce85a.pth' \\\n'/root/.cache/torch/hub/checkpoints/'\n\n!cp '../input/efficientnet-pytorch-pretrained/adv-efficientnet-b5-86493f6b.pth' \\\n'/root/.cache/torch/hub/checkpoints/'\n\n!cp '../input/efficientnet-pytorch/efficientnet-b1-dbc7070a.pth' '/root/.cache/torch/hub/checkpoints/'\n\n!cp '../input/efficientnet-pytorch/efficientnet-b5-586e6cc6.pth' '/root/.cache/torch/hub/checkpoints/'","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Global config","metadata":{}},{"cell_type":"code","source":"%%time\nclass Config:\n    seed = 42\n    segmentor_bs = 8\n    cell_level_bs = 128\n    image_level_bs = 64\n    fast_segment = True\n    save_preds = True\n    hidden_only = False\n    showed_df = pd.read_csv('../input/hpa-public-test-submission/my_empty_submission.csv')\n    sub_df = pd.read_csv('../input/hpa-single-cell-image-classification/sample_submission.csv')\n\n    if hidden_only:\n        sub_df = sub_df[~sub_df['ID'].isin(showed_df['ID'])].reset_index(drop=True)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"Config.sub_df.tail()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def seed_everything(seed=Config.seed):\n    os.environ['PYTHONHASHSEED'] = str(seed)\n    np.random.seed(seed)\n    torch.manual_seed(seed)\n    torch.cuda.manual_seed(seed)\n    torch.backends.cudnn.deterministic = True\n\nseed_everything()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"gc.collect()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 1. Cell segmentation","metadata":{}},{"cell_type":"code","source":"def encode_binary_mask(mask: np.ndarray) -> t.Text:\n    \"\"\"Converts a binary mask into OID challenge encoding ascii text.\"\"\"\n\n    # check input mask --\n    if mask.dtype != np.bool:\n        raise ValueError(\"encode_binary_mask expects a binary mask, received dtype == %s\" %mask.dtype)\n\n    mask = np.squeeze(mask)\n    if len(mask.shape) != 2:\n        raise ValueError(\"encode_binary_mask expects a 2d mask, received shape == %s\" %mask.shape)\n\n    # convert input mask to expected COCO API input --\n    mask_to_encode = np.asfortranarray(mask.reshape(mask.shape[0], mask.shape[1], 1).astype(np.uint8))\n\n    # RLE encode mask --\n    encoded_mask = coco_mask.encode(mask_to_encode)[0][\"counts\"]\n\n    # compress and base64 encoding --\n    binary_str = zlib.compress(encoded_mask, zlib.Z_BEST_COMPRESSION)\n    base64_str = base64.b64encode(binary_str)\n    return base64_str.decode('ascii')","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def load_images(df, root='../input/hpa-single-cell-image-classification/test/'):\n    blue = []\n    ryb = []\n    image_ids = []\n\n    for i, row in df.iterrows():\n        r = os.path.join(root, f'{row.ID}_red.png')\n        y = os.path.join(root, f'{row.ID}_yellow.png')\n        b = os.path.join(root, f'{row.ID}_blue.png')\n        r = cv2.imread(r, cv2.IMREAD_GRAYSCALE)\n        y = cv2.imread(y, cv2.IMREAD_GRAYSCALE)\n        b = cv2.imread(b, cv2.IMREAD_GRAYSCALE)\n        blue_image = cv2.resize(b, (512, 512))\n        ryb_image = cv2.resize(np.stack((r, y, b), axis=2), (512, 512))\n        blue.append(blue_image)\n        ryb.append(ryb_image)\n        image_ids.append(row.ID)\n\n    return blue, ryb, image_ids","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_cropped_cell(img, msk):\n    bmask = msk.astype(int)[...,None]\n    masked_img = img * bmask\n    true_points = np.argwhere(bmask)\n    top_left = true_points.min(axis=0)\n    bottom_right = true_points.max(axis=0)\n    cropped_arr = masked_img[top_left[0]:bottom_right[0]+1,top_left[1]:bottom_right[1]+1]\n    return cropped_arr","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def read_img(image_id, color, root='../input/hpa-single-cell-image-classification/test', image_size=None):\n    filename = f'{root}/{image_id}_{color}.png'\n    assert os.path.exists(filename), f'not found {filename}'\n    img = cv2.imread(filename, cv2.IMREAD_UNCHANGED)\n    if image_size is not None:\n        img = cv2.resize(img, (image_size, image_size))\n    if img.max() > 255:\n        img_max = img.max()\n        img = (img/255).astype('uint8')\n    return img","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\"\"\"\nThis code is from host's public HPA Cell Segmentation github respository: https://github.com/CellProfiling/HPA-Cell-Segmentation\nwith modification from: https://www.kaggle.com/linshokaku/faster-hpa-cell-segmentation\n\"\"\"\n\nclass CellSegmentator(object):\n    \"\"\"Uses pretrained DPN-Unet models to segment cells from images.\"\"\"\n\n    def __init__(\n        self,\n        nuclei_model=\"../input/hpacellsegmentatormodelweights/dpn_unet_nuclei_v1.pth\",\n        cell_model=\"../input/hpacellsegmentatormodelweights/dpn_unet_cell_3ch_v1.pth\",\n        scale_factor=1.0,\n        device=\"cuda\",\n        padding=False,\n        multi_channel_model=True,\n    ):\n        \"\"\"Class for segmenting nuclei and whole cells from confocal microscopy images.\n        It takes lists of images and returns the raw output from the\n        specified segmentation model. Models can be automatically\n        downloaded if they are not already available on the system.\n        When working with images from the Huan Protein Cell atlas, the\n        outputs from this class' methods are well combined with the\n        label functions in the utils module.\n        Note that for cell segmentation, there are two possible models\n        available. One that works with 2 channeled images and one that\n        takes 3 channels.\n        Keyword arguments:\n        nuclei_model -- A loaded torch nuclei segmentation model or the\n                        path to a file which contains such a model.\n                        If the argument is a path that points to a non-existant file,\n                        a pretrained nuclei_model is going to get downloaded to the\n                        specified path (default: './nuclei_model.pth').\n        cell_model -- A loaded torch cell segmentation model or the\n                      path to a file which contains such a model.\n                      The cell_model argument can be None if only nuclei\n                      are to be segmented (default: './cell_model.pth').\n        scale_factor -- How much to scale images before they are fed to\n                        segmentation models. Segmentations will be scaled back\n                        up by 1/scale_factor to match the original image\n                        (default: 0.25).\n        device -- The device on which to run the models.\n                  This should either be 'cpu' or 'cuda' or pointed cuda\n                  device like 'cuda:0' (default: 'cuda').\n        padding -- Whether to add padding to the images before feeding the\n                   images to the network. (default: False).\n        multi_channel_model -- Control whether to use the 3-channel cell model or not.\n                               If True, use the 3-channel model, otherwise use the\n                               2-channel version (default: True).\n        \"\"\"\n        if device != \"cuda\" and device != \"cpu\" and \"cuda\" not in device:\n            raise ValueError(f\"{device} is not a valid device (cuda/cpu)\")\n        if device != \"cpu\":\n            try:\n                assert torch.cuda.is_available()\n            except AssertionError:\n                print(\"No GPU found, using CPU.\", file=sys.stderr)\n                device = \"cpu\"\n        self.device = device\n\n        if isinstance(nuclei_model, str):\n            if not os.path.exists(nuclei_model):\n                print(\n                    f\"Could not find {nuclei_model}. Downloading it now\",\n                    file=sys.stderr,\n                )\n                download_with_url(NUCLEI_MODEL_URL, nuclei_model)\n            nuclei_model = torch.load(\n                nuclei_model, map_location=torch.device(self.device)\n            )\n        if isinstance(nuclei_model, torch.nn.DataParallel) and device == \"cpu\":\n            nuclei_model = nuclei_model.module\n\n        self.nuclei_model = nuclei_model.to(self.device).eval()\n\n        self.multi_channel_model = multi_channel_model\n        if isinstance(cell_model, str):\n            if not os.path.exists(cell_model):\n                print(\n                    f\"Could not find {cell_model}. Downloading it now\", file=sys.stderr\n                )\n                if self.multi_channel_model:\n                    download_with_url(MULTI_CHANNEL_CELL_MODEL_URL, cell_model)\n                else:\n                    download_with_url(TWO_CHANNEL_CELL_MODEL_URL, cell_model)\n            cell_model = torch.load(cell_model, map_location=torch.device(self.device))\n        self.cell_model = cell_model.to(self.device).eval()\n        self.scale_factor = scale_factor\n        self.padding = padding\n\n    def _image_conversion(self, images):\n        \"\"\"Convert/Format images to RGB image arrays list for cell predictions.\n        Intended for internal use only.\n        Keyword arguments:\n        images -- list of lists of image paths/arrays. It should following the\n                 pattern if with er channel input,\n                 [\n                     [microtubule_path0/image_array0, microtubule_path1/image_array1, ...],\n                     [er_path0/image_array0, er_path1/image_array1, ...],\n                     [nuclei_path0/image_array0, nuclei_path1/image_array1, ...]\n                 ]\n                 or if without er input,\n                 [\n                     [microtubule_path0/image_array0, microtubule_path1/image_array1, ...],\n                     None,\n                     [nuclei_path0/image_array0, nuclei_path1/image_array1, ...]\n                 ]\n        \"\"\"\n        microtubule_imgs, er_imgs, nuclei_imgs = images\n        if self.multi_channel_model:\n            if not isinstance(er_imgs, list):\n                raise ValueError(\"Please speicify the image path(s) for er channels!\")\n        else:\n            if not er_imgs is None:\n                raise ValueError(\n                    \"second channel should be None for two channel model predition!\"\n                )\n\n        if not isinstance(microtubule_imgs, list):\n            raise ValueError(\"The microtubule images should be a list\")\n        if not isinstance(nuclei_imgs, list):\n            raise ValueError(\"The microtubule images should be a list\")\n\n        if er_imgs:\n            if not len(microtubule_imgs) == len(er_imgs) == len(nuclei_imgs):\n                raise ValueError(\"The lists of images needs to be the same length\")\n        else:\n            if not len(microtubule_imgs) == len(nuclei_imgs):\n                raise ValueError(\"The lists of images needs to be the same length\")\n\n        if not all(isinstance(item, np.ndarray) for item in microtubule_imgs):\n            microtubule_imgs = [\n                os.path.expanduser(item) for _, item in enumerate(microtubule_imgs)\n            ]\n            nuclei_imgs = [\n                os.path.expanduser(item) for _, item in enumerate(nuclei_imgs)\n            ]\n\n            microtubule_imgs = list(\n                map(lambda item: imageio.imread(item), microtubule_imgs)\n            )\n            nuclei_imgs = list(map(lambda item: imageio.imread(item), nuclei_imgs))\n            if er_imgs:\n                er_imgs = [os.path.expanduser(item) for _, item in enumerate(er_imgs)]\n                er_imgs = list(map(lambda item: imageio.imread(item), er_imgs))\n\n        if not er_imgs:\n            er_imgs = [\n                np.zeros(item.shape, dtype=item.dtype)\n                for _, item in enumerate(microtubule_imgs)\n            ]\n        cell_imgs = list(\n            map(\n                lambda item: np.dstack((item[0], item[1], item[2])),\n                list(zip(microtubule_imgs, er_imgs, nuclei_imgs)),\n            )\n        )\n\n        return cell_imgs\n\n    def pred_nuclei(self, images):\n        \"\"\"Predict the nuclei segmentation.\n        Keyword arguments:\n        images -- A list of image arrays or a list of paths to images.\n                  If as a list of image arrays, the images could be 2d images\n                  of nuclei data array only, or must have the nuclei data in\n                  the blue channel; If as a list of file paths, the images\n                  could be RGB image files or gray scale nuclei image file\n                  paths.\n        Returns:\n        predictions -- A list of predictions of nuclei segmentation for each nuclei image.\n        \"\"\"\n\n        def _preprocess(image):\n            if isinstance(image, str):\n                image = imageio.imread(image)\n            self.target_shape = image.shape\n            if len(image.shape) == 2:\n                image = np.dstack((image, image, image))\n            image = transform.rescale(image, self.scale_factor, multichannel=True)\n            nuc_image = np.dstack((image[..., 2], image[..., 2], image[..., 2]))\n            if self.padding:\n                rows, cols = nuc_image.shape[:2]\n                self.scaled_shape = rows, cols\n                nuc_image = cv2.copyMakeBorder(\n                    nuc_image,\n                    32,\n                    (32 - rows % 32),\n                    32,\n                    (32 - cols % 32),\n                    cv2.BORDER_REFLECT,\n                )\n            nuc_image = nuc_image.transpose([2, 0, 1])\n            return nuc_image\n\n        def _segment_helper(imgs):\n            with torch.no_grad():\n                mean = torch.as_tensor(NORMALIZE[\"mean\"], device=self.device)\n                std = torch.as_tensor(NORMALIZE[\"std\"], device=self.device)\n                imgs = torch.tensor(imgs).float()\n                imgs = imgs.to(self.device)\n                imgs = imgs.sub_(mean[:, None, None]).div_(std[:, None, None])\n\n                imgs = self.nuclei_model(imgs)\n                imgs = F.softmax(imgs, dim=1)\n                return imgs\n\n        preprocessed_imgs = list(map(_preprocess, images))\n        bs = 24\n        predictions = []\n        for i in range(0, len(preprocessed_imgs), bs):\n            start = i\n            end = min(len(preprocessed_imgs), i+bs)\n            x = preprocessed_imgs[start:end]\n            pred = _segment_helper(x).cpu().numpy()\n            predictions.append(pred)\n        predictions = list(np.concatenate(predictions, axis=0))\n        predictions = map(util.img_as_ubyte, predictions)\n        predictions = list(map(self._restore_scaling_padding, predictions))\n        return predictions\n\n    def _restore_scaling_padding(self, n_prediction):\n        \"\"\"Restore an image from scaling and padding.\n        This method is intended for internal use.\n        It takes the output from the nuclei model as input.\n        \"\"\"\n        n_prediction = n_prediction.transpose([1, 2, 0])\n        if self.padding:\n            n_prediction = n_prediction[\n                32 : 32 + self.scaled_shape[0], 32 : 32 + self.scaled_shape[1], ...\n            ]\n        if not self.scale_factor == 1:\n            n_prediction[..., 0] = 0\n            n_prediction = cv2.resize(\n                n_prediction,\n                (self.target_shape[0], self.target_shape[1]),\n                interpolation=cv2.INTER_AREA,\n            )\n        return n_prediction\n\n    def pred_cells(self, images, precombined=False):\n        \"\"\"Predict the cell segmentation for a list of images.\n        Keyword arguments:\n        images -- list of lists of image paths/arrays. It should following the\n                  pattern if with er channel input,\n                  [\n                      [microtubule_path0/image_array0, microtubule_path1/image_array1, ...],\n                      [er_path0/image_array0, er_path1/image_array1, ...],\n                      [nuclei_path0/image_array0, nuclei_path1/image_array1, ...]\n                  ]\n                  or if without er input,\n                  [\n                      [microtubule_path0/image_array0, microtubule_path1/image_array1, ...],\n                      None,\n                      [nuclei_path0/image_array0, nuclei_path1/image_array1, ...]\n                  ]\n                  The ER channel is required when multichannel is True\n                  and required to be None when multichannel is False.\n                  The images needs to be of the same size.\n        precombined -- If precombined is True, the list of images is instead supposed to be\n                       a list of RGB numpy arrays (default: False).\n        Returns:\n        predictions -- a list of predictions of cell segmentations.\n        \"\"\"\n\n        def _preprocess(image):\n            self.target_shape = image.shape\n            if not len(image.shape) == 3:\n                raise ValueError(\"image should has 3 channels\")\n            cell_image = transform.rescale(image, self.scale_factor, multichannel=True)\n            if self.padding:\n                rows, cols = cell_image.shape[:2]\n                self.scaled_shape = rows, cols\n                cell_image = cv2.copyMakeBorder(\n                    cell_image,\n                    32,\n                    (32 - rows % 32),\n                    32,\n                    (32 - cols % 32),\n                    cv2.BORDER_REFLECT,\n                )\n            cell_image = cell_image.transpose([2, 0, 1])\n            return cell_image\n\n        def _segment_helper(imgs):\n            with torch.no_grad():\n                mean = torch.as_tensor(NORMALIZE[\"mean\"], device=self.device)\n                std = torch.as_tensor(NORMALIZE[\"std\"], device=self.device)\n                imgs = torch.tensor(imgs).float()\n                imgs = imgs.to(self.device)\n                imgs = imgs.sub_(mean[:, None, None]).div_(std[:, None, None])\n\n                imgs = self.cell_model(imgs)\n                imgs = F.softmax(imgs, dim=1)\n                return imgs\n\n        if not precombined:\n            images = self._image_conversion(images)\n        preprocessed_imgs = list(map(_preprocess, images))\n        bs = 24\n        predictions = []\n        for i in range(0, len(preprocessed_imgs), bs):\n            start = i\n            end = min(len(preprocessed_imgs), i+bs)\n            x = preprocessed_imgs[start:end]\n            pred = _segment_helper(x).cpu().numpy()\n            predictions.append(pred)\n        predictions = list(np.concatenate(predictions, axis=0))\n        predictions = map(self._restore_scaling_padding, predictions)\n        predictions = list(map(util.img_as_ubyte, predictions))\n\n        return predictions\n\n\nHIGH_THRESHOLD = 0.4\nLOW_THRESHOLD = HIGH_THRESHOLD - 0.25\n\n\ndef download_with_url(url_string, file_path, unzip=False):\n    \"\"\"Download file with a link.\"\"\"\n    with urllib.request.urlopen(url_string) as response, open(\n        file_path, \"wb\"\n    ) as out_file:\n        data = response.read()  # a `bytes` object\n        out_file.write(data)\n\n    if unzip:\n        with zipfile.ZipFile(file_path, \"r\") as zip_ref:\n            zip_ref.extractall(os.path.dirname(file_path))\n\n\ndef __fill_holes(image):\n    \"\"\"Fill_holes for labelled image, with a unique number.\"\"\"\n    boundaries = segmentation.find_boundaries(image)\n    image = np.multiply(image, np.invert(boundaries))\n    image = ndi.binary_fill_holes(image > 0)\n    image = ndi.label(image)[0]\n    return image\n\n\ndef label_cell(nuclei_pred, cell_pred):\n    \"\"\"Label the cells and the nuclei.\n    Keyword arguments:\n    nuclei_pred -- a 3D numpy array of a prediction from a nuclei image.\n    cell_pred -- a 3D numpy array of a prediction from a cell image.\n    Returns:\n    A tuple containing:\n    nuclei-label -- A nuclei mask data array.\n    cell-label  -- A cell mask data array.\n    0's in the data arrays indicate background while a continous\n    strech of a specific number indicates the area for a specific\n    cell.\n    The same value in cell mask and nuclei mask refers to the identical cell.\n    NOTE: The nuclei labeling from this function will be sligthly\n    different from the values in :func:`label_nuclei` as this version\n    will use information from the cell-predictions to make better\n    estimates.\n    \"\"\"\n    def __wsh(\n        mask_img,\n        threshold,\n        border_img,\n        seeds,\n        threshold_adjustment=0.35,\n        small_object_size_cutoff=10,\n    ):\n        img_copy = np.copy(mask_img)\n        m = seeds * border_img  # * dt\n        img_copy[m <= threshold + threshold_adjustment] = 0\n        img_copy[m > threshold + threshold_adjustment] = 1\n        img_copy = img_copy.astype(np.bool)\n        img_copy = remove_small_objects(img_copy, small_object_size_cutoff).astype(\n            np.uint8\n        )\n\n        mask_img[mask_img <= threshold] = 0\n        mask_img[mask_img > threshold] = 1\n        mask_img = mask_img.astype(np.bool)\n        mask_img = remove_small_holes(mask_img, 63)\n        mask_img = remove_small_objects(mask_img, 1).astype(np.uint8)\n        markers = ndi.label(img_copy, output=np.uint32)[0]\n        labeled_array = segmentation.watershed(\n            mask_img, markers, mask=mask_img, watershed_line=True\n        )\n        return labeled_array\n\n    nuclei_label = __wsh(\n        nuclei_pred[..., 2] / 255.0,\n        0.4,\n        1 - (nuclei_pred[..., 1] + cell_pred[..., 1]) / 255.0 > 0.05,\n        nuclei_pred[..., 2] / 255,\n        threshold_adjustment=-0.25,\n        small_object_size_cutoff=32,\n    )\n\n    # for hpa_image, to remove the small pseduo nuclei\n    nuclei_label = remove_small_objects(nuclei_label, 157)\n    nuclei_label = measure.label(nuclei_label)\n    # this is to remove the cell borders' signal from cell mask.\n    # could use np.logical_and with some revision, to replace this func.\n    # Tuned for segmentation hpa images\n    threshold_value = max(0.22, filters.threshold_otsu(cell_pred[..., 2] / 255) * 0.5)\n    # exclude the green area first\n    cell_region = np.multiply(\n        cell_pred[..., 2] / 255 > threshold_value,\n        np.invert(np.asarray(cell_pred[..., 1] / 255 > 0.05, dtype=np.int8)),\n    )\n    sk = np.asarray(cell_region, dtype=np.int8)\n    distance = np.clip(cell_pred[..., 2], 255 * threshold_value, cell_pred[..., 2])\n    cell_label = segmentation.watershed(-distance, nuclei_label, mask=sk)\n    cell_label = remove_small_objects(cell_label, 344).astype(np.uint8)\n    selem = disk(2)\n    cell_label = closing(cell_label, selem)\n    cell_label = __fill_holes(cell_label)\n    # this part is to use green channel, and extend cell label to green channel\n    # benefit is to exclude cells clear on border but without nucleus\n    sk = np.asarray(\n        np.add(\n            np.asarray(cell_label > 0, dtype=np.int8),\n            np.asarray(cell_pred[..., 1] / 255 > 0.05, dtype=np.int8),\n        )\n        > 0,\n        dtype=np.int8,\n    )\n    cell_label = segmentation.watershed(-distance, cell_label, mask=sk)\n    cell_label = __fill_holes(cell_label)\n    cell_label = np.asarray(cell_label > 0, dtype=np.uint8)\n    cell_label = measure.label(cell_label)\n    cell_label = remove_small_objects(cell_label, 344)\n    cell_label = measure.label(cell_label)\n    cell_label = np.asarray(cell_label, dtype=np.uint16)\n    nuclei_label = np.multiply(cell_label > 0, nuclei_label) > 0\n    nuclei_label = measure.label(nuclei_label)\n    nuclei_label = remove_small_objects(nuclei_label, 157)\n    nuclei_label = np.multiply(cell_label, nuclei_label > 0)\n\n    return nuclei_label, cell_label","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"cell_mask_dir = 'hpa_cell_mask'\nnucl_mask_dir = 'hpa_nuclei_mask'\n\nos.makedirs(cell_mask_dir, exist_ok=True)\nos.makedirs(nucl_mask_dir, exist_ok=True)\n\ndata_df = Config.sub_df.copy()\n\nsizes = np.unique(data_df[['ImageWidth', 'ImageHeight']].values, axis=0)\nsizes = [tuple(size) for size in sizes]\n\nif Config.fast_segment:\n    cellsegmentor = CellSegmentator()\nelse:    \n    NUC_MODEL = \"../input/hpacellsegmentatormodelweights/dpn_unet_nuclei_v1.pth\"\n    CELL_MODEL = \"../input/hpacellsegmentatormodelweights/dpn_unet_cell_3ch_v1.pth\"\n    import hpacellseg.cellsegmentator as cellsegmentator\n    cellsegmentor = cellsegmentator.CellSegmentator(\n            NUC_MODEL,\n            CELL_MODEL,\n            scale_factor=0.25,\n            device=\"cuda\",\n            padding=True,\n            multi_channel_model=True,\n        )","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%%time\nbatch_size = Config.segmentor_bs\n\nfor size in tqdm(sizes):\n    data_df_gr = data_df[data_df[['ImageWidth', 'ImageHeight']].values==size]\n    data_size = len(data_df_gr)\n    for i in tqdm(range(0, data_size, batch_size), position=0, leave=True):\n\n        start = i\n        end = min(len(data_df_gr), start + batch_size)\n        blue_batch, ryb_batch, image_ids = load_images(data_df_gr[start:end])\n        nuc_segmentations = cellsegmentor.pred_nuclei(blue_batch)\n        cell_segmentations = cellsegmentor.pred_cells(ryb_batch, precombined=True)\n\n        for i, image_id in enumerate(image_ids):\n            nucl_mask, cell_mask = label_cell(nuc_segmentations[i], cell_segmentations[i])\n            nucl_mask = cv2.resize(nucl_mask, size, interpolation=cv2.INTER_NEAREST)\n            cell_mask = cv2.resize(cell_mask, size, interpolation=cv2.INTER_NEAREST)\n\n            if len(cell_mask) == 0:\n                print('warning: no mask found!')\n            np.savez_compressed(f'{cell_mask_dir}/{image_id}', cell_mask)\n            np.savez_compressed(f'{nucl_mask_dir}/{image_id}', nucl_mask)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%%time\nsingle_cells_save_dir = 'single_cells'\nos.makedirs(single_cells_save_dir, exist_ok=True)\n\nlbls = []\nnum_files = len(data_df)\nall_cells = []\n\nfor idx in tqdm(range(num_files)):\n    image_id = data_df.iloc[idx].ID\n    cell_mask = np.load(f'{cell_mask_dir}/{image_id}.npz')['arr_0']\n    red = read_img(image_id, \"red\")\n    green = read_img(image_id, \"green\")\n    blue = read_img(image_id, \"blue\")\n    stacked_image = np.transpose(np.array([blue, green, red]), (1,2,0))\n\n    for j in range(1, np.max(cell_mask) + 1):\n        bmask = (cell_mask == j)\n        enc = encode_binary_mask(bmask)\n        cropped_cell = get_cropped_cell(stacked_image, bmask)\n        fname = f'{image_id}_{j}.jpg'\n        cv2.imwrite(os.path.join(single_cells_save_dir, fname), cropped_cell)\n        all_cells.append({\n            'image_id': image_id,\n            'fname': fname,\n            'cell_id': j,\n            'size1': cropped_cell.shape[0],\n            'size2': cropped_cell.shape[1],\n            'enc': enc,\n        })\ncell_df = pd.DataFrame(all_cells)\ncell_df.to_csv('cell_df.csv', index=False)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"if len(cell_df) == 0:\n    cell_df = pd.DataFrame({\n            'image_id': [],\n            'fname': [],\n            'cell_id': [],\n            'size1': [],\n            'size2': [],\n            'enc': [],\n        }, dtype='object')\ncell_df.tail()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print('before empty cache')\nprint(gpu_usage())\ntorch.cuda.empty_cache()\ndel cellsegmentor\nprint('\\nafter empty cache')\nprint(gpu_usage())\ngc.collect()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 2. Cell Level Prediction","metadata":{}},{"cell_type":"code","source":"def get_learner(model_name, lr=1e-3):\n    assert model_name in [f'b{i}' for i in range(8)] + ['resnet50', 'resnet101']\n    \n    opt_func = partial(Adam, lr=lr, wd=0.01, eps=1e-8)\n\n    if model_name == 'resnet50':\n        return cnn_learner(dls, resnet50, metrics=[accuracy_multi, PrecisionMulti()]).to_fp16()\n\n    elif model_name == 'resnet101':\n        return cnn_learner(dls, resnet101, metrics=[accuracy_multi, PrecisionMulti()]).to_fp16()\n\n    elif model_name == 'b0':\n        model = EfficientNet.from_pretrained(\"efficientnet-b0\", advprop=True)\n        model._fc = nn.Linear(1280, dls.c)\n\n    elif model_name == 'b1':\n        model = EfficientNet.from_pretrained(\"efficientnet-b1\", advprop=True)  \n        model._fc = nn.Linear(1280, dls.c)\n        \n    elif model_name == 'b2':\n        model = EfficientNet.from_pretrained(\"efficientnet-b2\", advprop=True)  \n        model._fc = nn.Linear(1280, dls.c)\n\n    elif model_name == 'b3':\n        model = EfficientNet.from_pretrained(\"efficientnet-b3\", advprop=True)  \n        model._fc = nn.Linear(1536, dls.c)\n\n    elif model_name == 'b4':\n        model = EfficientNet.from_pretrained(\"efficientnet-b4\", advprop=True)  \n        model._fc = nn.Linear(1792, dls.c)\n\n    elif model_name == 'b5':\n        model = EfficientNet.from_pretrained(\"efficientnet-b5\", advprop=True)\n        model._fc = nn.Linear(2048, dls.c)\n\n    elif model_name == 'b6':\n        model = EfficientNet.from_pretrained(\"efficientnet-b6\", advprop=True)\n        model._fc = nn.Linear(2304, dls.c)\n        \n    elif model_name == 'b7':\n        model = EfficientNet.from_pretrained(\"efficientnet-b7\", advprop=True)\n        model._fc = nn.Linear(2560, dls.c)\n\n    learn = Learner(\n        dls, model, opt_func=opt_func,\n        metrics=[accuracy_multi, PrecisionMulti()]\n        ).to_fp16()\n\n    return learn","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"cell_df['path'] = single_cells_save_dir + '/' + cell_df['fname']\ncell_df['image_labels'] = '0'\ncell_df.tail()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model_dict = {'GREEN': {'resnet50': [('../input/single-cell-models/resnet50_green_model_3.pth', 2)],\n\n                       'b1': [('../input/single-cell-models/b1_green_model_1.pth', 3)],\n\n                      'b5': [('../input/single-cell-models/green_model_3.pth', 2)]\n                      },\n\n             'RGB': {'b5': [('../input/single-cell-models/fold0_b5_rgb_balanced_2.pth', 1),\n                           ('../input/single-cell-models/fold4_traindataset_b5_size128_bs128_3.pth', 2)]\n                     }\n             }\n\nsample_stats = ([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])\nitem_tfms = RandomResizedCrop(224, min_scale=0.75, ratio=(1.,1.))\nbatch_tfms = [*aug_transforms(flip_vert=True, size=128, max_warp=0), Normalize.from_stats(*sample_stats)]\nbs = Config.cell_level_bs\n\ndef get_y(r): \n    return r['image_labels'].split('|')","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%%time\nif len(cell_df) == 0:\n    preds = []\nelse:\n    ttas = []\n    sum_weights = 0\n\n    for color, v1 in model_dict.items():\n\n        assert color in ['GREEN', 'RGB']\n\n        if color=='GREEN':\n            def get_x(r): \n                return cv2.imread(r['path'])[:,:,1]\n        else:\n            def get_x(r): \n                return r['path']\n\n        dblock = DataBlock(blocks=(ImageBlock, MultiCategoryBlock(vocab=[str(i) for i in range(19)])),        \n                get_x=get_x,\n                get_y=get_y,\n                item_tfms=item_tfms,\n                batch_tfms=batch_tfms\n                )\n\n        dls = dblock.dataloaders(cell_df, bs=bs)\n\n        test_dl = dls.test_dl(cell_df)\n\n        for model_name, v3 in v1.items():\n\n            learn = get_learner(model_name)\n\n            for model_path, weight in v3:\n\n                save_name = os.path.split(model_path)[-1].split('.')[0]\n                print(f'{save_name}\\n')\n\n                learn.model.load_state_dict(load_learner(model_path, cpu=False))\n                tta, _ = learn.tta(dl=test_dl)\n\n                if Config.save_preds:\n                    with open(f'{save_name}.pickle', 'wb') as handle:\n                        pickle.dump(tta, handle)\n\n                ttas.append(tta * weight)\n                sum_weights += weight\n\n            del learn\n\n        del dblock\n        del dls\n        del test_dl\n        torch.cuda.empty_cache()\n\n    preds = torch.sum(torch.stack(ttas, axis=0), axis=0) / sum_weights\n    preds[:,-1] = torch.prod(1 - preds[:,:-1], axis=1)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"if type(preds) != torch.Tensor:\n    preds = torch.Tensor(preds)\n\ncell_df['cls'] = ''\nthreshold = 0.0\n\nfor i in range(preds.shape[0]):\n    p = torch.nonzero(preds[i] > threshold).squeeze().numpy().tolist()\n    if type(p) != list: \n        p = [p]\n\n    if len(p) == 0: \n        cls = [(preds[i].argmax().item(), preds[i].max().item())]\n    else:\n        cls = [(x, preds[i][x].item()) for x in p]\n    cell_df['cls'].loc[i] = cls","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def combine(r):\n    cls = r[0]\n    enc = r[1]\n    classes = [str(c[0]) + ' ' + str(c[1]) + ' ' + enc for c in cls]\n    return ' '.join(classes)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"if len(cell_df) == 0:\n    cell_df['pred'] = ''\nelse:\n    cell_df['pred'] = cell_df[['cls', 'enc']].apply(combine, axis=1)\ncell_df.tail()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"subm = cell_df.groupby(['image_id'])['pred'].apply(lambda x: ' '.join(x)).reset_index()\nsubm.head()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sample_submission = Config.sub_df.copy()\nsample_submission = sample_submission.drop(sample_submission.columns[-1:], axis=1)\n\nss_df = pd.merge(\n    sample_submission,\n    subm,\n    how=\"left\",\n    left_on='ID',\n    right_on='image_id',\n)\nss_df['PredictionString'] = ss_df['pred']\nss_df = ss_df[['ID', 'ImageWidth', 'ImageHeight', 'PredictionString']]\nss_df.tail()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 3. Image Level Prediction","metadata":{}},{"cell_type":"code","source":"print('before empty cache')\nprint(gpu_usage())\ntorch.cuda.empty_cache()\nprint('\\nafter empty cache')\nprint(gpu_usage())\ngc.collect()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\"\"\"\nCode inherited from: https://www.kaggle.com/cdeotte/rotation-augmentation-gpu-tpu-0-96\n\"\"\"\n\ndef get_mat(rotation, shear, height_zoom, width_zoom, height_shift, width_shift):\n    # returns 3x3 transformmatrix which transforms indicies\n\n    # CONVERT DEGREES TO RADIANS\n    rotation = math.pi * rotation / 180.\n    shear = math.pi * shear / 180.\n\n    # ROTATION MATRIX\n    c1 = tf.math.cos(rotation)\n    s1 = tf.math.sin(rotation)\n    one = tf.constant([1],dtype='float32')\n    zero = tf.constant([0],dtype='float32')\n    rotation_matrix = tf.reshape(tf.concat([c1,s1,zero, -s1,c1,zero, zero,zero,one],axis=0), [3,3])\n\n    # SHEAR MATRIX\n    c2 = tf.math.cos(shear)\n    s2 = tf.math.sin(shear)\n    shear_matrix = tf.reshape(tf.concat([one,s2,zero, zero,c2,zero, zero,zero,one],axis=0), [3,3])\n\n    # ZOOM MATRIX\n    zoom_matrix = tf.reshape(tf.concat([one/height_zoom,zero,zero, zero,one/width_zoom,zero, zero,zero,one],axis=0), [3,3])\n\n    # SHIFT MATRIX\n    shift_matrix = tf.reshape( tf.concat([one,zero,height_shift, zero,one,width_shift, zero,zero,one],axis=0), [3,3])\n\n    return K.dot(K.dot(rotation_matrix, shear_matrix), K.dot(zoom_matrix, shift_matrix))","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def auto_select_accelerator():\n    try:\n        tpu = tf.distribute.cluster_resolver.TPUClusterResolver()\n        tf.config.experimental_connect_to_cluster(tpu)\n        tf.tpu.experimental.initialize_tpu_system(tpu)\n        strategy = tf.distribute.experimental.TPUStrategy(tpu)\n        print(\"Running on TPU:\", tpu.master())\n    except ValueError:\n        strategy = tf.distribute.get_strategy()\n    print(f\"Running on {strategy.num_replicas_in_sync} replicas\")\n    \n    return strategy\n\n\ndef build_decoder(color, with_labels=True, target_size=(256, 256), res16=False, ext='png'):\n    assert color in ['GREEN', 'RGB']\n\n    if color=='RGB':\n      \n        def decode(img_id):\n          \n            paths = [img_id + f'_{colour}.' + ext for colour in ['red', 'green', 'blue']]\n          \n            file_bytes_all = [tf.io.read_file(path) for path in paths]\n\n            if ext == 'png':\n                if res16:\n                    img = tf.concat([tf.image.decode_png(file_bytes, channels=1, dtype=tf.dtypes.uint16) for \\\n                              file_bytes in file_bytes_all], axis=-1)\n                else:\n                    img = tf.concat([tf.image.decode_png(file_bytes, channels=1) for \\\n                              file_bytes in file_bytes_all], axis=-1)\n\n            elif ext in ['jpg', 'jpeg']:\n                img = tf.concat([tf.image.decode_jpeg(file_bytes, channels=1) for \\\n                              file_bytes in file_bytes_all], axis=-1)\n            else:\n                raise ValueError(\"Image extension not supported\")\n\n            if ext == 'png' and res16:\n                img = tf.cast(img, tf.float32) / float(2**16 - 1)\n            else:\n                img = tf.cast(img, tf.float32) / 255.0\n\n            img = tf.image.resize(img, target_size)\n\n            mean = tf.convert_to_tensor([0.485, 0.456, 0.406])\n            std = tf.convert_to_tensor([0.229, 0.224, 0.225])\n\n            img = (img-mean)/std\n\n            return img\n\n        def decode_with_labels(path, label):\n            return decode(path), label\n\n        return decode_with_labels if with_labels else decode\n\n    else:\n        def decode(path):\n            file_bytes = tf.io.read_file(path)\n\n            if ext == 'png':\n                if res16:\n                    img = tf.image.decode_png(file_bytes, channels=3, dtype=tf.dtypes.uint16)\n                else:\n                    img = tf.image.decode_png(file_bytes, channels=3)\n            elif ext in ['jpg', 'jpeg']:\n                img = tf.image.decode_jpeg(file_bytes, channels=3)\n            else:\n                raise ValueError(\"Image extension not supported\")\n\n            if ext == 'png' and res16:\n                img = tf.cast(img, tf.float32) / float(2**16 - 1)\n            else:\n                img = tf.cast(img, tf.float32) / 255.0\n            img = tf.image.resize(img, target_size)\n\n            return img\n\n        def decode_with_labels(path, label):\n            return decode(path), label\n      \n        return decode_with_labels if with_labels else decode\n\ndef build_augmenter(dim=600, extra_aug=True, with_labels=True):\n\n    def transform(image):\n        \"\"\"\n        Code inherited from: https://www.kaggle.com/cdeotte/rotation-augmentation-gpu-tpu-0-96\n        \"\"\"\n        # input image - is one image of size [dim,dim,3] not a batch of [b,dim,dim,3]\n        # output - image randomly rotated, sheared, zoomed, and shifted\n        DIM = dim\n        XDIM = DIM%2 #fix for size 331\n\n        rot = 90. * tf.random.normal([1], dtype='float32')\n        shr = 5. * tf.random.normal([1], dtype='float32') \n        h_zoom = 1.0 + tf.random.normal([1], dtype='float32')/10.\n        w_zoom = 1.0 + tf.random.normal([1], dtype='float32')/10.\n        h_shift = 0.05 * DIM * tf.random.normal([1], dtype='float32') \n        w_shift = 0.05 * DIM * tf.random.normal([1], dtype='float32')\n\n        # GET TRANSFORMATION MATRIX\n        m = get_mat(rot, shr, h_zoom, w_zoom, h_shift, w_shift) \n\n        # LIST DESTINATION PIXEL INDICES\n        x = tf.repeat(tf.range(DIM//2,-DIM//2,-1), DIM)\n        y = tf.tile(tf.range(-DIM//2,DIM//2), [DIM])\n        z = tf.ones([DIM*DIM], dtype='int32')\n        idx = tf.stack([x,y,z])\n\n        # ROTATE DESTINATION PIXELS ONTO ORIGIN PIXELS\n        idx2 = K.dot(m, tf.cast(idx, dtype='float32'))\n        idx2 = K.cast(idx2, dtype='int32')\n        idx2 = K.clip(idx2, -DIM//2+XDIM+1, DIM//2)\n\n        # FIND ORIGIN PIXEL VALUES           \n        idx3 = tf.stack([DIM//2-idx2[0,], DIM//2-1+idx2[1,]])\n        d = tf.gather_nd(image, tf.transpose(idx3))\n\n        return tf.reshape(d, [DIM, DIM, 3])\n\n    if extra_aug:\n        def augment(img):\n            img = tf.image.random_flip_left_right(img, seed=Config.seed)\n            img = tf.image.random_flip_up_down(img, seed=Config.seed)\n            img = tf.image.random_brightness(img, max_delta=0.1, seed=Config.seed)\n            img = transform(img)\n\n            return img\n    else:\n        def augment(img):\n            img = tf.image.random_flip_left_right(img, seed=Config.seed)\n            img = tf.image.random_flip_up_down(img, seed=Config.seed)\n            img = tf.image.random_brightness(img, max_delta=0.1, seed=Config.seed)\n            \n            return img\n\n    def augment_with_labels(img, label):\n        return augment(img), label\n\n    return augment_with_labels if with_labels else augment\n\ndef build_dataset(paths, labels=None, bsize=128, cache=True,\n                  decode_fn=None, augment_fn=None,\n                  augment=True, repeat=True, \n                  shuffle=1024, cache_dir=\"\"):\n    if cache_dir != \"\" and cache is True:\n        os.makedirs(cache_dir, exist_ok=True)\n\n    if decode_fn is None:\n        decode_fn = build_decoder(labels is not None)\n\n    if augment_fn is None:\n        augment_fn = build_augmenter(labels is not None)  \n\n    AUTO = tf.data.experimental.AUTOTUNE\n    slices = paths if labels is None else (paths, labels)\n\n    dset = tf.data.Dataset.from_tensor_slices(slices)\n    dset = dset.map(decode_fn, num_parallel_calls=AUTO)\n    dset = dset.cache(cache_dir) if cache else dset\n    dset = dset.map(augment_fn, num_parallel_calls=AUTO) if augment else dset\n    dset = dset.repeat() if repeat else dset\n    dset = dset.shuffle(shuffle) if shuffle else dset\n    dset = dset.batch(bsize).prefetch(AUTO)\n\n    return dset","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"strategy = auto_select_accelerator()\nBATCH_SIZE = Config.image_level_bs\nCOMPETITION_NAME = '../input/hpa-single-cell-image-classification'\nsub_df = Config.sub_df.copy()\nsub_df = sub_df.drop(sub_df.columns[1:], axis=1)\nlabel_cols = [str(i) for i in range(19)]\nfor i in label_cols:\n    sub_df[i] = pd.Series(np.zeros(sub_df.shape[0]))","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model_dict = {'GREEN':\n              {True: {True: {600: [#('../input/image-level-models/image_level_models/green/b0/res8/fold0_b0_GREEN_bs256_40epochs_unnormalized_augmented.h5', 1),\n                                     #('../input/image-level-models/image_level_models/green/b0/res8/fold1_b0_GREEN_bs256_40epochs_unnormalized_augmented.h5', ),\n                                     ('../input/image-level-models/image_level_models/green/b0/res8/fold2_b0_GREEN_bs256_50epochs_unnormalized_augmented.h5', 2),\n                                     #('../input/image-level-models/image_level_models/green/b0/res8/fold3_b0_GREEN_bs256_50epochs_unnormalized_augmented.h5', ),\n\n                                     ('../input/image-level-models/image_level_models/green/b1/fold0_b1_GREEN_bs256_unnormalized_augmented.h5', 2), # augment?\n                                     #('../input/image-level-models/image_level_models/green/b1/fold1_b1_GREEN_bs256_50epochs_unnormalized_augmented.h5', ),\n                                     #('../input/image-level-models/image_level_models/green/b1/fold4_b1_GREEN_bs256_50epochs_unnormalized_augmented.h5', ),\n\n                                     #('../input/image-level-models/image_level_models/green/b2/fold1_b2_GREEN_bs256_50epochs_unnormalized_augmented.h5', ),\n\n                                     #('../input/image-level-models/image_level_models/green/b3/40e/fold0_b3_GREEN_bs256_40epochs_unnormalized_augmented.h5', ),\n                                     #('../input/image-level-models/image_level_models/green/b3/40e/fold1_b3_GREEN_bs256_40epochs_unnormalized_augmented.h5', ),\n                                     #('../input/image-level-models/image_level_models/green/b3/50e/fold2_b3_GREEN_bs256_50epochs_unnormalized_augmented.h5', ),\n                                     ('../input/image-level-models/image_level_models/green/b3/50e/fold3_b3_GREEN_bs256_50epochs_unnormalized_augmented.h5', 1.5),\n                                     #('../input/image-level-models/image_level_models/green/b3/50e/fold4_b3_GREEN_bs256_50epochs_unnormalized_augmented.h5', ),\n\n                                    #('../input/image-level-models/image_level_models/green/resnet/fold0_resnet_GREEN_bs256_50epochs_unnormalized_augmented.h5'),\n                                    ('../input/image-level-models/image_level_models/green/resnet/fold1_resnet_GREEN_bs256_50epochs_unnormalized_augmented.h5', 1.5),\n                                    ],\n\n                               700: [('../input/image-level-models/image_level_models/green/densenet/fold2_densenet_GREEN_bs256_40epochs_size700_unnormalized_augmented.h5', 1.5)]\n                      },\n                       \n                       False: {600: [\n                                   ('../input/image-level-models/image_level_models/green/b2/fold0_b2_green_bs256_unnormalized.h5', 2),\n\n                                   ('../input/image-level-models/image_level_models/green/b5/fold0_b5_green_public_unnormalized_bs16.h5', 2),\n\n                                    #('../input/image-level-models/image_level_models/green/b7/model_green_fold0_b7.h5', ),\n                                    #('../input/image-level-models/image_level_models/green/b7/model_green_fold1_b7.h5', ),\n                                    #('../input/image-level-models/image_level_models/green/b7/model_green_fold2_b7.h5', ),\n                                    #('../input/image-level-models/image_level_models/green/b7/model_green_fold3_b7.h5', ),\n                                    ('../input/image-level-models/image_level_models/green/b7/model_green_fold4_b7.h5', 2)\n                       ]\n                       }},\n\n              False: {True: {720: [('../input/image-level-models/image_level_models/green/b0/res16/fold2_b0_GREEN_bs256_50epochs_size720_unnormalized_augmented_res16.h5', 4)],\n                            },\n                     False: {}}},\n\n             'RGB':\n              {False: {False: {}, \n                       True: {}},\n\n              True: {True: {700: [('../input/image-level-models/image_level_models/rgb/res16/fold3_b0_RGB_bs256_50epochs_size700_unnormalized_augmented_res16.h5', 4)]}, \n                     False: {}}}}","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%%time\n\nttas = []\n\nif len(sub_df) > 0:\n\n    sum_weights = 0\n    for color, v1 in model_dict.items():\n        test_paths = COMPETITION_NAME + \"/test/\" + sub_df['ID']\n        if color=='GREEN':\n            test_paths += '_green.png'\n\n        for res16, v2 in v1.items():\n\n            for extra_aug, v3 in v2.items():\n\n                for size, v4 in v3.items():\n\n                    test_decoder = build_decoder(color=color, with_labels=False, target_size=(size, size), res16=res16)\n                    test_augmenter = build_augmenter(dim=size, extra_aug=extra_aug, with_labels=False)\n\n                    dtest_no_tta = build_dataset(\n                            test_paths, bsize=BATCH_SIZE, repeat=False,\n                            shuffle=False, augment=False, cache=False,\n                            decode_fn=test_decoder)\n\n                    dtest_tta = build_dataset(\n                                test_paths, bsize=BATCH_SIZE, repeat=False,\n                                shuffle=False, augment=True, cache=False,\n                                decode_fn=test_decoder, augment_fn=test_augmenter)\n\n                    for model_path, weight in v4:\n\n                        print(f'color = {color}')\n                        print(f'16bit = {res16}')\n                        print(f'extra_aug = {extra_aug}')\n                        print(f'image_size = {size}\\n')\n\n                        model_name = os.path.split(model_path)[-1].split('.')[0]\n\n                        print(model_name)\n\n                        with strategy.scope():\n                            model = tf.keras.models.load_model(model_path)\n\n                        tta = [model.predict(dtest_no_tta, verbose=1)]\n\n                        num_steps = 4\n\n                        for step in range(num_steps):\n                            tta.append(model.predict(dtest_tta, verbose=1))\n\n                        num_steps += 1\n\n                        sum_weights += weight\n\n                        tta = np.mean(np.stack(tta, axis=0), axis=0)\n\n                        if Config.save_preds:\n                            np.save(model_name, tta, allow_pickle=True)\n\n                        ttas.append(tta * weight)\n\n                        print('\\n')\n\n    ttas = np.sum(np.stack(ttas, axis=0), axis=0) / sum_weights","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 4. Ensemble & Final Prediction","metadata":{}},{"cell_type":"code","source":"sub_df[label_cols] = ttas\n\nss_df = pd.merge(ss_df, sub_df, on='ID', how ='left')\n\nfor i in range(ss_df.shape[0]):\n    a = ss_df.loc[i,'PredictionString']\n    b = a.split()\n    for j in range(int(len(b)/3)):\n        for k in range(19):\n            if int(b[0 + 3 * j]) == k:\n\n                w = 0.5\n                c = b[1 + 3 * j]\n                b[1 + 3 * j] = str(0.5*((ss_df.loc[i,f'{k}'] * w + float(c) * (1 - w)) + (ss_df.loc[i,f'{k}']**w) * (float(c))**(1 - w)))\n\n    ss_df.loc[i,'PredictionString'] = ' '.join(b)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"if Config.hidden_only:\n    ss_df = pd.concat([Config.showed_df, ss_df], ignore_index=True)\n\nss_df = ss_df[['ID','ImageWidth','ImageHeight','PredictionString']]\nss_df.to_csv('submission.csv', index=False)\nss_df.tail()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!ls","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for tree in (single_cells_save_dir, cell_mask_dir, nucl_mask_dir):\n    shutil.rmtree(tree)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!ls","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}