{"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":"  --- updated data, old models ---  \n* v01(old v53) : 10_01 with fold0,1,2,3, LB=(old 0.874)(th=0.5, pad=256, tta2) -> Timeout Error  \n* v02(old v53) : rasterIO, 10_01 with fold0, LB=(old ?)(th=0.5, pad=256, tta2) -> Exceeded Error  \n* v03(old v53) : rasterIO, 10_01 with fold0,1,2,3, LB=(old 0.874)(th=0.5, pad=256, tta2)  \n* v04 : rasterIO, 10_01 with fold0, LB= (th=0.5, pad=64, no tta)  \n* v05 : debug  \n* v06 : re-upload the weights, rasterIO, 10_01 with fold0, LB= (th=0.5, pad=64, no tta)  \n* v09 : debug, sample submission -> OK  \n* v10 : rasterIO, 10_01 with fold0, LB= (th=0.5, pad=0, no tta)  \n* v11 : bug-corrected, rasterIO, 10_01 with fold0, LB= (th=0.5, pad=0, no tta)  \n  \n  \n  --- OK ---  \n* v14 : better approach, rasterIO, 10_01 with fold0, LB=0.908 (th=0.5, input_sz=256, pad=0, no tta)  \n* v18 : better approach, rasterIO, 10_01 with fold0123, LB= (th=0.5, input_sz=320, pad=0, tta2) <-- GPU OOM  \n* v17 : better approach, rasterIO, 10_01 with fold0123456, LB=0.920 (th=0.5, input_sz=320, pad=0, tta4)  \n* v21 : better approach, rasterIO, 10_01 with fold0123, LB=0.924 (th=0.5, input_sz=320, pad=64, tta2)  \n* v22 : better approach, rasterIO, 10_01 with fold0123, LB=0.923 (th=0.5, input_sz=320, pad=128, tta2)  \n* v23 : better approach, rasterIO, 10_01 with fold0123, LB=0.924 (th=0.5, input_sz=320, pad=256, tta2)  \n* v24 : better approach, rasterIO, 10_01 with fold0123456, LB=0.923 (th=0.5, input_sz=320, pad=256, tta2)  \n* v25 : better approach, rasterIO, 10_01 with fold0123, LB= (th=0.5, input_sz=320, pad=256, tta4) -> TLO  \n* v26 : better approach, rasterIO, 10_01 with fold0123, LB=0.925 (th=0.5, input_sz=320, pad=256, tta3)  \n  \n  \n  --- trained with new data ---  \n* v28 : new_01_01 : baseline with new kaggle dataset, unet seresnext101, more hue-sat(0.3), classification head, deepsupervision, 320x320, coarse dropout corrected, 1024x1024 tiling, 5folds, data balance with (00_01, 00_02), group by patient number, balanced sampling, aug(), cosine_annealing(1e-4to1e-6, 20epochs), CV=0.9354, LB=0.917(th=0.5, input_sz=320, pad=256, tta2)  \n* v29 : new_01_01 : baseline with new kaggle dataset, unet seresnext101, more hue-sat(0.3), classification head, deepsupervision, 320x320, coarse dropout corrected, 1024x1024 tiling, 5folds, data balance with (00_01, 00_02), group by patient number, balanced sampling, aug(), cosine_annealing(1e-4to1e-6, 20epochs), CV=0.9354, LB=0.921(th=0.5, input_sz=320, pad=64, tta4)  \n* v30 : 01_02 : manually specified val_patient_numbers (4folds), baseline with new kaggle dataset, unet seresnext101, more hue-sat(0.3), classification head, deepsupervision, 320x320, coarse dropout corrected, 1024x1024 tiling, data balance with (00_02, 00_04), group by patient number, balanced sampling, aug(), cosine_annealing(1e-4to1e-6, 20epochs), CV=0.9331, LB=0.921(th=0.5, input_sz=320, pad=256, tta3)  \n* v31 : 01_04 : unet seresnext50, manually specified val_patient_numbers (4folds), baseline with new kaggle dataset, more hue-sat(0.3), classification head, deepsupervision, 320x320, coarse dropout corrected, 1024x1024 tiling, data balance with (00_02, 00_04), group by patient number, balanced sampling, aug(), cosine_annealing(1e-4to1e-6, 20epochs), CV=0.9327, LB=0.921(th=0.5, input_sz=320, pad=256, tta3)  \n* v33 : 03_01 : pseudo-label for train+test(00_05,00_06), manually specified val_patient_numbers (4folds), baseline with new kaggle dataset, unet seresnext101, more hue-sat(0.3), classification head, deepsupervision, 320x320, coarse dropout corrected, 1024x1024 tiling, data balance, group by patient number, balanced sampling, aug(), cosine_annealing(1e-4to1e-6, 20epochs), CV=0.9779, LB=0.921(th=0.5, input_sz=320, pad=256, tta3)  \n* v35 : v30(LB0.921), create sub for LB probing  \n* v36 : v26(LB0.925), create sub for LB probing  \n* v37 : v33(LB0.921), create sub for LB probing  \n* v38 : 01_07 : focal loss, manually specified val_patient_numbers (4folds), baseline with new kaggle dataset, unet seresnext101, more hue-sat(0.3), classification head, deepsupervision, 320x320, coarse dropout corrected, 1024x1024 tiling, data balance with (00_02, 00_04), group by patient number, balanced sampling, aug(), cosine_annealing(1e-4to1e-6, 20epochs), CV=0.9326, LB=0.921(th=0.5, input_sz=320, pad=256, tta3)  \n* v39 : v38(LB=), create sub for LB probing  \n* v41 : 03_02 : pseudo-label (test(00_05,00_06), external(00,10,00_11), dataset_a_dib(00_08,00_09)), manually specified val_patient_numbers (4folds), baseline with new kaggle dataset, unet seresnext101, more hue-sat(0.3), classification head, deepsupervision, 320x320, coarse dropout corrected, 1024x1024 tiling, data balance, group by patient number, balanced sampling, aug(), cosine_annealing(1e-4to1e-6, 20epochs), CV=0.9385  (fold2 looks not good, should be removed ?), LB=0.922(th=0.5, input_sz=320, pad=256, tta3)  \n* v42 : fold013 of 03_02 : pseudo-label (test(00_05,00_06), external(00,10,00_11), dataset_a_dib(00_08,00_09)), manually specified val_patient_numbers (4folds), baseline with new kaggle dataset, unet seresnext101, more hue-sat(0.3), classification head, deepsupervision, 320x320, coarse dropout corrected, 1024x1024 tiling, data balance, group by patient number, balanced sampling, aug(), cosine_annealing(1e-4to1e-6, 20epochs), CV=0.9385  (fold2 looks not good, should be removed ?), LB=0.922(th=0.5, input_sz=320, pad=256, tta4)  \n* v43 : 03_03 : add Carno Chao's hand-labeling data (d488c759a), pseudo-label (test(00_05,00_06), external(00,10,00_11), dataset_a_dib(00_08,00_09)), manually specified val_patient_numbers (4folds), baseline with new kaggle dataset, unet seresnext101, more hue-sat(0.3), classification head, deepsupervision, 320x320, coarse dropout corrected, 1024x1024 tiling, data balance, group by patient number, balanced sampling, aug(), cosine_annealing(1e-4to1e-6, 20epochs), CV=0.9375* v41 : 03_02 : pseudo-label (test(00_05,00_06), external(00,10,00_11), dataset_a_dib(00_08,00_09)), manually specified val_patient_numbers (4folds), baseline with new kaggle dataset, unet seresnext101, more hue-sat(0.3), classification head, deepsupervision, 320x320, coarse dropout corrected, 1024x1024 tiling, data balance, group by patient number, balanced sampling, aug(), cosine_annealing(1e-4to1e-6, 20epochs), CV=0.9385  (fold2 looks not good, should be removed ?), LB=(th=0.5, input_sz=320, pad=256, tta3)  ","metadata":{"papermill":{"duration":0.01772,"end_time":"2021-03-31T10:37:28.865319","exception":false,"start_time":"2021-03-31T10:37:28.847599","status":"completed"},"tags":[]}},{"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":[],"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/',\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':128, #(64,64), #(256,256), #(128,128)\n    \n    'tta':3,\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":[],"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":[],"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":[],"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":[],"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":[],"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":[],"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":[],"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    \n# class SpatialAttention2d(nn.Module):\n#     def __init__(self, in_channel):\n#         super().__init__()\n#         self.squeeze = conv1x1(in_channel,1).apply(init_weight)\n#         self.sigmoid = nn.Sigmoid()\n        \n#     def forward(self, inputs):\n#         x = self.squeeze(inputs)\n#         x = self.sigmoid(x)\n#         return inputs * x\n    \n    \n# class GAB(nn.Module):\n#     def __init__(self, in_channel, reduction=4):\n#         super().__init__()\n#         self.global_avgpool = nn.AdaptiveAvgPool2d(1)\n#         self.conv1 = conv1x1(in_channel, in_channel//reduction).apply(init_weight)\n#         self.conv2 = conv1x1(in_channel//reduction, in_channel).apply(init_weight)\n#         self.relu  = nn.ReLU(True)\n#         self.sigmoid = nn.Sigmoid()\n        \n#     def forward(self, inputs):\n#         x = self.global_avgpool(inputs)\n#         x = self.relu(self.conv1(x))\n#         x = self.sigmoid(self.conv2(x))\n#         return inputs * x\n\n    \n# class scSEBlock2(nn.Module):\n#     def __init__(self, in_channel, reduction=4):\n#         super().__init__()\n#         self.cSE = GAB(in_channel, reduction)\n#         self.sSE = SpatialAttention2d(in_channel)\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 ResNet34 + CBAM + hypercolumns + deepsupervision\nclass UNET_RESNET34(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 = 'resnet34' #26M\n        resnet34 = pretrainedmodels.__dict__['resnet34'](num_classes=1000,pretrained=None)\n        if load_weights:\n            resnet34.load_state_dict(torch.load(f'../../../pretrainedmodels_weight/{model_name}.pth'))\n        self.conv1   = resnet34.conv1 #(*,3,h,w)->(*,64,h/2,w/2)\n        self.bn1     = resnet34.bn1\n        self.maxpool = resnet34.maxpool #->(*,64,h/4,w/4)\n        self.layer1  = resnet34.layer1 #->(*,64,h/4,w/4) \n        self.layer2  = resnet34.layer2 #->(*,128,h/8,w/8) \n        self.layer3  = resnet34.layer3 #->(*,256,h/16,w/16) \n        self.layer4  = resnet34.layer4 #->(*,512,h/32,w/32) \n        \n        #center\n        self.center  = CenterBlock(512,512) #->(*,512,h/32,w/32) \n        \n        #decoder\n        self.decoder4 = DecodeBlock(512+512,64, upsample=True) #->(*,64,h/16,w/16) \n        self.decoder3 = DecodeBlock(64+256,64, upsample=True) #->(*,64,h/8,w/8) \n        self.decoder2 = DecodeBlock(64+128,64,  upsample=True) #->(*,64,h/4,w/4) \n        self.decoder1 = DecodeBlock(64+64,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(512).apply(init_weight),\n            nn.Linear(512,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 = F.relu(self.bn1(self.conv1(inputs))) #->(*,64,h/2,w/2) \n        x0 = self.maxpool(x0) #->(*,64,h/4,w/4)\n        x1 = self.layer1(x0) #->(*,64,h/4,w/4)\n        x2 = self.layer2(x1) #->(*,128,h/8,w/8)\n        x3 = self.layer3(x2) #->(*,256,h/16,w/16)\n        x4 = self.layer4(x3) #->(*,512,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) #->(*,512,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        \n#U-Net SeResNext50 + CBAM + hypercolumns + deepsupervision\nclass UNET_SERESNEXT50(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_resnext50_32x4d' #26M\n        seresnext50 = pretrainedmodels.__dict__[model_name](pretrained=None)\n        if load_weights:\n            seresnext50.load_state_dict(torch.load(f'../../../pretrainedmodels_weight/{model_name}.pth'))\n        \n        self.encoder0 = nn.Sequential(\n            seresnext50.layer0.conv1, #(*,3,h,w)->(*,64,h/2,w/2)\n            seresnext50.layer0.bn1,\n            seresnext50.layer0.relu1,\n        )\n        self.encoder1 = nn.Sequential(\n            seresnext50.layer0.pool, #->(*,64,h/4,w/4)\n            seresnext50.layer1 #->(*,256,h/4,w/4)\n        )\n        self.encoder2 = seresnext50.layer2 #->(*,512,h/8,w/8)\n        self.encoder3 = seresnext50.layer3 #->(*,1024,h/16,w/16)\n        self.encoder4 = seresnext50.layer4 #->(*,2048,h/32,w/32)\n        \n        #center\n        self.center  = CenterBlock(2048,512) #->(*,512,h/32,w/32) 10,16\n        \n        #decoder\n        self.decoder4 = DecodeBlock(512+2048,64, upsample=True) #->(*,64,h/16,w/16) 20,32\n        self.decoder3 = DecodeBlock(64+1024,64, upsample=True) #->(*,64,h/8,w/8) 40,64\n        self.decoder2 = DecodeBlock(64+512,64,  upsample=True) #->(*,64,h/4,w/4) 80,128\n        self.decoder1 = DecodeBlock(64+256,64,   upsample=True) #->(*,64,h/2,w/2) 160,256\n        self.decoder0 = DecodeBlock(64,64, upsample=True) #->(*,64,h,w) 320,512\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) 160,256\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) 160,256\n        y0 = self.decoder0(y1) #->(*,64,h,w) 320,512\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) #->(*,4,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\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":[],"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":"#from models import build_model\n\nLOAD_LOCAL_WEIGHT_PATH_LIST = {}\nfor seed in config['split_seed_list']:\n    LOAD_LOCAL_WEIGHT_PATH_LIST[seed] = []\n    for fold in config['FOLD_LIST']:\n        LOAD_LOCAL_WEIGHT_PATH_LIST[seed].append(opj(config['model_path'],f'model_seed{seed}_fold{fold}_bestscore.pth'))\n        #LOAD_LOCAL_WEIGHT_PATH_LIST[seed].append(opj(config['model_path'],f'model_seed{seed}_fold{fold}_swa.pth'))\n\nmodel_list = {}\nfor seed in config['split_seed_list']:\n    model_list[seed] = []\n    for path in LOAD_LOCAL_WEIGHT_PATH_LIST[seed]:\n        print(\"Loading weights from %s\" % path)\n        \n        model = build_model(resolution=(None,None), #config['resolution'], \n                            deepsupervision=config['deepsupervision'], \n                            clfhead=config['clfhead'],\n                            load_weights=False).to(device)\n        \n        model.load_state_dict(torch.load(path))\n        model.eval()\n        model_list[seed].append(model) ","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":[],"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":[],"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":[],"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_list):\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        pred_mask_float = 0\n        for model in model_list[seed]:\n            with torch.no_grad():\n                if config['tta']>0:\n                    pred_mask_float += torch.sigmoid(model(img_patch.to(device, torch.float32, non_blocking=True))).detach().cpu().numpy()[:,0,:,:] #.squeeze()\n                if config['tta']>1:\n                    # h-flip\n                    _pred_mask_float = torch.sigmoid(model(img_patch.flip([-1]).to(device, torch.float32, non_blocking=True))).detach().cpu().numpy()[:,0,:,:] #.squeeze()\n                    pred_mask_float += _pred_mask_float[:,:,::-1]\n                if config['tta']>2:\n                    # v-flip\n                    _pred_mask_float = torch.sigmoid(model(img_patch.flip([-2]).to(device, torch.float32, non_blocking=True))).detach().cpu().numpy()[:,0,:,:] #.squeeze()\n                    pred_mask_float += _pred_mask_float[:,::-1,:]\n                if config['tta']>3:\n                    # h-v-flip\n                    _pred_mask_float = torch.sigmoid(model(img_patch.flip([-1,-2]).to(device, torch.float32, non_blocking=True))).detach().cpu().numpy()[:,0,:,:] #.squeeze()\n                    pred_mask_float += _pred_mask_float[:,::-1,::-1]\n        pred_mask_float = pred_mask_float / min(config['tta'],4) / len(model_list[seed]) # (bs,input_res,input_res)\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":[],"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_list)\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":[],"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":[],"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":[],"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":[]}]}