{"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":"# Config","metadata":{"papermill":{"duration":0.015995,"end_time":"2021-03-31T10:37:28.897826","exception":false,"start_time":"2021-03-31T10:37:28.881831","status":"completed"},"tags":[]}},{"cell_type":"code","source":"DEBUG = False","metadata":{"papermill":{"duration":0.024862,"end_time":"2021-03-31T10:37:28.939348","exception":false,"start_time":"2021-03-31T10:37:28.914486","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2022-04-27T09:27:28.005585Z","iopub.execute_input":"2022-04-27T09:27:28.005870Z","iopub.status.idle":"2022-04-27T09:27:28.011295Z","shell.execute_reply.started":"2022-04-27T09:27:28.005843Z","shell.execute_reply":"2022-04-27T09:27:28.010408Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import torch\n\nconfig = {\n    'split_seed_list':[0],\n    'FOLD_LIST':[0,1,2,3], \n    'model_path':'../input/hubmap-new-03-03/model_seed0_fold0_bestscore.pth',\n    'model_name':'seresnext101',\n    \n    'num_classes':1,\n    'resolution':1024, #(1024,1024),(512,512),\n    'input_resolution':320, #(320,320), #(256,256), #(512,512), #(384,384)\n    'deepsupervision':False, # always false for inference\n    'clfhead':False,\n    'clf_threshold':0.5,\n    'small_mask_threshold':0, #256*256*0.03, #512*512*0.03,\n    'mask_threshold':0.5,\n    'pad_size':256, #(64,64), #(256,256), #(128,128)\n    \n    'test_batch_size':12,\n    \n    'FP16':False,\n    'num_workers':4,\n    'device':torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\"),\n}\n\ndevice = config['device']","metadata":{"papermill":{"duration":1.689504,"end_time":"2021-03-31T10:37:30.64523","exception":false,"start_time":"2021-03-31T10:37:28.955726","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2022-04-27T09:32:56.833180Z","iopub.execute_input":"2022-04-27T09:32:56.833502Z","iopub.status.idle":"2022-04-27T09:32:56.841506Z","shell.execute_reply.started":"2022-04-27T09:32:56.833472Z","shell.execute_reply":"2022-04-27T09:32:56.840406Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Import Libraries and Data","metadata":{"papermill":{"duration":0.016215,"end_time":"2021-03-31T10:37:30.677231","exception":false,"start_time":"2021-03-31T10:37:30.661016","status":"completed"},"tags":[]}},{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\npd.get_option(\"display.max_columns\")\npd.set_option('display.max_columns', 300)\npd.get_option(\"display.max_rows\")\npd.set_option('display.max_rows', 300)\n\nimport matplotlib.pyplot as plt\n%matplotlib inline\n\nimport sys\nimport os\nfrom os.path import join as opj\nimport gc\n\nimport cv2\nimport rasterio\nfrom rasterio.windows import Window\n\nINPUT_PATH = '../input/hubmap-kidney-segmentation'","metadata":{"_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","papermill":{"duration":0.459661,"end_time":"2021-03-31T10:37:31.152738","exception":false,"start_time":"2021-03-31T10:37:30.693077","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2022-04-27T09:27:29.123949Z","iopub.execute_input":"2022-04-27T09:27:29.124290Z","iopub.status.idle":"2022-04-27T09:27:29.520108Z","shell.execute_reply.started":"2022-04-27T09:27:29.124262Z","shell.execute_reply":"2022-04-27T09:27:29.519378Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print('Python        : ' + sys.version.split('\\n')[0])\nprint('Numpy         : ' + np.__version__)\nprint('Pandas        : ' + pd.__version__)\nprint('Rasterio      : ' + rasterio.__version__)\nprint('OpenCV        : ' + cv2.__version__)","metadata":{"papermill":{"duration":0.028018,"end_time":"2021-03-31T10:37:31.199056","exception":false,"start_time":"2021-03-31T10:37:31.171038","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2022-04-27T09:27:29.522541Z","iopub.execute_input":"2022-04-27T09:27:29.523073Z","iopub.status.idle":"2022-04-27T09:27:29.530484Z","shell.execute_reply.started":"2022-04-27T09:27:29.523033Z","shell.execute_reply":"2022-04-27T09:27:29.529379Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df = pd.read_csv(opj(INPUT_PATH, 'train.csv'))\ninfo_df  = pd.read_csv(opj(INPUT_PATH,'HuBMAP-20-dataset_information.csv'))\nsub_df = pd.read_csv(opj(INPUT_PATH, 'sample_submission.csv'))\n\nprint('train_df.shape = ', train_df.shape)\nprint('info_df.shape  = ', info_df.shape)\nprint('sub_df.shape = ', sub_df.shape)","metadata":{"papermill":{"duration":0.369479,"end_time":"2021-03-31T10:37:31.58586","exception":false,"start_time":"2021-03-31T10:37:31.216381","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2022-04-27T09:27:29.532272Z","iopub.execute_input":"2022-04-27T09:27:29.532753Z","iopub.status.idle":"2022-04-27T09:27:29.920549Z","shell.execute_reply.started":"2022-04-27T09:27:29.532701Z","shell.execute_reply":"2022-04-27T09:27:29.919816Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#sub_df['predicted'] = '1 1'\n#sub_df.to_csv('submission.csv', index=False)\n\nif len(sub_df) == 5:\n    if DEBUG:\n        sub_df = sub_df[:]\n    else:\n        sub_df = sub_df[:1]","metadata":{"papermill":{"duration":0.025261,"end_time":"2021-03-31T10:37:31.62786","exception":false,"start_time":"2021-03-31T10:37:31.602599","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2022-04-27T09:27:29.923312Z","iopub.execute_input":"2022-04-27T09:27:29.923683Z","iopub.status.idle":"2022-04-27T09:27:29.928805Z","shell.execute_reply.started":"2022-04-27T09:27:29.923643Z","shell.execute_reply":"2022-04-27T09:27:29.927896Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Utils  ","metadata":{"papermill":{"duration":0.016345,"end_time":"2021-03-31T10:37:31.660344","exception":false,"start_time":"2021-03-31T10:37:31.643999","status":"completed"},"tags":[]}},{"cell_type":"code","source":"import random\nimport torch\nimport numpy as np\nimport os\nimport time\n\ndef fix_seed(seed):\n    random.seed(seed)\n    torch.manual_seed(seed)\n    torch.cuda.manual_seed_all(seed)\n    np.random.seed(seed)\n    os.environ['PYTHONHASHSEED'] = str(seed)\n    torch.backends.cudnn.deterministic = True\n    torch.backends.cudnn.benchmark = True\n    \ndef elapsed_time(start_time):\n    return time.time() - start_time\n\ndef count_parameters(model):\n    return sum(p.numel() for p in model.parameters() if p.requires_grad)\n\nfix_seed(2020)","metadata":{"papermill":{"duration":0.030782,"end_time":"2021-03-31T10:37:31.707493","exception":false,"start_time":"2021-03-31T10:37:31.676711","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2022-04-27T09:27:29.930379Z","iopub.execute_input":"2022-04-27T09:27:29.930906Z","iopub.status.idle":"2022-04-27T09:27:29.943386Z","shell.execute_reply.started":"2022-04-27T09:27:29.930864Z","shell.execute_reply":"2022-04-27T09:27:29.942494Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import cv2\n\ndef rle2mask(rle, shape):\n    '''\n    mask_rle: run-length as string formatted (start length)\n    shape: (height, width) of array to return \n    Returns numpy array <- 1(mask), 0(background)\n    '''\n    s = rle.split()\n    starts, lengths = [np.asarray(x, dtype=int) for x in (s[0:][::2], s[1:][::2])]\n    starts -= 1\n    ends = starts + lengths\n    img = np.zeros(shape[0]*shape[1], dtype=np.uint8)\n    for lo, hi in zip(starts, ends):\n        img[lo:hi] = 1\n    return img.reshape(shape, order='F')  # Needed to align to RLE direction\n\n\ndef mask2rle(img, shape, small_mask_threshold):\n    '''\n    Convert mask to rle.\n    img: numpy array <- 1(mask), 0(background)\n    Returns run length as string formated\n    \n    pixels = np.array([1,1,1,0,0,1,0,1,1]) #-> rle = '1 3 6 1 8 2'\n    pixels = np.concatenate([[0], pixels, [0]]) #[0,1,1,1,0,0,1,0,1,1,0]\n    runs = np.where(pixels[1:] != pixels[:-1])[0] + 1 #[ 1  4  6  7  8 10] bit change points\n    print(runs[1::2]) #[4 7 10]\n    print(runs[::2]) #[1 6 8]\n    runs[1::2] -= runs[::2]\n    print(runs) #[1 3 6 1 8 2]\n    '''\n    if img.shape != shape:\n        h,w = shape\n        img = cv2.resize(img, dsize=(w,h), interpolation=cv2.INTER_LINEAR)\n    img = img.astype(np.int8) \n    pixels = img.T.flatten()\n    #pixels = np.concatenate([[0], pixels, [0]])\n    pixels = np.pad(pixels, ((1, 1), ))\n    runs = np.where(pixels[1:] != pixels[:-1])[0] + 1\n    runs[1::2] -= runs[::2]\n    if runs[1::2].sum() <= small_mask_threshold:\n        return ''\n    else:\n        return ' '.join(str(x) for x in runs)","metadata":{"papermill":{"duration":0.033552,"end_time":"2021-03-31T10:37:31.757271","exception":false,"start_time":"2021-03-31T10:37:31.723719","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2022-04-27T09:27:29.945144Z","iopub.execute_input":"2022-04-27T09:27:29.945606Z","iopub.status.idle":"2022-04-27T09:27:29.960718Z","shell.execute_reply.started":"2022-04-27T09:27:29.945543Z","shell.execute_reply":"2022-04-27T09:27:29.959896Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Model","metadata":{"papermill":{"duration":0.01607,"end_time":"2021-03-31T10:37:31.789392","exception":false,"start_time":"2021-03-31T10:37:31.773322","status":"completed"},"tags":[]}},{"cell_type":"code","source":"import torch\nfrom torch import nn, optim\nimport torch.nn.functional as F\nimport sys\npackage_dir = \"../input/pretrainedmodels/pretrained-models.pytorch-master/\"\nsys.path.insert(0, package_dir)\nimport pretrainedmodels\n\n\ndef conv3x3(in_channel, out_channel): #not change resolusion\n    return nn.Conv2d(in_channel,out_channel,\n                      kernel_size=3,stride=1,padding=1,dilation=1,bias=False)\n\ndef conv1x1(in_channel, out_channel): #not change resolution\n    return nn.Conv2d(in_channel,out_channel,\n                      kernel_size=1,stride=1,padding=0,dilation=1,bias=False)\n\ndef init_weight(m):\n    classname = m.__class__.__name__\n    if classname.find('Conv') != -1:\n        #nn.init.xavier_uniform_(m.weight, gain=1)\n        #nn.init.xavier_normal_(m.weight, gain=1)\n        #nn.init.kaiming_uniform_(m.weight, mode='fan_in', nonlinearity='relu')\n        nn.init.kaiming_normal_(m.weight, mode='fan_in', nonlinearity='relu')\n        #nn.init.orthogonal_(m.weight, gain=1)\n        if m.bias is not None:\n            m.bias.data.zero_()\n    elif classname.find('Batch') != -1:\n        m.weight.data.normal_(1,0.02)\n        m.bias.data.zero_()\n    elif classname.find('Linear') != -1:\n        nn.init.orthogonal_(m.weight, gain=1)\n        if m.bias is not None:\n            m.bias.data.zero_()\n    elif classname.find('Embedding') != -1:\n        nn.init.orthogonal_(m.weight, gain=1)\n\n        \nclass cSEBlock(nn.Module):\n    def __init__(self, c, feat):\n        super().__init__()\n        self.attention_fc = nn.Linear(feat,1, bias=False)\n        self.bias         = nn.Parameter(torch.zeros((1,c,1), requires_grad=True))\n        self.sigmoid      = nn.Sigmoid()\n        self.dropout      = nn.Dropout2d(0.1)\n        \n    def forward(self,inputs):\n        batch,c,h,w = inputs.size()\n        x = inputs.view(batch,c,-1)\n        x = self.attention_fc(x) + self.bias\n        x = x.view(batch,c,1,1)\n        x = self.sigmoid(x)\n        x = self.dropout(x)\n        return inputs * x\n\nclass sSEBlock(nn.Module):\n    def __init__(self, c, h, w):\n        super().__init__()\n        self.attention_fc = nn.Linear(c,1, bias=False).apply(init_weight)\n        self.bias         = nn.Parameter(torch.zeros((1,h,w,1), requires_grad=True))\n        self.sigmoid      = nn.Sigmoid()\n        \n    def forward(self,inputs):\n        batch,c,h,w = inputs.size()\n        x = torch.transpose(inputs, 1,2) #(*,c,h,w)->(*,h,c,w)\n        x = torch.transpose(x, 2,3) #(*,h,c,w)->(*,h,w,c)\n        x = self.attention_fc(x) + self.bias\n        x = torch.transpose(x, 2,3) #(*,h,w,1)->(*,h,1,w)\n        x = torch.transpose(x, 1,2) #(*,h,1,w)->(*,1,h,w)\n        x = self.sigmoid(x)\n        return inputs * x\n    \nclass scSEBlock(nn.Module):\n    def __init__(self, c, h, w):\n        super().__init__()\n        self.cSE = cSEBlock(c,h*w)\n        self.sSE = sSEBlock(c,h,w)\n    \n    def forward(self, inputs):\n        x1 = self.cSE(inputs)\n        x2 = self.sSE(inputs)\n        return x1+x2\n    \n\nclass Attention(nn.Module):\n    def __init__(self, channels):\n        super().__init__()\n        self.channels = channels\n        self.theta    = nn.utils.spectral_norm(conv1x1(channels, channels//8)).apply(init_weight)\n        self.phi      = nn.utils.spectral_norm(conv1x1(channels, channels//8)).apply(init_weight)\n        self.g        = nn.utils.spectral_norm(conv1x1(channels, channels//2)).apply(init_weight)\n        self.o        = nn.utils.spectral_norm(conv1x1(channels//2, channels)).apply(init_weight)\n        self.gamma    = nn.Parameter(torch.tensor(0.), requires_grad=True)\n        \n    def forward(self, inputs):\n        batch,c,h,w = inputs.size()\n        theta = self.theta(inputs) #->(*,c/8,h,w)\n        phi   = F.max_pool2d(self.phi(inputs), [2,2]) #->(*,c/8,h/2,w/2)\n        g     = F.max_pool2d(self.g(inputs), [2,2]) #->(*,c/2,h/2,w/2)\n        \n        theta = theta.view(batch, self.channels//8, -1) #->(*,c/8,h*w)\n        phi   = phi.view(batch, self.channels//8, -1) #->(*,c/8,h*w/4)\n        g     = g.view(batch, self.channels//2, -1) #->(*,c/2,h*w/4)\n        \n        beta = F.softmax(torch.bmm(theta.transpose(1,2), phi), -1) #->(*,h*w,h*w/4)\n        o    = self.o(torch.bmm(g, beta.transpose(1,2)).view(batch,self.channels//2,h,w)) #->(*,c,h,w)\n        return self.gamma*o + inputs\n    \n    \n\nclass ChannelAttentionModule(nn.Module):\n    def __init__(self, in_channel, reduction):\n        super().__init__()\n        self.global_maxpool = nn.AdaptiveMaxPool2d(1)\n        self.global_avgpool = nn.AdaptiveAvgPool2d(1) \n        self.fc = nn.Sequential(\n            conv1x1(in_channel, in_channel//reduction).apply(init_weight),\n            nn.ReLU(True),\n            conv1x1(in_channel//reduction, in_channel).apply(init_weight)\n        )\n        \n    def forward(self, inputs):\n        x1 = self.global_maxpool(inputs)\n        x2 = self.global_avgpool(inputs)\n        x1 = self.fc(x1)\n        x2 = self.fc(x2)\n        x  = torch.sigmoid(x1 + x2)\n        return x\n    \n    \nclass SpatialAttentionModule(nn.Module):\n    def __init__(self):\n        super().__init__()\n        self.conv3x3 = conv3x3(2,1).apply(init_weight)\n        \n    def forward(self, inputs):\n        x1,_ = torch.max(inputs, dim=1, keepdim=True)\n        x2 = torch.mean(inputs, dim=1, keepdim=True)\n        x  = torch.cat([x1,x2], dim=1)\n        x  = self.conv3x3(x)\n        x  = torch.sigmoid(x)\n        return x\n    \n    \nclass CBAM(nn.Module):\n    def __init__(self, in_channel, reduction):\n        super().__init__()\n        self.channel_attention = ChannelAttentionModule(in_channel, reduction)\n        self.spatial_attention = SpatialAttentionModule()\n        \n    def forward(self, inputs):\n        x = inputs * self.channel_attention(inputs)\n        x = x * self.spatial_attention(x)\n        return x\n    \n    \nclass CenterBlock(nn.Module):\n    def __init__(self, in_channel, out_channel):\n        super().__init__()\n        self.conv = conv3x3(in_channel, out_channel).apply(init_weight)\n        \n    def forward(self, inputs):\n        x = self.conv(inputs)\n        return x\n\n\nclass DecodeBlock(nn.Module):\n    def __init__(self, in_channel, out_channel, upsample):\n        super().__init__()\n        self.bn1 = nn.BatchNorm2d(in_channel).apply(init_weight)\n        self.upsample = nn.Sequential()\n        if upsample:\n            self.upsample.add_module('upsample',nn.Upsample(scale_factor=2, mode='nearest'))\n        self.conv3x3_1 = conv3x3(in_channel, in_channel).apply(init_weight)\n        self.bn2 = nn.BatchNorm2d(in_channel).apply(init_weight)\n        self.conv3x3_2 = conv3x3(in_channel, out_channel).apply(init_weight)\n        self.cbam = CBAM(out_channel, reduction=16)\n        self.conv1x1   = conv1x1(in_channel, out_channel).apply(init_weight)\n        \n    def forward(self, inputs):\n        x  = F.relu(self.bn1(inputs))\n        x  = self.upsample(x)\n        x  = self.conv3x3_1(x)\n        x  = self.conv3x3_2(F.relu(self.bn2(x)))\n        x  = self.cbam(x)\n        x += self.conv1x1(self.upsample(inputs)) #shortcut\n        return x\n    \n\n#U-Net SeResNext101 + CBAM + hypercolumns + deepsupervision\nclass UNET_SERESNEXT101(nn.Module):\n    def __init__(self, resolution, deepsupervision, clfhead, load_weights=True):\n        super().__init__()\n        h,w = resolution\n        self.deepsupervision = deepsupervision\n        self.clfhead = clfhead\n        \n        #encoder\n        model_name = 'se_resnext101_32x4d'\n        seresnext101 = pretrainedmodels.__dict__[model_name](pretrained=None)\n        if load_weights:\n            seresnext101.load_state_dict(torch.load(f'../../../pretrainedmodels_weight/{model_name}.pth'))\n        \n        self.encoder0 = nn.Sequential(\n            seresnext101.layer0.conv1, #(*,3,h,w)->(*,64,h/2,w/2)\n            seresnext101.layer0.bn1,\n            seresnext101.layer0.relu1,\n        )\n        self.encoder1 = nn.Sequential(\n            seresnext101.layer0.pool, #->(*,64,h/4,w/4)\n            seresnext101.layer1 #->(*,256,h/4,w/4)\n        )\n        self.encoder2 = seresnext101.layer2 #->(*,512,h/8,w/8)\n        self.encoder3 = seresnext101.layer3 #->(*,1024,h/16,w/16)\n        self.encoder4 = seresnext101.layer4 #->(*,2048,h/32,w/32)\n        \n        #center\n        self.center  = CenterBlock(2048,512) #->(*,512,h/32,w/32)\n        \n        #decoder\n        self.decoder4 = DecodeBlock(512+2048,64, upsample=True) #->(*,64,h/16,w/16)\n        self.decoder3 = DecodeBlock(64+1024,64, upsample=True) #->(*,64,h/8,w/8)\n        self.decoder2 = DecodeBlock(64+512,64,  upsample=True) #->(*,64,h/4,w/4) \n        self.decoder1 = DecodeBlock(64+256,64,   upsample=True) #->(*,64,h/2,w/2) \n        self.decoder0 = DecodeBlock(64,64, upsample=True) #->(*,64,h,w) \n        \n        #upsample\n        self.upsample4 = nn.Upsample(scale_factor=16, mode='bilinear', align_corners=True)\n        self.upsample3 = nn.Upsample(scale_factor=8, mode='bilinear', align_corners=True)\n        self.upsample2 = nn.Upsample(scale_factor=4, mode='bilinear', align_corners=True)\n        self.upsample1 = nn.Upsample(scale_factor=2, mode='bilinear', align_corners=True)\n        \n        #deep supervision\n        self.deep4 = conv1x1(64,1).apply(init_weight)\n        self.deep3 = conv1x1(64,1).apply(init_weight)\n        self.deep2 = conv1x1(64,1).apply(init_weight)\n        self.deep1 = conv1x1(64,1).apply(init_weight)\n        \n        #final conv\n        self.final_conv = nn.Sequential(\n            conv3x3(320,64).apply(init_weight),\n            nn.ELU(True),\n            conv1x1(64,1).apply(init_weight)\n        )\n        \n        #clf head\n        self.avgpool = nn.AdaptiveAvgPool2d(1)\n        self.clf = nn.Sequential(\n            nn.BatchNorm1d(2048).apply(init_weight),\n            nn.Linear(2048,512).apply(init_weight),\n            nn.ELU(True),\n            nn.BatchNorm1d(512).apply(init_weight),\n            nn.Linear(512,1).apply(init_weight)\n        )\n        \n    def forward(self, inputs):\n        #encoder\n        x0 = self.encoder0(inputs) #->(*,64,h/2,w/2)\n        x1 = self.encoder1(x0) #->(*,256,h/4,w/4)\n        x2 = self.encoder2(x1) #->(*,512,h/8,w/8)\n        x3 = self.encoder3(x2) #->(*,1024,h/16,w/16)\n        x4 = self.encoder4(x3) #->(*,2048,h/32,w/32)\n        \n        #clf head\n        logits_clf = self.clf(self.avgpool(x4).squeeze(-1).squeeze(-1)) #->(*,1)\n        if config['clf_threshold'] is not None:\n            if (torch.sigmoid(logits_clf)>config['clf_threshold']).sum().item()==0:\n                bs,_,h,w = inputs.shape\n                logits = torch.zeros((bs,1,h,w))\n                if self.clfhead:\n                    if self.deepsupervision:\n                        return logits,_,_\n                    else:\n                        return logits,_\n                else:\n                    if self.deepsupervision:\n                        return logits,_\n                    else:\n                        return logits\n        \n        #center\n        y5 = self.center(x4) #->(*,320,h/32,w/32)\n        \n        #decoder\n        y4 = self.decoder4(torch.cat([x4,y5], dim=1)) #->(*,64,h/16,w/16)\n        y3 = self.decoder3(torch.cat([x3,y4], dim=1)) #->(*,64,h/8,w/8)\n        y2 = self.decoder2(torch.cat([x2,y3], dim=1)) #->(*,64,h/4,w/4)\n        y1 = self.decoder1(torch.cat([x1,y2], dim=1)) #->(*,64,h/2,w/2) \n        y0 = self.decoder0(y1) #->(*,64,h,w)\n        \n        #hypercolumns\n        y4 = self.upsample4(y4) #->(*,64,h,w)\n        y3 = self.upsample3(y3) #->(*,64,h,w)\n        y2 = self.upsample2(y2) #->(*,64,h,w)\n        y1 = self.upsample1(y1) #->(*,64,h,w)\n        hypercol = torch.cat([y0,y1,y2,y3,y4], dim=1)\n        \n        #final conv\n        logits = self.final_conv(hypercol) #->(*,1,h,w)\n        \n        #clf head\n        logits_clf = self.clf(self.avgpool(x4).squeeze(-1).squeeze(-1)) #->(*,1)\n        \n        if self.clfhead:\n            if self.deepsupervision:\n                s4 = self.deep4(y4)\n                s3 = self.deep3(y3)\n                s2 = self.deep2(y2)\n                s1 = self.deep1(y1)\n                logits_deeps = [s4,s3,s2,s1]\n                return logits, logits_deeps, logits_clf\n            else:\n                return logits, logits_clf\n        else:\n            if self.deepsupervision:\n                s4 = self.deep4(y4)\n                s3 = self.deep3(y3)\n                s2 = self.deep2(y2)\n                s1 = self.deep1(y1)\n                logits_deeps = [s4,s3,s2,s1]\n                return logits, logits_deeps\n            else:\n                return logits    \n\n    \ndef build_model(resolution, deepsupervision, clfhead, load_weights):\n    model_name = config['model_name']\n    if model_name=='resnet34':\n        model = UNET_RESNET34(resolution, deepsupervision, clfhead, load_weights)\n    elif model_name=='seresnext50':\n        model = UNET_SERESNEXT50(resolution, deepsupervision, clfhead, load_weights)\n    elif model_name=='seresnext101':\n        model = UNET_SERESNEXT101(resolution, deepsupervision, clfhead, load_weights)\n    return model","metadata":{"papermill":{"duration":1.551183,"end_time":"2021-03-31T10:37:33.356746","exception":false,"start_time":"2021-03-31T10:37:31.805563","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2022-04-27T09:27:29.962200Z","iopub.execute_input":"2022-04-27T09:27:29.963626Z","iopub.status.idle":"2022-04-27T09:27:31.410275Z","shell.execute_reply.started":"2022-04-27T09:27:29.963590Z","shell.execute_reply":"2022-04-27T09:27:31.409489Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Inference","metadata":{"papermill":{"duration":0.016345,"end_time":"2021-03-31T10:37:33.38936","exception":false,"start_time":"2021-03-31T10:37:33.373015","status":"completed"},"tags":[]}},{"cell_type":"code","source":"path = config['model_path']\nmodel = build_model(resolution=(None,None), #config['resolution'], \n                    deepsupervision=config['deepsupervision'], \n                    clfhead=config['clfhead'],\n                    load_weights=False).to(device)\n\nmodel.load_state_dict(torch.load(path))\nmodel.eval()\nprint()","metadata":{"papermill":{"duration":34.271842,"end_time":"2021-03-31T10:38:07.677397","exception":false,"start_time":"2021-03-31T10:37:33.405555","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2022-04-27T09:33:11.264630Z","iopub.execute_input":"2022-04-27T09:33:11.264971Z","iopub.status.idle":"2022-04-27T09:33:13.895491Z","shell.execute_reply.started":"2022-04-27T09:33:11.264941Z","shell.execute_reply":"2022-04-27T09:33:13.894607Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import numpy as np\nfrom albumentations import (Compose, HorizontalFlip, VerticalFlip, Rotate, RandomRotate90,\n                            ShiftScaleRotate, ElasticTransform,\n                            GridDistortion, RandomSizedCrop, RandomCrop, CenterCrop,\n                            RandomBrightnessContrast, HueSaturationValue, IAASharpen,\n                            RandomGamma, RandomBrightness, RandomBrightnessContrast,\n                            GaussianBlur,CLAHE,\n                            Cutout, CoarseDropout, GaussNoise, ChannelShuffle, ToGray, OpticalDistortion,\n                            Normalize, OneOf, NoOp)\nfrom albumentations.pytorch import ToTensor, ToTensorV2\n#from get_config import *\n#config = get_config()\n\nMEAN = np.array([0.485, 0.456, 0.406])\nSTD  = np.array([0.229, 0.224, 0.225])\n\ndef get_transforms_test():\n    transforms = Compose([\n        Normalize(mean=(MEAN[0], MEAN[1], MEAN[2]), \n                  std=(STD[0], STD[1], STD[2])),\n        ToTensorV2(),\n    ] )\n    return transforms\n\ndef denormalize(z, mean=MEAN.reshape(-1,1,1), std=STD.reshape(-1,1,1)):\n    return std*z + mean","metadata":{"papermill":{"duration":1.342372,"end_time":"2021-03-31T10:38:09.046504","exception":false,"start_time":"2021-03-31T10:38:07.704132","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2022-04-27T09:33:17.527669Z","iopub.execute_input":"2022-04-27T09:33:17.528744Z","iopub.status.idle":"2022-04-27T09:33:17.570880Z","shell.execute_reply.started":"2022-04-27T09:33:17.528697Z","shell.execute_reply":"2022-04-27T09:33:17.569169Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from torch.utils.data import Dataset\n\nclass HuBMAPDataset(Dataset):\n    def __init__(self, idx, df):\n        super().__init__()\n        filename = df.loc[idx, 'id']+'.tiff'\n        path = opj(INPUT_PATH,'test',filename)\n        self.data = rasterio.open(path)\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.h, self.w = self.data.height, self.data.width\n        self.input_sz = config['input_resolution']\n        self.sz = config['resolution']\n        self.pad_sz = config['pad_size'] # add to each input tile\n        self.pred_sz = self.sz - 2*self.pad_sz\n        self.pad_h = self.pred_sz - self.h % self.pred_sz # add to whole slide\n        self.pad_w = self.pred_sz - self.w % self.pred_sz # add to whole slide\n        self.num_h = (self.h + self.pad_h) // self.pred_sz\n        self.num_w = (self.w + self.pad_w) // self.pred_sz\n        self.transforms = get_transforms_test()\n        \n    def __len__(self):\n        return self.num_h * self.num_w\n    \n    def __getitem__(self, idx): # idx = i_h * self.num_w + i_w\n        # prepare coordinates for rasterio\n        i_h = idx // self.num_w\n        i_w = idx % self.num_w\n        y = i_h*self.pred_sz \n        x = i_w*self.pred_sz\n        py0,py1 = max(0,y), min(y+self.pred_sz, self.h)\n        px0,px1 = max(0,x), min(x+self.pred_sz, self.w)\n        \n        # padding coordinate for rasterio\n        qy0,qy1 = max(0,y-self.pad_sz), min(y+self.pred_sz+self.pad_sz, self.h)\n        qx0,qx1 = max(0,x-self.pad_sz), min(x+self.pred_sz+self.pad_sz, self.w)\n        \n        # placeholder for input tile (before resize)\n        img = np.zeros((self.sz,self.sz,3), np.uint8)\n        \n        # replace the value\n        if self.data.count == 3:\n            img[0:qy1-qy0, 0:qx1-qx0] =\\\n                np.moveaxis(self.data.read([1,2,3], window=Window.from_slices((qy0,qy1),(qx0,qx1))), 0,-1)\n        else:\n            for i,layer in enumerate(self.layers):\n                img[0:qy1-qy0, 0:qx1-qx0, i] =\\\n                    layer.read(1,window=Window.from_slices((qy0,qy1),(qx0,qx1)))\n        if self.sz != self.input_sz:\n            img = cv2.resize(img, (self.input_sz, self.input_sz), interpolation=cv2.INTER_AREA)\n        img = self.transforms(image=img)['image'] # to normalized tensor\n        return {'img':img, 'p':[py0,py1,px0,px1], 'q':[qy0,qy1,qx0,qx1]}","metadata":{"papermill":{"duration":0.042755,"end_time":"2021-03-31T10:38:09.106626","exception":false,"start_time":"2021-03-31T10:38:09.063871","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2022-04-27T09:33:19.311506Z","iopub.execute_input":"2022-04-27T09:33:19.311891Z","iopub.status.idle":"2022-04-27T09:33:19.338979Z","shell.execute_reply.started":"2022-04-27T09:33:19.311846Z","shell.execute_reply":"2022-04-27T09:33:19.338083Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from torch.utils.data import DataLoader\nfrom tqdm.notebook import tqdm\nimport gc\nimport math\n\n\ndef my_collate_fn(batch):\n    img = []\n    p = []\n    q = []\n    for sample in batch:\n        img.append(sample['img'])\n        p.append(sample['p'])\n        q.append(sample['q'])\n    img = torch.stack(img)\n    return {'img':img, 'p':p, 'q':q}\n\n\nseed = 0\n\ndef get_pred_mask(idx, df, model):\n    ds = HuBMAPDataset(idx, df)\n    #rasterio cannot be used with multiple workers\n    dl = DataLoader(ds,batch_size=config['test_batch_size'],\n                    num_workers=0,shuffle=False,pin_memory=True,\n                    collate_fn=my_collate_fn) \n    \n    pred_mask = np.zeros((len(ds),ds.pred_sz,ds.pred_sz), dtype=np.uint8)\n    \n    i_data = 0\n    for data in tqdm(dl):\n        bs = data['img'].shape[0]\n        img_patch = data['img'] # (bs,3,input_res,input_res)\n\n        with torch.no_grad():\n            pred_mask_float = torch.sigmoid(model(img_patch.to(device, torch.float32, non_blocking=True))).detach().cpu().numpy()[:,0,:,:] #.squeeze()\n        \n        # resize\n        pred_mask_float = np.vstack([cv2.resize(_mask.astype(np.float32), (ds.sz,ds.sz))[None] for _mask in pred_mask_float])\n        \n        # float to uint8\n        pred_mask_int = (pred_mask_float>config['mask_threshold']).astype(np.uint8)\n        \n        # replace the values\n        for j in range(bs):\n            py0,py1,px0,px1 = data['p'][j]\n            qy0,qy1,qx0,qx1 = data['q'][j]\n            pred_mask[i_data+j,0:py1-py0, 0:px1-px0] = pred_mask_int[j, py0-qy0:py1-qy0, px0-qx0:px1-qx0] # (pred_sz,pred_sz)\n        i_data += bs\n    \n    pred_mask = pred_mask.reshape(ds.num_h*ds.num_w, ds.pred_sz, ds.pred_sz).reshape(ds.num_h, ds.num_w, ds.pred_sz, ds.pred_sz)\n    pred_mask = pred_mask.transpose(0,2,1,3).reshape(ds.num_h*ds.pred_sz, ds.num_w*ds.pred_sz)\n    pred_mask = pred_mask[:ds.h,:ds.w] # back to the original slide size\n    non_zero_ratio = (pred_mask).sum() / (ds.h*ds.w)\n    print('non_zero_ratio = {:.4f}'.format(non_zero_ratio))\n    return pred_mask,ds.h,ds.w\n\ndef get_rle(y_preds, h,w):\n    rle = mask2rle(y_preds, shape=(h,w), small_mask_threshold=config['small_mask_threshold'])\n    return rle","metadata":{"papermill":{"duration":0.048072,"end_time":"2021-03-31T10:38:09.171422","exception":false,"start_time":"2021-03-31T10:38:09.12335","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2022-04-27T09:33:55.863643Z","iopub.execute_input":"2022-04-27T09:33:55.863973Z","iopub.status.idle":"2022-04-27T09:33:55.884482Z","shell.execute_reply.started":"2022-04-27T09:33:55.863945Z","shell.execute_reply":"2022-04-27T09:33:55.883658Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%%time\n\nfor idx in range(len(sub_df)): \n    print('idx = ', idx)\n    pred_mask,h,w = get_pred_mask(idx, sub_df, model)\n    rle = get_rle(pred_mask,h,w)\n    sub_df.loc[idx,'predicted'] = rle","metadata":{"papermill":{"duration":1850.195536,"end_time":"2021-03-31T11:08:59.383643","exception":false,"start_time":"2021-03-31T10:38:09.188107","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2022-04-27T09:34:21.759862Z","iopub.execute_input":"2022-04-27T09:34:21.760293Z","iopub.status.idle":"2022-04-27T09:38:01.936042Z","shell.execute_reply.started":"2022-04-27T09:34:21.760253Z","shell.execute_reply":"2022-04-27T09:38:01.935111Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Submission","metadata":{"papermill":{"duration":0.01885,"end_time":"2021-03-31T11:08:59.422121","exception":false,"start_time":"2021-03-31T11:08:59.403271","status":"completed"},"tags":[]}},{"cell_type":"code","source":"sub_df.to_csv('submission.csv', index=False)","metadata":{"papermill":{"duration":0.288472,"end_time":"2021-03-31T11:08:59.729891","exception":false,"start_time":"2021-03-31T11:08:59.441419","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2022-04-27T09:38:01.937765Z","iopub.execute_input":"2022-04-27T09:38:01.938255Z","iopub.status.idle":"2022-04-27T09:38:02.006293Z","shell.execute_reply.started":"2022-04-27T09:38:01.938216Z","shell.execute_reply":"2022-04-27T09:38:02.005573Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sub_df","metadata":{"papermill":{"duration":0.043112,"end_time":"2021-03-31T11:08:59.792271","exception":false,"start_time":"2021-03-31T11:08:59.749159","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2022-04-27T09:38:02.008146Z","iopub.execute_input":"2022-04-27T09:38:02.009173Z","iopub.status.idle":"2022-04-27T09:38:02.029643Z","shell.execute_reply.started":"2022-04-27T09:38:02.009134Z","shell.execute_reply":"2022-04-27T09:38:02.028806Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"papermill":{"duration":0.019351,"end_time":"2021-03-31T11:08:59.831375","exception":false,"start_time":"2021-03-31T11:08:59.812024","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}