{"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":"# Baselines\n\n|                         |                                           Kaggle Train                                          |                                                Local Train                                               |                                           Kaggle Submission                                          |\n|:-----------------------:|:-----------------------------------------------------------------------------------------------:|:--------------------------------------------------------------------------------------------------------:|:----------------------------------------------------------------------------------------------------:|\n|  Efficient_Net_Unet_256 |    [url](https://www.kaggle.com/code/yuliknormanowen/hubmap-hap-efficientnet-unet-256-train)    |      [url](https://www.kaggle.com/datasets/yuliknormanowen/ucode-hubmap-efficientnet-train-local-v2)     |    [url](https://www.kaggle.com/code/yuliknormanowen/hubmap-hap-efficientnet-unet-256-submission)    |\n|  Efficient_Net_Unet_768 |    [url]( https://www.kaggle.com/code/yuliknormanowen/hubmap-hap-efficientnet-unet-768-train)   |     [url](https://www.kaggle.com/datasets/yuliknormanowen/ucode-hubmap-efficientnet-768-train-local)     |    [url](https://www.kaggle.com/code/yuliknormanowen/hubmap-hap-efficientnet-unet-768-submission)    |\n| Swin_Transformer_v1_768 | [url](https://www.kaggle.com/code/yuliknormanowen/hubmap-hap-swintransformer-v1-unet-768-train) | [url](https://www.kaggle.com/datasets/yuliknormanowen/hubmaphap-swintransformer-v1-unet-256-train-local) | [url](https://www.kaggle.com/code/yuliknormanowen/hubmap-hap-swintransformer-v1-unet-768-submission) |\n| Swin_Transformer_v2_256 | [url](https://www.kaggle.com/code/yuliknormanowen/hubmap-hap-swintransformer-v2-unet-256-train) | [url](https://www.kaggle.com/datasets/yuliknormanowen/ucode-hubmap-swintransformer-768-train-local)      | [url](https://www.kaggle.com/code/yuliknormanowen/hubmap-hap-swintransformer-v2-unet-256-submission) |","metadata":{}},{"cell_type":"code","source":"import glob\n\nimport cv2\nimport torch\nfrom fastai.layers import PixelShuffle_ICNR, ConvLayer, SelfAttention\nfrom fastai.torch_core import Module\nfrom torch import Tensor\nfrom torch.autograd import Variable\nimport torch.nn.functional as F\nimport numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nfrom PIL import Image\nimport tifffile as tiff\nimport cv2\nimport os\nimport gc\nfrom tqdm.notebook import tqdm\nimport rasterio\nfrom rasterio.windows import Window\nimport torch.nn as nn\nfrom torch.utils.data import Dataset, DataLoader\nimport glob\nimport warnings\n\nwarnings.filterwarnings(\"ignore\")\ntry:\n    from itertools import ifilterfalse\nexcept ImportError:\n    from itertools import filterfalse\nimport sys\n\nsys.path.insert(0, '../input/my-efficientnet-pytorch/EfficientNet-PyTorch/EfficientNet-PyTorch/EfficientNet-PyTorch-master')\n\nfrom efficientnet_pytorch import EfficientNet\nfrom efficientnet_pytorch.utils import get_model_params","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import fastai\nprint(torch.__version__)\nprint(fastai.__version__)","metadata":{"execution":{"iopub.status.busy":"2022-08-09T03:04:44.905329Z","iopub.execute_input":"2022-08-09T03:04:44.906001Z","iopub.status.idle":"2022-08-09T03:04:44.914491Z","shell.execute_reply.started":"2022-08-09T03:04:44.905958Z","shell.execute_reply":"2022-08-09T03:04:44.912708Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"bs = 1\nsz = 256  # the size of tiles\nreduce = 4  # reduce the original images by 4 times\nDATA = '../input/hubmap-organ-segmentation/test_images'\nmodel_encoder = 'efficientnet-b7'\nMODELS = glob.glob(f\"../input/hubmaphpa-weight/*.pth\")\ndf_sample = pd.read_csv('../input/hubmap-organ-segmentation/test.csv')\ndevice = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')\nEnsemble_Weight = True\npre_th = 0.07 # None for self-defined\n\nif len(df_sample) == 1:\n    DEBUG = True\nelse:\n    DEBUG = False","metadata":{"execution":{"iopub.status.busy":"2022-08-09T03:04:44.916649Z","iopub.execute_input":"2022-08-09T03:04:44.918135Z","iopub.status.idle":"2022-08-09T03:04:45.010156Z","shell.execute_reply.started":"2022-08-09T03:04:44.918067Z","shell.execute_reply":"2022-08-09T03:04:45.008862Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# functions to convert encoding to mask and mask to encoding\ndef enc2mask(encs, shape):\n    img = np.zeros(shape[0]*shape[1], dtype=np.uint8)\n    for m,enc in enumerate(encs):\n        if isinstance(enc,np.float) and np.isnan(enc): continue\n        s = enc.split()\n        for i in range(len(s)//2):\n            start = int(s[2*i]) - 1\n            length = int(s[2*i+1])\n            img[start:start+length] = 1 + m\n    return img.reshape(shape).T\n\ndef mask2enc(mask, n=1):\n    pixels = mask.T.flatten()\n    encs = []\n    for i in range(1,n+1):\n        p = (pixels == i).astype(np.int8)\n        if p.sum() == 0: encs.append(np.nan)\n        else:\n            p = np.concatenate([[0], p, [0]])\n            runs = np.where(p[1:] != p[:-1])[0] + 1\n            runs[1::2] -= runs[::2]\n            encs.append(' '.join(str(x) for x in runs))\n    return encs\n\n#https://www.kaggle.com/bguberfain/memory-aware-rle-encoding\n#with transposed mask\ndef rle_encode_less_memory(img):\n    #the image should be transposed\n    pixels = img.T.flatten()\n    \n    # This simplified method requires first and last pixel to be zero\n    pixels[0] = 0\n    pixels[-1] = 0\n    runs = np.where(pixels[1:] != pixels[:-1])[0] + 2\n    runs[1::2] -= runs[::2]\n    \n    return ' '.join(str(x) for x in runs)","metadata":{"execution":{"iopub.status.busy":"2022-08-09T03:04:45.012797Z","iopub.execute_input":"2022-08-09T03:04:45.013189Z","iopub.status.idle":"2022-08-09T03:04:45.029502Z","shell.execute_reply.started":"2022-08-09T03:04:45.013149Z","shell.execute_reply":"2022-08-09T03:04:45.028203Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def img2tensor(img, dtype: np.dtype = np.float32):\n    if img.ndim == 2: img = np.expand_dims(img, 2)\n    img = np.transpose(img, (2, 0, 1))\n    return torch.from_numpy(img.astype(dtype, copy=False))\n\n\nclass HuBMAPDataset(Dataset):\n    def __init__(self, idx, sz=sz, reduce=reduce):\n        self.data = rasterio.open(os.path.join(DATA, idx + '.tiff'), transform=identity,\n                                  num_threads='all_cpus')\n        # some images have issues with their format\n        # and must be saved correctly before reading with rasterio\n        if self.data.count != 3:\n            subdatasets = self.data.subdatasets\n            self.layers = []\n            if len(subdatasets) > 0:\n                for i, subdataset in enumerate(subdatasets, 0):\n                    self.layers.append(rasterio.open(subdataset))\n        self.shape = self.data.shape\n        self.reduce = reduce\n        self.sz = reduce * sz\n        self.pad0 = (self.sz - self.shape[0] % self.sz) % self.sz\n        self.pad1 = (self.sz - self.shape[1] % self.sz) % self.sz\n        self.n0max = (self.shape[0] + self.pad0) // self.sz\n        self.n1max = (self.shape[1] + self.pad1) // self.sz\n\n    def __len__(self):\n        return self.n0max * self.n1max\n\n    def __getitem__(self, idx):\n        # the code below may be a little bit difficult to understand,\n        # but the thing it does is mapping the original image to\n        # tiles created with adding padding, as done in\n        # https://www.kaggle.com/iafoss/256x256-images ,\n        # and then the tiles are loaded with rasterio\n        # n0,n1 - are the x and y index of the tile (idx = n0*self.n1max + n1)\n        n0, n1 = idx // self.n1max, idx % self.n1max\n        # x0,y0 - are the coordinates of the lower left corner of the tile in the image\n        # negative numbers correspond to padding (which must not be loaded)\n        x0, y0 = -self.pad0 // 2 + n0 * self.sz, -self.pad1 // 2 + n1 * self.sz\n        # make sure that the region to read is within the image\n        p00, p01 = max(0, x0), min(x0 + self.sz, self.shape[0])\n        p10, p11 = max(0, y0), min(y0 + self.sz, self.shape[1])\n        img = np.zeros((self.sz, self.sz, 3), np.uint8)\n        # mapping the loade region to the tile\n        if self.data.count == 3:\n            img[(p00 - x0):(p01 - x0), (p10 - y0):(p11 - y0)] = np.moveaxis(self.data.read([1, 2, 3],\n                                                                                           window=Window.from_slices(\n                                                                                               (p00, p01), (p10, p11))),\n                                                                            0, -1)\n        else:\n            for i, layer in enumerate(self.layers):\n                img[(p00 - x0):(p01 - x0), (p10 - y0):(p11 - y0), i] = \\\n                    layer.read(1, window=Window.from_slices((p00, p01), (p10, p11)))\n\n        if self.reduce != 1:\n            img = cv2.resize(img, (self.sz // reduce, self.sz // reduce),\n                             interpolation=cv2.INTER_AREA)\n        # check for empty imges\n        hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)\n        h, s, v = cv2.split(hsv)\n        if (s > s_th).sum() <= p_th or img.sum() <= p_th:\n            # images with -1 will be skipped\n            return img2tensor(img / 255.0), -1\n        else:\n            return img2tensor(img / 255.0), idx\n","metadata":{"execution":{"iopub.status.busy":"2022-08-09T03:04:45.031092Z","iopub.execute_input":"2022-08-09T03:04:45.031855Z","iopub.status.idle":"2022-08-09T03:04:45.056504Z","shell.execute_reply.started":"2022-08-09T03:04:45.031821Z","shell.execute_reply":"2022-08-09T03:04:45.055006Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class Model_pred:\n    def __init__(self, models, dl, all_score, tta: bool = True, half: bool = False):\n        self.models = models\n        self.dl = dl\n        self.tta = tta\n        self.half = half\n        self.all_score = all_score\n\n    def __iter__(self):\n        count = 0\n        with torch.no_grad():\n            for x, y in iter(self.dl):\n                if DEBUG:\n                    print(\"\\n Original:\")\n                    show_image = x.squeeze(0)\n                    show_image = show_image.permute(1,2,0)\n                    show_image = show_image.cpu().detach().numpy()\n                    plt.imshow(show_image)\n                    plt.show()\n\n                if ((y >= 0).sum() > 0):  # exclude empty images\n                    x = x[y >= 0].to(device)\n                    y = y[y >= 0]\n                    if self.half: x = x.half()\n                    py = None\n                    for model, score in self.models:\n                        p = model(x)\n                        p = torch.sigmoid(p).detach() * score / self.all_score\n                        if py is None:\n                            py = p\n                        else:\n                            py += p\n                    if self.tta:\n                        # x,y,xy flips as TTA\n                        flips = [[-1], [-2], [-2, -1]]\n                        for f in flips:\n                            xf = torch.flip(x, f)\n                            for model, score in self.models:\n                                p = model(xf)\n                                p = torch.flip(p, f)\n                                py += torch.sigmoid(p).detach() * score / self.all_score\n                        py /= (1 + len(flips))\n\n                    py = F.upsample(py, scale_factor=reduce, mode=\"bilinear\")\n                    py = py.permute(0, 2, 3, 1).float().cpu()\n\n                    batch_size = len(py)\n                    for i in range(batch_size):\n                        yield py[i], y[i]\n                        count += 1\n\n    def __len__(self):\n        return len(self.dl.dataset)","metadata":{"execution":{"iopub.status.busy":"2022-08-09T03:04:45.058316Z","iopub.execute_input":"2022-08-09T03:04:45.059548Z","iopub.status.idle":"2022-08-09T03:04:45.082824Z","shell.execute_reply.started":"2022-08-09T03:04:45.059484Z","shell.execute_reply":"2022-08-09T03:04:45.081389Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class FPN(nn.Module):\n    def __init__(self, input_channels: list, output_channels: list):\n        super().__init__()\n        self.convs = nn.ModuleList(\n            [nn.Sequential(nn.Conv2d(in_ch, out_ch * 2, kernel_size=3, padding=1),\n                           nn.ReLU(inplace=True), nn.BatchNorm2d(out_ch * 2),\n                           nn.Conv2d(out_ch * 2, out_ch, kernel_size=3, padding=1))\n             for in_ch, out_ch in zip(input_channels, output_channels)])\n\n    def forward(self, xs: list, last_layer):\n        hcs = [F.interpolate(c(x), scale_factor=2 ** (len(self.convs) - i), mode='bilinear')\n               for i, (c, x) in enumerate(zip(self.convs, xs))]\n        hcs.append(last_layer)\n        return torch.cat(hcs, dim=1)\n\n\nclass UnetBlock(Module):\n    def __init__(self, up_in_c: int, x_in_c: int, nf: int = None, blur: bool = False,\n                 self_attention: bool = False, **kwargs):\n        super().__init__()\n        self.shuf = PixelShuffle_ICNR(up_in_c, up_in_c // 2, blur=blur, **kwargs)\n        self.bn = nn.BatchNorm2d(x_in_c)\n        ni = up_in_c // 2 + x_in_c\n        nf = nf if nf is not None else max(up_in_c // 2, 32)\n        self.conv1 = ConvLayer(ni, nf, norm_type=None, **kwargs)\n        self.conv2 = ConvLayer(nf, nf, norm_type=None,\n                               xtra=SelfAttention(nf) if self_attention else None, **kwargs)\n        self.relu = nn.ReLU(inplace=True)\n\n    def forward(self, up_in: Tensor, left_in: Tensor) -> Tensor:\n        s = left_in\n        up_out = self.shuf(up_in)\n        cat_x = self.relu(torch.cat([up_out, self.bn(s)], dim=1))\n        return self.conv2(self.conv1(cat_x))\n\n\nclass _ASPPModule(nn.Module):\n    def __init__(self, inplanes, planes, kernel_size, padding, dilation, groups=1):\n        super().__init__()\n        self.atrous_conv = nn.Conv2d(inplanes, planes, kernel_size=kernel_size,\n                                     stride=1, padding=padding, dilation=dilation, bias=False, groups=groups)\n        self.bn = nn.BatchNorm2d(planes)\n        self.relu = nn.ReLU()\n\n        self._init_weight()\n\n    def forward(self, x):\n        x = self.atrous_conv(x)\n        x = self.bn(x)\n\n        return self.relu(x)\n\n    def _init_weight(self):\n        for m in self.modules():\n            if isinstance(m, nn.Conv2d):\n                torch.nn.init.kaiming_normal_(m.weight)\n            elif isinstance(m, nn.BatchNorm2d):\n                m.weight.data.fill_(1)\n                m.bias.data.zero_()\n\n\nclass ASPP(nn.Module):\n    def __init__(self, inplanes=512, mid_c=256, dilations=[6, 12, 18, 24], out_c=None):\n        super().__init__()\n        self.aspps = [_ASPPModule(inplanes, mid_c, 1, padding=0, dilation=1)] + \\\n                     [_ASPPModule(inplanes, mid_c, 3, padding=d, dilation=d, groups=4) for d in dilations]\n        self.aspps = nn.ModuleList(self.aspps)\n        self.global_pool = nn.Sequential(nn.AdaptiveMaxPool2d((1, 1)),\n                                         nn.Conv2d(inplanes, mid_c, 1, stride=1, bias=False),\n                                         nn.BatchNorm2d(mid_c), nn.ReLU())\n        out_c = out_c if out_c is not None else mid_c\n        self.out_conv = nn.Sequential(nn.Conv2d(mid_c * (2 + len(dilations)), out_c, 1, bias=False),\n                                      nn.BatchNorm2d(out_c), nn.ReLU(inplace=True))\n        self.conv1 = nn.Conv2d(mid_c * (2 + len(dilations)), out_c, 1, bias=False)\n        self._init_weight()\n\n    def forward(self, x):\n        x0 = self.global_pool(x)\n        xs = [aspp(x) for aspp in self.aspps]\n        x0 = F.interpolate(x0, size=xs[0].size()[2:], mode='bilinear', align_corners=True)\n        x = torch.cat([x0] + xs, dim=1)\n        return self.out_conv(x)\n\n    def _init_weight(self):\n        for m in self.modules():\n            if isinstance(m, nn.Conv2d):\n                torch.nn.init.kaiming_normal_(m.weight)\n            elif isinstance(m, nn.BatchNorm2d):\n                m.weight.data.fill_(1)\n                m.bias.data.zero_()","metadata":{"execution":{"iopub.status.busy":"2022-08-09T03:04:45.087296Z","iopub.execute_input":"2022-08-09T03:04:45.087706Z","iopub.status.idle":"2022-08-09T03:04:45.123443Z","shell.execute_reply.started":"2022-08-09T03:04:45.087653Z","shell.execute_reply":"2022-08-09T03:04:45.121521Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"s_th = 40  # saturation blancking threshold\np_th = 1000 * (sz // 256) ** 2  # threshold for the minimum number of pixels\nidentity = rasterio.Affine(1, 0, 0, 0, 1, 0)\npretrained_root = '../input/my-efficientnet-pytorch/'\nefficient_net_encoders = {\n    \"efficientnet-b0\": {\n        \"out_channels\": (3, 32, 24, 40, 112, 320),\n        \"stage_idxs\": (3, 5, 9, 16),\n        \"weight_path\": pretrained_root + \"efficientnet-b0-08094119.pth\"\n    },\n    \"efficientnet-b1\": {\n        \"out_channels\": (3, 32, 24, 40, 112, 320),\n        \"stage_idxs\": (5, 8, 16, 23),\n        \"weight_path\": pretrained_root + \"efficientnet-b1-dbc7070a.pth\"\n    },\n    \"efficientnet-b2\": {\n        \"out_channels\": (3, 32, 24, 48, 120, 352),\n        \"stage_idxs\": (5, 8, 16, 23),\n        \"weight_path\": pretrained_root + \"efficientnet-b2-27687264.pth\"\n    },\n    \"efficientnet-b3\": {\n        \"out_channels\": (3, 40, 32, 48, 136, 384),\n        \"stage_idxs\": (5, 8, 18, 26),\n        \"weight_path\": pretrained_root + \"efficientnet-b3-c8376fa2.pth\"\n    },\n    \"efficientnet-b4\": {\n        \"out_channels\": (3, 48, 32, 56, 160, 448),\n        \"stage_idxs\": (6, 10, 22, 32),\n        \"weight_path\": pretrained_root + \"efficientnet-b4-e116e8b3.pth\"\n    },\n    \"efficientnet-b5\": {\n        \"out_channels\": (3, 48, 40, 64, 176, 512),\n        \"stage_idxs\": (8, 13, 27, 39),\n        \"weight_path\": pretrained_root + \"efficientnet-b5-586e6cc6.pth\"\n    },\n    \"efficientnet-b6\": {\n        \"out_channels\": (3, 56, 40, 72, 200, 576),\n        \"stage_idxs\": (9, 15, 31, 45),\n        \"weight_path\": pretrained_root + \"efficientnet-b6-c76e70fd.pth\"\n    },\n    \"efficientnet-b7\": {\n        \"out_channels\": (3, 64, 48, 80, 224, 640),\n        \"stage_idxs\": (11, 18, 38, 55),\n        \"weight_path\": pretrained_root + \"efficientnet-b7-dcc49843.pth\"\n    }\n}\n\n\nclass EfficientNetEncoder(EfficientNet):\n    def __init__(self, stage_idxs, out_channels, model_name, depth=5):\n\n        blocks_args, global_params = get_model_params(model_name, override_params=None, image_size = sz)\n        super().__init__(blocks_args, global_params)\n\n        cfg = efficient_net_encoders[model_name]\n\n        self._stage_idxs = stage_idxs\n        self._out_channels = out_channels\n        self._depth = depth\n        self._in_channels = 3\n\n        del self._fc\n        self.load_state_dict(torch.load(cfg['weight_path']))\n\n    def get_stages(self):\n        return [\n            nn.Identity(),\n            nn.Sequential(self._conv_stem, self._bn0, self._swish),\n            self._blocks[:self._stage_idxs[0]],\n            self._blocks[self._stage_idxs[0]:self._stage_idxs[1]],\n            self._blocks[self._stage_idxs[1]:self._stage_idxs[2]],\n            self._blocks[self._stage_idxs[2]:],\n        ]\n\n    def forward(self, x):\n        stages = self.get_stages()\n\n        block_number = 0.\n        drop_connect_rate = self._global_params.drop_connect_rate\n\n        features = []\n        for i in range(self._depth + 1):\n\n            # Identity and Sequential stages\n            if i < 2:\n                x = stages[i](x)\n\n            # Block stages need drop_connect rate\n            else:\n                for module in stages[i]:\n                    drop_connect = drop_connect_rate * block_number / len(self._blocks)\n                    block_number += 1.\n                    x = module(x, drop_connect)\n\n            features.append(x)\n\n        return features\n\n    def load_state_dict(self, state_dict, **kwargs):\n        state_dict.pop(\"_fc.bias\")\n        state_dict.pop(\"_fc.weight\")\n        super().load_state_dict(state_dict, **kwargs)\n\n\nclass EffUnet(nn.Module):\n    def __init__(self, model_name, stride=1):\n        super().__init__()\n\n        cfg = efficient_net_encoders[model_name]\n        stage_idxs = cfg['stage_idxs']\n        out_channels = cfg['out_channels']\n\n        self.encoder = EfficientNetEncoder(stage_idxs, out_channels, model_name)\n\n        # aspp with customized dilatations\n        self.aspp = ASPP(out_channels[-1], 256, out_c=384,\n                         dilations=[stride * 1, stride * 2, stride * 3, stride * 4])\n        self.drop_aspp = nn.Dropout2d(0.5)\n        # decoder\n        self.dec4 = UnetBlock(384, out_channels[-2], 256)\n        self.dec3 = UnetBlock(256, out_channels[-3], 128)\n        self.dec2 = UnetBlock(128, out_channels[-4], 64)\n        self.dec1 = UnetBlock(64, out_channels[-5], 32)\n        self.fpn = FPN([384, 256, 128, 64], [16] * 4)\n        self.drop = nn.Dropout2d(0.1)\n        self.final_conv = ConvLayer(32 + 16 * 4, 1, ks=1, norm_type=None, act_cls=None)\n\n    def forward(self, x):\n        enc0, enc1, enc2, enc3, enc4 = self.encoder(x)[-5:]\n        enc5 = self.aspp(enc4)\n        dec3 = self.dec4(self.drop_aspp(enc5), enc3)\n        dec2 = self.dec3(dec3, enc2)\n        dec1 = self.dec2(dec2, enc1)\n        dec0 = self.dec1(dec1, enc0)\n        x = self.fpn([enc5, dec3, dec2, dec1], dec0)\n        x = self.final_conv(self.drop(x))\n        x = F.interpolate(x, scale_factor=2, mode='bilinear')\n        return x","metadata":{"execution":{"iopub.status.busy":"2022-08-09T03:04:45.127958Z","iopub.execute_input":"2022-08-09T03:04:45.128535Z","iopub.status.idle":"2022-08-09T03:04:45.161824Z","shell.execute_reply.started":"2022-08-09T03:04:45.128501Z","shell.execute_reply":"2022-08-09T03:04:45.160621Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def extract_model_name(path):\n    file_name = path[path.rindex(\"/\") + 1:]  # like \"efficientnet-b5_fold_0_0.532.pth\"\n    model_name = file_name[: file_name.index(\"_\")]\n    return model_name\n\n\ndef extract_model_score(path):\n    file_name = path[path.rindex(\"/\") + 1:]\n    score = float(file_name[file_name.rindex(\"_\") + 1:file_name.rindex(\".\")])\n    return score\n\n\ndef extract_model_th(path):\n    file_name = path[path.rindex(\"/\") + 1:]\n    first_down = file_name.index(\"_\")\n    second_down = first_down + file_name[first_down + 1:].index(\"_\") + 1\n    th = float(file_name[first_down + 1: second_down])\n    return th","metadata":{"execution":{"iopub.status.busy":"2022-08-09T03:04:45.163569Z","iopub.execute_input":"2022-08-09T03:04:45.164553Z","iopub.status.idle":"2022-08-09T03:04:45.183117Z","shell.execute_reply.started":"2022-08-09T03:04:45.164516Z","shell.execute_reply":"2022-08-09T03:04:45.180816Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"split_layers = lambda m: [\n    list(m.encoder.parameters()),\n    list(m.aspp.parameters()) + list(m.dec4.parameters()) +\n    list(m.dec3.parameters()) + list(m.dec2.parameters()) +\n    list(m.dec1.parameters()) + list(m.fpn.parameters()) +\n    list(m.final_conv.parameters())\n]\n\nmodels = []\nths = []\nall_score = 0\nfor path in MODELS:\n    state_dict = torch.load(path, map_location=torch.device('cuda:0'))\n    model_name = extract_model_name(path)\n    if not pre_th:\n        th = extract_model_th(path)\n    else:\n        th = pre_th\n    if Ensemble_Weight:\n        score = extract_model_score(path)\n    else:\n        score = 1\n    all_score += score\n    model = EffUnet(model_name).cuda()\n    model.load_state_dict(state_dict)\n    model.float()\n    model.eval()\n    model.to(device)\n    models.append((model, score))\n    ths.append((th, score))\ndel state_dict","metadata":{"execution":{"iopub.status.busy":"2022-08-09T03:04:45.188312Z","iopub.execute_input":"2022-08-09T03:04:45.189441Z","iopub.status.idle":"2022-08-09T03:05:15.209470Z","shell.execute_reply.started":"2022-08-09T03:04:45.189403Z","shell.execute_reply":"2022-08-09T03:05:15.208355Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"TH = 0\nfor th_, score in ths:\n    TH += th_ * score / all_score\nprint(\"TH: \" + repr(TH))","metadata":{"execution":{"iopub.status.busy":"2022-08-09T03:05:15.211134Z","iopub.execute_input":"2022-08-09T03:05:15.211474Z","iopub.status.idle":"2022-08-09T03:05:15.219433Z","shell.execute_reply.started":"2022-08-09T03:05:15.211439Z","shell.execute_reply":"2022-08-09T03:05:15.218048Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Prediction","metadata":{}},{"cell_type":"code","source":"names, preds = [], []\nfor idx, row in tqdm(df_sample.iterrows(), total=len(df_sample)):\n    idx = str(row['id'])\n    ds = HuBMAPDataset(idx)\n    # rasterio cannot be used with multiple workers\n    dl = DataLoader(ds, bs, num_workers=0, shuffle=False, pin_memory=True)\n    mp = Model_pred(models, dl, all_score)\n    # generate masks\n    mask = torch.zeros(len(ds), ds.sz, ds.sz, dtype=torch.int8)\n    for p, i in iter(mp): mask[i.item()] = p.squeeze(-1) > TH\n\n    # reshape tiled masks into a single mask and crop padding\n    mask = mask.view(ds.n0max, ds.n1max, ds.sz, ds.sz). \\\n        permute(0, 2, 1, 3).reshape(ds.n0max * ds.sz, ds.n1max * ds.sz)\n    mask = mask[ds.pad0 // 2:-(ds.pad0 - ds.pad0 // 2) if ds.pad0 > 0 else ds.n0max * ds.sz,\n           ds.pad1 // 2:-(ds.pad1 - ds.pad1 // 2) if ds.pad1 > 0 else ds.n1max * ds.sz]\n    \n    if DEBUG:\n        print(\"\\nPredict:\")\n        plt.imsave(\"result.png\", mask * 255, cmap=plt.get_cmap('gray'))\n        plt.imshow(mask,cmap = 'gray')\n    \n    rle = rle_encode_less_memory(mask.numpy())\n    names.append(idx)\n    preds.append(rle)\n    del mask, ds, dl\n    gc.collect()","metadata":{"execution":{"iopub.status.busy":"2022-08-09T03:05:15.221082Z","iopub.execute_input":"2022-08-09T03:05:15.222424Z","iopub.status.idle":"2022-08-09T03:05:26.237005Z","shell.execute_reply.started":"2022-08-09T03:05:15.222362Z","shell.execute_reply":"2022-08-09T03:05:26.236108Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df = pd.DataFrame({'id':names,'rle':preds})\ndf.to_csv('submission.csv',index=False)","metadata":{"execution":{"iopub.status.busy":"2022-08-09T03:05:26.241191Z","iopub.execute_input":"2022-08-09T03:05:26.247042Z","iopub.status.idle":"2022-08-09T03:05:26.260791Z","shell.execute_reply.started":"2022-08-09T03:05:26.246980Z","shell.execute_reply":"2022-08-09T03:05:26.259413Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df.head()","metadata":{"execution":{"iopub.status.busy":"2022-08-09T03:05:26.263127Z","iopub.execute_input":"2022-08-09T03:05:26.263970Z","iopub.status.idle":"2022-08-09T03:05:26.282775Z","shell.execute_reply.started":"2022-08-09T03:05:26.263935Z","shell.execute_reply":"2022-08-09T03:05:26.281950Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# HAP Check","metadata":{}},{"cell_type":"code","source":"import cv2\nidx = \"10274_0007\"\nimg = cv2.cvtColor(cv2.imread(f\"../input/hubmap-2022-256x256/train/{idx}.png\"), cv2.COLOR_BGR2RGB)\nmask = cv2.imread(f\"../input/hubmap-2022-256x256/masks/{idx}.png\", cv2.IMREAD_GRAYSCALE)\nplt.imshow(img)","metadata":{"execution":{"iopub.status.busy":"2022-08-09T03:05:26.284222Z","iopub.execute_input":"2022-08-09T03:05:26.284844Z","iopub.status.idle":"2022-08-09T03:05:26.559844Z","shell.execute_reply.started":"2022-08-09T03:05:26.284805Z","shell.execute_reply":"2022-08-09T03:05:26.558768Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.imshow(mask,cmap = 'gray')","metadata":{"execution":{"iopub.status.busy":"2022-08-09T03:05:26.563707Z","iopub.execute_input":"2022-08-09T03:05:26.566965Z","iopub.status.idle":"2022-08-09T03:05:26.805461Z","shell.execute_reply.started":"2022-08-09T03:05:26.566925Z","shell.execute_reply":"2022-08-09T03:05:26.804523Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"img = img2tensor(img / 255.0).unsqueeze(0)","metadata":{"execution":{"iopub.status.busy":"2022-08-09T03:05:26.810108Z","iopub.execute_input":"2022-08-09T03:05:26.812353Z","iopub.status.idle":"2022-08-09T03:05:26.818999Z","shell.execute_reply.started":"2022-08-09T03:05:26.812312Z","shell.execute_reply":"2022-08-09T03:05:26.818076Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"m = models[0][0]\npred = m(img.to('cuda'))","metadata":{"execution":{"iopub.status.busy":"2022-08-09T03:05:26.823933Z","iopub.execute_input":"2022-08-09T03:05:26.826445Z","iopub.status.idle":"2022-08-09T03:05:26.916791Z","shell.execute_reply.started":"2022-08-09T03:05:26.826400Z","shell.execute_reply":"2022-08-09T03:05:26.915807Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"pred = torch.sigmoid(pred) > TH\npred = pred.squeeze().squeeze().detach().cpu()\npred = np.array(pred, dtype=np.uint8)","metadata":{"execution":{"iopub.status.busy":"2022-08-09T03:05:26.921702Z","iopub.execute_input":"2022-08-09T03:05:26.923906Z","iopub.status.idle":"2022-08-09T03:05:26.939189Z","shell.execute_reply.started":"2022-08-09T03:05:26.923869Z","shell.execute_reply":"2022-08-09T03:05:26.938077Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.imshow(pred,cmap = 'gray')","metadata":{"execution":{"iopub.status.busy":"2022-08-09T03:05:26.943673Z","iopub.execute_input":"2022-08-09T03:05:26.945798Z","iopub.status.idle":"2022-08-09T03:05:27.161611Z","shell.execute_reply.started":"2022-08-09T03:05:26.945761Z","shell.execute_reply":"2022-08-09T03:05:27.160669Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# HUBMAP Check","metadata":{}},{"cell_type":"code","source":"import cv2\nidx = \"0486052bb_0082\"\nimg = cv2.cvtColor(cv2.imread(f\"../input/hubmap-256x256/train/{idx}.png\"), cv2.COLOR_BGR2RGB)\nmask = cv2.imread(f\"../input/hubmap-256x256/masks/{idx}.png\", cv2.IMREAD_GRAYSCALE)\nplt.imshow(img)\nimg.shape","metadata":{"execution":{"iopub.status.busy":"2022-08-09T03:05:27.166302Z","iopub.execute_input":"2022-08-09T03:05:27.169072Z","iopub.status.idle":"2022-08-09T03:05:27.432101Z","shell.execute_reply.started":"2022-08-09T03:05:27.169007Z","shell.execute_reply":"2022-08-09T03:05:27.430985Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.imshow(mask,cmap = 'gray')","metadata":{"execution":{"iopub.status.busy":"2022-08-09T03:05:27.433496Z","iopub.execute_input":"2022-08-09T03:05:27.433945Z","iopub.status.idle":"2022-08-09T03:05:27.635054Z","shell.execute_reply.started":"2022-08-09T03:05:27.433906Z","shell.execute_reply":"2022-08-09T03:05:27.634050Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"img = img2tensor(img / 255.0).unsqueeze(0)","metadata":{"execution":{"iopub.status.busy":"2022-08-09T03:05:27.636366Z","iopub.execute_input":"2022-08-09T03:05:27.636952Z","iopub.status.idle":"2022-08-09T03:05:27.644234Z","shell.execute_reply.started":"2022-08-09T03:05:27.636913Z","shell.execute_reply":"2022-08-09T03:05:27.643064Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"m = models[0][0]\npred = m(img.to('cuda'))\npred = torch.sigmoid(pred) > TH\npred = pred.squeeze().squeeze().detach().cpu()\npred = np.array(pred, dtype=np.uint8)","metadata":{"execution":{"iopub.status.busy":"2022-08-09T03:05:27.646043Z","iopub.execute_input":"2022-08-09T03:05:27.646758Z","iopub.status.idle":"2022-08-09T03:05:27.710827Z","shell.execute_reply.started":"2022-08-09T03:05:27.646704Z","shell.execute_reply":"2022-08-09T03:05:27.709697Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.imshow(pred,cmap = 'gray')","metadata":{"execution":{"iopub.status.busy":"2022-08-09T03:05:27.713040Z","iopub.execute_input":"2022-08-09T03:05:27.713727Z","iopub.status.idle":"2022-08-09T03:05:27.916853Z","shell.execute_reply.started":"2022-08-09T03:05:27.713689Z","shell.execute_reply":"2022-08-09T03:05:27.915909Z"},"trusted":true},"execution_count":null,"outputs":[]}]}