{"cells":[{"metadata":{"_kg_hide-output":true,"trusted":true},"cell_type":"code","source":"!pip install segmentation_models_pytorch","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"%%time\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\nimport os\nimport os\nimport cv2\nimport numpy as np\nimport pandas as pd\nfrom torch.utils.data import TensorDataset, DataLoader, Dataset\nfrom albumentations import *\nimport segmentation_models_pytorch as smp\nfrom albumentations.pytorch import ToTensor\nimport torch\nfrom tqdm.auto import tqdm\nimport matplotlib.pyplot as plt","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"DEVICE = ('cuda' if torch.cuda.is_available() else 'cpu')","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# parameters"},{"metadata":{"trusted":true},"cell_type":"code","source":"class config:\n    backbone = 'efficientnet-b4'\n    ACTIVATION = 'sigmoid'\n    ENCODER_WEIGHTS = 'imagenet'\n    \n    lr=5e-4\n    epochs= 50\n    batch_size=8\n#     T_max=500\n    im_size=256\n    num_workers=4\n    \n#     nfolds = 4\n#     fold = 0\n    \n#     seed = 2020\n    \n    images_path = f'../input/{im_size}{im_size}-pu/train/'\n    masks_path = f'../input/{im_size}{im_size}-pu/masks/'\n    \n    images_path2 = f'../input/{im_size}{im_size}-pu/2train/'\n    masks_path2 = f'../input/{im_size}{im_size}-pu/2masks/'\n    \n    images_path3 = f'../input/{im_size}{im_size}-pu/3train/'\n    masks_path3 = f'../input/{im_size}{im_size}-pu/3masks/'","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# data (augment)"},{"metadata":{"trusted":true},"cell_type":"code","source":"def get_aug(p=1.0):\n    return Compose([\n        HorizontalFlip(),\n        VerticalFlip(),\n        RandomRotate90(),\n        ShiftScaleRotate(shift_limit=0.0625, scale_limit=0.2, rotate_limit=15, p=0.9, \n                         border_mode=cv2.BORDER_REFLECT),\n        OneOf([\n            OpticalDistortion(p=0.3),\n            GridDistortion(p=.1),\n            IAAPiecewiseAffine(p=0.3),\n        ], p=0.3),\n        OneOf([\n            HueSaturationValue(10,15,10),\n            CLAHE(clip_limit=2),\n            RandomBrightnessContrast(),            \n        ], p=0.4),\n    ], p=p)\n\nmean = np.array([0.65459856,0.48386562,0.69428385])\nstd = np.array([0.15167958,0.23584107,0.13146145])\n\ndef img2tensor(img,dtype:np.dtype=np.float32):\n    if img.ndim==2 : img = np.expand_dims(img,2)  \n    img = np.transpose(img,(2,0,1))\n    return torch.from_numpy(img.astype(dtype, copy=False))\n\nclass HuBMAPDataset(Dataset):\n    def __init__(self, ids, transforms=None):\n        self.ids = ids\n        \n        self.transforms = transforms\n        \n    def __getitem__(self, idx):\n        path = self.ids[idx]\n        \n        if path[19] == 't':\n            img = cv2.cvtColor(cv2.imread(path), cv2.COLOR_BGR2RGB)\n            mask = cv2.imread(os.path.join(path[:19]+'masks/'+path[25:]),cv2.IMREAD_GRAYSCALE)\n            \n        else:\n            img = cv2.cvtColor(cv2.imread(path), cv2.COLOR_BGR2RGB)\n            mask = cv2.imread(os.path.join(path[:20]+'masks/'+path[26:]),cv2.IMREAD_GRAYSCALE)\n    \n        if self.transforms:\n            augmented = self.transforms(image=img, mask=mask)\n            img = augmented['image']\n            mask = augmented['mask']\n        \n#         print(img.shape, mask.shape)\n        return img2tensor((img/255.0 - mean)/std),img2tensor(mask)\n\n    def __len__(self):\n        return len(self.ids)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"data = os.listdir(config.images_path)#[:100]\ntrain_lsit = list(set([row.split(\"_\")[0] for row in data]))\ntrain_idx = [row for row in data if row.split(\"_\")[0] in train_lsit[:-2]]\nvalid_idx = [row for row in data if row.split(\"_\")[0] not in train_lsit[:-2]]\nlen(train_idx), len(valid_idx)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"data2 = os.listdir(config.images_path2)#[:100]\ntrain_lsit2 = list(set([row.split(\"_\")[0] for row in data2]))\ntrain_idx2 = [row for row in data2 if row.split(\"_\")[0] in train_lsit2[:-2]]\nvalid_idx2 = [row for row in data2 if row.split(\"_\")[0] not in train_lsit2[:-2]]\nlen(train_idx2), len(valid_idx2)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"data3 = os.listdir(config.images_path3)#[:100]\ntrain_lsit3 = list(set([row.split(\"_\")[0] for row in data3]))\ntrain_idx3 = [row for row in data3 if row.split(\"_\")[0] in train_lsit3[:-2]]\nvalid_idx3 = [row for row in data3 if row.split(\"_\")[0] not in train_lsit3[:-2]]\nlen(train_idx3), len(valid_idx3)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# train_idx.extend(train_idx2)\n# train_idx.extend(train_idx3)\nlen(train_idx)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# valid_idx.extend(valid_idx2)\n# valid_idx.extend(valid_idx3)\nlen(valid_idx)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"dataset"},{"metadata":{"trusted":true},"cell_type":"code","source":"train_datasets = HuBMAPDataset(train_idx, transforms= get_aug())\nvalid_datasets = HuBMAPDataset(valid_idx)\ntrain_loader = DataLoader(train_datasets, batch_size=config.batch_size, shuffle=True, num_workers=config.num_workers)\nvalid_loader = DataLoader(valid_datasets, batch_size=config.batch_size, shuffle=False, num_workers=config.num_workers)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# helper function for data visualization\nds = HuBMAPDataset(train_idx[:40],transforms= None)\ndl = DataLoader(ds,batch_size=40,shuffle=False,num_workers=config.num_workers)\nimgs,masks = next(iter(dl))\n\nplt.figure(figsize=(16,16))\nfor i,(img,mask) in enumerate(zip(imgs,masks)):\n    img = ((img.permute(1,2,0)*std + mean)*255.0).numpy().astype(np.uint8)\n#     img = img.permute(1,2,0).numpy().astype(np.uint8)\n    plt.subplot(8,8,i+1)\n    plt.imshow(img,vmin=0,vmax=255)\n    plt.imshow(mask.squeeze().numpy(), alpha=0.3)\n    plt.axis('off')\n    plt.subplots_adjust(wspace=None, hspace=None)\n    \ndel ds,dl,imgs,masks","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Model"},{"metadata":{},"cell_type":"markdown","source":"https://segmentation-modelspytorch.readthedocs.io/en/latest/docs/api.html#unet"},{"metadata":{"trusted":true},"cell_type":"code","source":"model = smp.Unet(\n    config.backbone, \n    encoder_weights=config.ENCODER_WEIGHTS, \n    in_channels=3,\n    classes=1, \n    activation=config.ACTIVATION,\n    decoder_use_batchnorm=False\n)\noptimizer = torch.optim.AdamW(model.parameters(),lr=config.lr)\n\nloss_fn = smp.utils.losses.DiceLoss() # smp.utils.losses.BCEWithLogitsLoss()\n\n#metric = [smp.utils.losses.DiceLoss()]\nmetrics = [\n    smp.utils.metrics.IoU(threshold=0.5),\n]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_epoch = smp.utils.train.TrainEpoch(\n    model, \n    loss=loss_fn, \n    metrics=metrics, \n    optimizer=optimizer,\n    device=DEVICE,\n    verbose=True,\n)\n\nvalid_epoch = smp.utils.train.ValidEpoch(\n    model, \n    loss=loss_fn, \n    metrics=metrics, \n    device=DEVICE,\n    verbose=True,\n)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def savelogs(logs, name):\n    with open(f'{name}.txt', 'a') as f:\n        for k, v in logs.items():\n            f.write(f'{k} {v}')\n        f.write('\\n')","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Train"},{"metadata":{"trusted":true},"cell_type":"code","source":"%%time\n\npatience = 0\nmax_score = 1e5\nlosses = {}\nious = {}\nlosses['train'] = []\nlosses['valid'] = []\nious['train'] = []\nious['valid'] = []\n\nfor i in range(0, config.epochs):\n\n    print('\\nEpoch: {}'.format(i))\n    train_logs = train_epoch.run(train_loader)\n    valid_logs = valid_epoch.run(valid_loader)\n    \n    savelogs(train_logs, f'train_logs')\n    savelogs(valid_logs, f'valid_logs')\n    \n    losses['train'].append(train_logs['dice_loss'])\n    losses['valid'].append(valid_logs['dice_loss'])\n    \n    ious['train'].append(train_logs['iou_score'])\n    ious['valid'].append(valid_logs['iou_score'])\n    \n    patience += 1\n    #break\n    # do something (save model, change lr, etc.)\n    # val loss\n    if max_score > valid_logs['dice_loss']:\n        max_score = valid_logs['dice_loss']\n        torch.save(model, 'best.pth')\n        patience = 0\n        print('get the best score: ', 1- max_score)\n        print('Model saved!')\n        \n    if i == 15:\n        optimizer.param_groups[0]['lr'] = 1e-4\n        print('Decrease decoder learning rate to 1e-5!')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# PLOT\ndef plot(scores, name):\n    plt.figure(figsize=(15,5))\n    plt.plot(range(len(scores[\"train\"])), scores[\"train\"], label=f'train {name}')\n    plt.plot(range(len(scores[\"train\"])), scores[\"valid\"], label=f'val {name}')\n    plt.title(f'{name} plot'); plt.xlabel('Epoch'); plt.ylabel(f'{name}');\n    plt.legend(); \n    plt.show()\n\nplot(losses, \"loss\")\nplot(ious, \"iou\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]}],"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":4,"nbformat_minor":4}