{"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":"code","source":"! pip install segmentation-models-pytorch\n\nfrom skimage import io, filters, transform \nimport tifffile as tiff\nimport albumentations as A\n \nimport os\nimport numpy as np\nimport pandas as pd\n\nimport torch\nimport torch.nn as nn\n\nimport segmentation_models_pytorch as smp","metadata":{"papermill":{"duration":23.756017,"end_time":"2022-07-23T11:15:09.824927","exception":false,"start_time":"2022-07-23T11:14:46.06891","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2022-07-25T10:14:13.589439Z","iopub.execute_input":"2022-07-25T10:14:13.589778Z","iopub.status.idle":"2022-07-25T10:14:37.212853Z","shell.execute_reply.started":"2022-07-25T10:14:13.589699Z","shell.execute_reply":"2022-07-25T10:14:37.211780Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class config:\n    IMAGE_SIZE = 768\n    TRAIN_BATCH_SIZE = 4\n    VALID_BATCH_SIZE = 2*TRAIN_BATCH_SIZE\n    EPOCHS = 21\n    DEVICE = \"cuda\"\n    OUTPUT = \"/hubmap/\"\n    MODEL_PATH = \"nvidia/segformer-b0-finetuned-cityscapes-768-768\"\n    FOLDS = 5\n    LR = 8e-5\n    \n#     MEAN =  [0.78036435, 0.75635034, 0.77327976]\n#     STD = [0.24925208, 0.26279064, 0.258655 ] ","metadata":{"papermill":{"duration":0.01455,"end_time":"2022-07-23T11:15:09.845044","exception":false,"start_time":"2022-07-23T11:15:09.830494","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2022-07-25T10:14:37.215426Z","iopub.execute_input":"2022-07-25T10:14:37.216321Z","iopub.status.idle":"2022-07-25T10:14:37.224046Z","shell.execute_reply.started":"2022-07-25T10:14:37.216267Z","shell.execute_reply":"2022-07-25T10:14:37.220810Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class HubDataset(torch.utils.data.Dataset):\n    def __init__(self,image_path,mask_path, augmentations=None):\n        self.image_path = image_path\n        self.mask_path = mask_path\n        self.augmentations = augmentations\n        \n    def __len__(self):\n        return len(self.image_path)\n    \n    def __getitem__(self,item):\n        \n        image = tiff.imread(self.image_path[item])\n        mask = io.imread(self.mask_path[item])\n        mask = mask.reshape(mask.shape[0],mask.shape[1],1)\n        \n        \n        ## resize\n        image = transform.resize(image, (config.IMAGE_SIZE, config.IMAGE_SIZE, 3))\n        mask = transform.resize(mask, (config.IMAGE_SIZE, config.IMAGE_SIZE, 1))\n        \n        image = image - np.min(image)\n        image = image / np.max(image)\n        \n        if self.augmentations is not None:\n            augmented = self.augmentations(image=image, mask=mask)\n            image = augmented[\"image\"]\n            mask = augmented[\"mask\"]    \n        image = np.transpose(image, (2, 0, 1)).astype(np.float32)\n        mask = np.transpose(mask, (2, 0, 1)).astype(np.float32)\n        \n        return {\n            \"image\": torch.tensor(image, dtype=torch.float),\n            \"mask\" : torch.tensor(mask, dtype=torch.float),\n        }","metadata":{"papermill":{"duration":0.018553,"end_time":"2022-07-23T11:15:09.86919","exception":false,"start_time":"2022-07-23T11:15:09.850637","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2022-07-25T10:14:37.226097Z","iopub.execute_input":"2022-07-25T10:14:37.227007Z","iopub.status.idle":"2022-07-25T10:14:37.238912Z","shell.execute_reply.started":"2022-07-25T10:14:37.226969Z","shell.execute_reply":"2022-07-25T10:14:37.238016Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def dice_metric(_mask1,_mask2):\n    \n    batch_size = _mask1.shape[0]\n    dice_total = 0.0\n    \n    for idx in range(batch_size):\n        mask1 = _mask1[idx].reshape(_mask1[idx].shape[1],_mask1[idx].shape[2]).cpu().numpy()\n        mask2 = _mask2[idx].reshape(_mask2[idx].shape[1],_mask2[idx].shape[2]).cpu().numpy()\n        intersect = np.sum(mask1*mask2)\n        fsum = np.sum(mask1)\n        ssum = np.sum(mask2)\n        eps = 1e-7 ##  for empty masks the numerator should not be divivded by zero\n        dice = (2 * intersect + eps) / (fsum + ssum + eps)\n        dice = np.mean(dice)\n        \n        dice_total += dice\n        \n    final_dice = dice_total/batch_size\n    final_dice = round(final_dice, 4)  # for easy reading till 4 decimal places\n    return final_dice  ","metadata":{"papermill":{"duration":0.015113,"end_time":"2022-07-23T11:15:09.8894","exception":false,"start_time":"2022-07-23T11:15:09.874287","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2022-07-25T10:14:37.242510Z","iopub.execute_input":"2022-07-25T10:14:37.243279Z","iopub.status.idle":"2022-07-25T10:14:37.251703Z","shell.execute_reply.started":"2022-07-25T10:14:37.243236Z","shell.execute_reply":"2022-07-25T10:14:37.250736Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import torch\nimport torch.nn as nn\n\nJaccardLoss = smp.losses.JaccardLoss(mode='binary',smooth=1.0)\nDiceLoss = smp.losses.DiceLoss(mode='binary', smooth=1.0)\nFocalLoss = smp.losses.FocalLoss(mode=\"binary\")\nBCELoss     = smp.losses.SoftBCEWithLogitsLoss()\nLovaszLoss  = smp.losses.LovaszLoss(mode='binary', per_image=False)\nTverskyLoss = smp.losses.TverskyLoss(mode='binary', log_loss=False)\n\ndef criterion(y_pred, y_true):\n    return DiceLoss(y_pred, y_true)\n\nscaler = torch.cuda.amp.GradScaler()\n\ndef train(model,train_loader,device,optimizer):\n    model.train()\n    running_train_loss = 0.0\n    for data in train_loader:\n        inputs = data['image']\n        masks = data['mask']\n\n        ## CUDA\n        inputs = inputs.to(device, dtype=torch.float)\n        masks = masks.to(device, dtype=torch.float)\n\n        ## forward \n        with torch.cuda.amp.autocast():\n            outputs = model(inputs,)\n            loss = criterion(outputs, masks)\n\n        optimizer.zero_grad()\n        scaler.scale(loss).backward()\n        scaler.step(optimizer)\n        scaler.update()\n\n        running_train_loss +=loss.item()\n        \n    train_loss_value = running_train_loss/len(train_loader)\n    print(f'train custom Loss is {train_loss_value}')\n\n@torch.no_grad()    \ndef evaluation(model,valid_loader,device,optimizer):\n    model.eval()\n    running_dice_score = 0.0\n    running_val_loss = 0.0\n    for data in valid_loader:\n        inputs = data['image']\n        masks = data['mask']\n        \n        inputs = inputs.to(device, dtype=torch.float)\n        masks = masks.to(device, dtype=torch.float)\n\n        output = model(inputs,)\n        running_val_loss +=  criterion(output, masks)\n        \n        output = torch.sigmoid(output)\n        running_dice_score += dice_metric(masks, output)\n\n    val_loss = running_val_loss/len(valid_loader) \n    dice_score = running_dice_score/len(valid_loader)\n        \n    print(f'valid custom Loss is {val_loss}')\n        \n    return dice_score","metadata":{"papermill":{"duration":0.123821,"end_time":"2022-07-23T11:15:10.018165","exception":false,"start_time":"2022-07-23T11:15:09.894344","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2022-07-25T10:14:37.253402Z","iopub.execute_input":"2022-07-25T10:14:37.254242Z","iopub.status.idle":"2022-07-25T10:14:37.331710Z","shell.execute_reply.started":"2022-07-25T10:14:37.254205Z","shell.execute_reply":"2022-07-25T10:14:37.330631Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import torch\nimport torch.nn as nn\nimport segmentation_models_pytorch as smp\n\nfrom transformers import SegformerForSemanticSegmentation\n\nclass HubmapModel(nn.Module):\n    def __init__(self):\n        super(HubmapModel, self).__init__()\n#         configuration = SegformerConfig.from_pretrained(\"nvidia/segformer-b0-finetuned-ade-512-512\")\n#         configuration.num_labels = 1 ## set output as 1 \n#         self.model = SegformerForSemanticSegmentation(config=configuration)\n\n        self.model = SegformerForSemanticSegmentation.from_pretrained(config.MODEL_PATH,\n                                                         num_labels=1,ignore_mismatched_sizes=True)\n    \n    def forward(self, image):\n        img_segs = self.model(image)\n    \n        upsampled_logits = nn.functional.interpolate(img_segs.logits,\n#                 size=(image.shape[0],1,image.shape[2],image.shape[3]), # (height, width)\n                scale_factor=4,\n                mode='nearest',\n                )\n#         print(upsampled_logits.shape)\n        return upsampled_logits\n\n\n# def HubmapModel():\n\n#     model = smp.Unet(encoder_name=\"efficientnet-b7\", \n#         encoder_weights=\"imagenet\", \n#         in_channels=3, \n#         classes=1).to(\"cuda\")\n    \n#     return model","metadata":{"papermill":{"duration":0.728612,"end_time":"2022-07-23T11:15:10.755272","exception":false,"start_time":"2022-07-23T11:15:10.02666","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2022-07-25T10:14:37.333509Z","iopub.execute_input":"2022-07-25T10:14:37.334247Z","iopub.status.idle":"2022-07-25T10:14:37.886716Z","shell.execute_reply.started":"2022-07-25T10:14:37.334208Z","shell.execute_reply":"2022-07-25T10:14:37.885776Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## MAIN","metadata":{"papermill":{"duration":0.007603,"end_time":"2022-07-23T11:15:10.77147","exception":false,"start_time":"2022-07-23T11:15:10.763867","status":"completed"},"tags":[]}},{"cell_type":"code","source":"df = pd.read_csv(\"../input/hubmap-folds/train_unsplit_data.csv\")","metadata":{"papermill":{"duration":0.402736,"end_time":"2022-07-23T11:15:11.182085","exception":false,"start_time":"2022-07-23T11:15:10.779349","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2022-07-25T10:14:37.888987Z","iopub.execute_input":"2022-07-25T10:14:37.889528Z","iopub.status.idle":"2022-07-25T10:14:38.207196Z","shell.execute_reply.started":"2022-07-25T10:14:37.889481Z","shell.execute_reply":"2022-07-25T10:14:38.206228Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# from sklearn import model_selection\n# df_train, df_valid = model_selection.train_test_split(df, test_size=0.3,)","metadata":{"papermill":{"duration":0.019011,"end_time":"2022-07-23T11:15:11.21037","exception":false,"start_time":"2022-07-23T11:15:11.191359","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2022-07-25T10:14:38.209110Z","iopub.execute_input":"2022-07-25T10:14:38.209728Z","iopub.status.idle":"2022-07-25T10:14:38.214290Z","shell.execute_reply.started":"2022-07-25T10:14:38.209690Z","shell.execute_reply":"2022-07-25T10:14:38.213204Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for fold in {1}:\n    best_score = 0.0\n\n    model = HubmapModel()\n    model.to(\"cuda\")\n    \n    df_train = df[df.fold != fold].reset_index(drop=True)\n    df_valid = df[df.fold == fold].reset_index(drop=True)\n\n    df_train = df_train.drop(columns = 'fold')\n    df_valid = df_valid.drop(columns = 'fold')\n\n    train_ids = df_train.id.values.tolist()\n    valid_ids = df_valid.id.values.tolist()\n\n    train_images = [os.path.join(\"../input/hubmap-organ-segmentation/train_images\",str(i) + \".tiff\") for i in train_ids]\n    train_masks =  [os.path.join(\"../input/hubmap-hpa-2022-maskdataset/hubmap_2022_MaskDataset\",str(i) + \".png\") for i in train_ids]\n\n    valid_images = [os.path.join(\"../input/hubmap-organ-segmentation/train_images\",str(i) + \".tiff\") for i in valid_ids]\n    valid_masks =  [os.path.join(\"../input/hubmap-hpa-2022-maskdataset/hubmap_2022_MaskDataset\",str(i) + \".png\") for i in valid_ids]\n\n    train_dataset = HubDataset(image_path=train_images,mask_path=train_masks)\n    train_loader = torch.utils.data.DataLoader(train_dataset,batch_size=config.TRAIN_BATCH_SIZE,shuffle=True,pin_memory=True) \n    valid_dataset = HubDataset(image_path=valid_images, mask_path=valid_masks)\n    valid_loader = torch.utils.data.DataLoader(valid_dataset,batch_size=config.VALID_BATCH_SIZE,shuffle=False,pin_memory=True) \n\n    optimizer = torch.optim.Adam(model.parameters(),lr=config.LR,)\n    scheduler = torch.optim.lr_scheduler.ExponentialLR(optimizer, gamma=0.8, verbose=True)\n\n    print(f'============================== FOLD -- {fold} ==============================')\n\n    for epoch in range(config.EPOCHS):\n        print(f'==================== Epoch -- {epoch} ====================')\n        train(model=model,train_loader=train_loader,device=config.DEVICE,optimizer=optimizer)\n        scheduler.step()\n        dice_score = evaluation(model=model,valid_loader=valid_loader,device=config.DEVICE,optimizer=optimizer)\n\n        print(f'validation DICE Metric={dice_score}')\n        \n        if dice_score > best_score:\n            best_score = dice_score\n            torch.save(model.state_dict(),'model-'+str(fold) +'.pth')\n","metadata":{"papermill":{"duration":10585.369433,"end_time":"2022-07-23T14:11:36.588136","exception":false,"start_time":"2022-07-23T11:15:11.218703","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2022-07-25T10:14:38.216530Z","iopub.execute_input":"2022-07-25T10:14:38.217120Z"},"trusted":true},"execution_count":null,"outputs":[]}]}