{"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":"# Libraries and setup","metadata":{}},{"cell_type":"code","source":"import pandas as pd\nimport numpy as np\nimport os\nimport cv2\nimport gc\nfrom PIL import Image\nimport matplotlib.pyplot as plt\nfrom tqdm import tqdm\nfrom tqdm.notebook import tqdm\nfrom datetime import datetime\nimport json,itertools\nfrom typing import Optional\nfrom glob import glob\nimport warnings\nwarnings.filterwarnings(\"ignore\")\nimport matplotlib.gridspec as gridspec\nimport matplotlib.patches as mpatches\nimport matplotlib as mpl\nfrom sklearn.model_selection import StratifiedKFold, KFold, StratifiedGroupKFold\nimport random\n\nfrom tensorflow import keras\nimport tensorflow as tf\nimport keras\nfrom keras import backend as K\nfrom keras.models import Model\nfrom keras.losses import binary_crossentropy\nfrom keras.callbacks import Callback, ModelCheckpoint, EarlyStopping\nfrom keras.models import load_model, save_model\nfrom matplotlib.patches import Rectangle","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-06-25T08:00:48.14076Z","iopub.execute_input":"2022-06-25T08:00:48.141085Z","iopub.status.idle":"2022-06-25T08:00:48.150284Z","shell.execute_reply.started":"2022-06-25T08:00:48.141042Z","shell.execute_reply":"2022-06-25T08:00:48.149232Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Reproducibility**","metadata":{}},{"cell_type":"code","source":"# Set random seeds\ndef set_seed(seed=0):\n    np.random.seed(seed)\n    random.seed(seed)\n    tf.random.set_seed(seed)\nset_seed(seed=42)","metadata":{"execution":{"iopub.status.busy":"2022-06-25T08:03:55.10366Z","iopub.execute_input":"2022-06-25T08:03:55.104229Z","iopub.status.idle":"2022-06-25T08:03:55.109725Z","shell.execute_reply.started":"2022-06-25T08:03:55.104168Z","shell.execute_reply":"2022-06-25T08:03:55.1087Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(f\"\\n... ACCELERATOR SETUP STARTING ...\\n\")\n\ntry:\n    TPU = tf.distribute.cluster_resolver.TPUClusterResolver()  \nexcept ValueError:\n    TPU = None\n\nif TPU:\n    print(f\"\\n... RUNNING ON TPU - {TPU.master()}...\")\n    tf.config.experimental_connect_to_cluster(TPU)\n    tf.tpu.experimental.initialize_tpu_system(TPU)\n    strategy = tf.distribute.experimental.TPUStrategy(TPU)\nelse:\n    print(f\"\\n... RUNNING ON CPU/GPU ...\")\n    strategy = tf.distribute.get_strategy() \n\nN_REPLICAS = strategy.num_replicas_in_sync\nprint(f\"... # OF REPLICAS: {N_REPLICAS} ...\\n\")\nprint(f\"\\n... ACCELERATOR SETUP COMPLTED ...\\n\")","metadata":{"execution":{"iopub.status.busy":"2022-06-21T16:47:03.088282Z","iopub.execute_input":"2022-06-21T16:47:03.088526Z","iopub.status.idle":"2022-06-21T16:47:03.104131Z","shell.execute_reply.started":"2022-06-21T16:47:03.0885Z","shell.execute_reply":"2022-06-21T16:47:03.103241Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Config**","metadata":{}},{"cell_type":"code","source":"BATCH_SIZE = 16\nEPOCHS = 30\nn_splits = 5\nfold_selected = 2   \nIMAGE_WIDTH = 288\nIMAGE_HEIGHT = 288","metadata":{"execution":{"iopub.status.busy":"2022-06-25T08:03:58.794257Z","iopub.execute_input":"2022-06-25T08:03:58.794511Z","iopub.status.idle":"2022-06-25T08:03:58.798816Z","shell.execute_reply.started":"2022-06-25T08:03:58.794482Z","shell.execute_reply":"2022-06-25T08:03:58.798024Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Data","metadata":{}},{"cell_type":"markdown","source":"To import dataset in kaggle click on + Add data in top right corner -> go to competitions and choose the uw-madison-gi-tract-image-segmentation datset","metadata":{}},{"cell_type":"code","source":"print(\"\\n... DATA ACCESS SETUP STARTED ...\\n\")\n\nDATA_DIR = \"/kaggle/input/uw-madison-gi-tract-image-segmentation\"\nsave_locally = None\nload_locally = None","metadata":{"execution":{"iopub.status.busy":"2022-06-25T08:15:03.780219Z","iopub.execute_input":"2022-06-25T08:15:03.780495Z","iopub.status.idle":"2022-06-25T08:15:03.78622Z","shell.execute_reply.started":"2022-06-25T08:15:03.780464Z","shell.execute_reply":"2022-06-25T08:15:03.785512Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Train set**","metadata":{}},{"cell_type":"code","source":"TRAIN_DIR = os.path.join(DATA_DIR, \"train\")\nTRAIN_CSV = os.path.join(DATA_DIR, \"train.csv\")\ntrain_df = pd.read_csv(TRAIN_CSV)\nprint(train_df.shape)\ntrain_df.head()","metadata":{"execution":{"iopub.status.busy":"2022-06-25T08:15:06.86178Z","iopub.execute_input":"2022-06-25T08:15:06.862231Z","iopub.status.idle":"2022-06-25T08:15:07.119242Z","shell.execute_reply.started":"2022-06-25T08:15:06.862192Z","shell.execute_reply":"2022-06-25T08:15:07.118585Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Test set**","metadata":{}},{"cell_type":"code","source":"TEST_CSV = os.path.join(DATA_DIR, 'sample_submission.csv')\ntest_df = pd.read_csv(TEST_CSV)\n\nif len(test_df)==0:\n    DEBUG=True\n    test_df = train_df[115488-300:]\n    testdf = train_df[115488-300:]\nelse:\n    DEBUG=False\n\nsubmission=test_df.copy()\ntest_df.head()","metadata":{"execution":{"iopub.status.busy":"2022-06-25T08:15:09.673316Z","iopub.execute_input":"2022-06-25T08:15:09.673593Z","iopub.status.idle":"2022-06-25T08:15:09.691226Z","shell.execute_reply.started":"2022-06-25T08:15:09.673557Z","shell.execute_reply":"2022-06-25T08:15:09.69059Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Preprocessing","metadata":{}},{"cell_type":"code","source":"def preprocessing(df, subset=\"train\"):\n    df[\"case\"] = df[\"id\"].apply(lambda x: int(x.split(\"_\")[0].replace(\"case\", \"\")))\n    df[\"day\"] = df[\"id\"].apply(lambda x: int(x.split(\"_\")[1].replace(\"day\", \"\")))\n    df[\"slice\"] = df[\"id\"].apply(lambda x: x.split(\"_\")[3])\n    if (subset==\"train\") or (DEBUG):\n        DIR=\"../input/uw-madison-gi-tract-image-segmentation/train\"\n    else:\n        DIR=\"../input/uw-madison-gi-tract-image-segmentation/test\"\n    \n    all_images = glob(os.path.join(DIR, \"**\", \"*.png\"), recursive=True)\n    x = all_images[0].rsplit(\"/\", 4)[0] \n\n    path_partial_list = []\n    for i in range(0, df.shape[0]):\n        path_partial_list.append(os.path.join(x,\n                              \"case\"+str(df[\"case\"].values[i]),\n                              \"case\"+str(df[\"case\"].values[i])+\"_\"+ \"day\"+str(df[\"day\"].values[i]),\n                              \"scans\",\n                              \"slice_\"+str(df[\"slice\"].values[i])))\n    df[\"path_partial\"] = path_partial_list\n    path_partial_list = []\n    for i in range(0, len(all_images)):\n        path_partial_list.append(str(all_images[i].rsplit(\"_\",4)[0]))\n\n    tmp_df = pd.DataFrame()\n    tmp_df['path_partial'] = path_partial_list\n    tmp_df['path'] = all_images\n\n    df = df.merge(tmp_df, on=\"path_partial\").drop(columns=[\"path_partial\"])\n    df[\"width\"] = df[\"path\"].apply(lambda x: int(x[:-4].rsplit(\"_\",4)[1]))\n    df[\"height\"] = df[\"path\"].apply(lambda x: int(x[:-4].rsplit(\"_\",4)[2]))\n    del x, path_partial_list, tmp_df\n    \n    return df","metadata":{"execution":{"iopub.status.busy":"2022-06-25T08:04:08.19893Z","iopub.execute_input":"2022-06-25T08:04:08.199203Z","iopub.status.idle":"2022-06-25T08:04:08.214642Z","shell.execute_reply.started":"2022-06-25T08:04:08.199171Z","shell.execute_reply":"2022-06-25T08:04:08.212657Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def restructure(df, subset=\"train\"):\n    # RESTRUCTURE  DATAFRAME\n    df_out = pd.DataFrame({'id': df['id'][::3]})\n\n    if subset==\"train\":\n        df_out['large_bowel'] = df['segmentation'][::3].values\n        df_out['small_bowel'] = df['segmentation'][1::3].values\n        df_out['stomach'] = df['segmentation'][2::3].values\n\n    df_out['path'] = df['path'][::3].values\n    df_out['case'] = df['case'][::3].values\n    df_out['day'] = df['day'][::3].values\n    df_out['slice'] = df['slice'][::3].values\n    df_out['width'] = df['width'][::3].values\n    df_out['height'] = df['height'][::3].values\n\n    df_out=df_out.reset_index(drop=True)\n    df_out=df_out.fillna('')\n    if subset==\"train\":\n        df_out['count'] = np.sum(df_out.iloc[:,1:4]!='',axis=1).values\n    \n    return df_out","metadata":{"execution":{"iopub.status.busy":"2022-06-25T08:04:12.62403Z","iopub.execute_input":"2022-06-25T08:04:12.624288Z","iopub.status.idle":"2022-06-25T08:04:12.633357Z","shell.execute_reply.started":"2022-06-25T08:04:12.624258Z","shell.execute_reply":"2022-06-25T08:04:12.63259Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df = preprocessing(train_df, subset=\"train\")\nprint(train_df.shape)\ntrain_df.head()","metadata":{"execution":{"iopub.status.busy":"2022-06-25T08:15:17.315969Z","iopub.execute_input":"2022-06-25T08:15:17.316224Z","iopub.status.idle":"2022-06-25T08:15:21.973609Z","shell.execute_reply.started":"2022-06-25T08:15:17.316196Z","shell.execute_reply":"2022-06-25T08:15:21.97287Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_df=preprocessing(test_df, subset=\"test\")\nprint(test_df.shape)\ntest_df.head()","metadata":{"execution":{"iopub.status.busy":"2022-06-25T08:15:25.790198Z","iopub.execute_input":"2022-06-25T08:15:25.79077Z","iopub.status.idle":"2022-06-25T08:15:26.753731Z","shell.execute_reply.started":"2022-06-25T08:15:25.790729Z","shell.execute_reply":"2022-06-25T08:15:26.752893Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df=restructure(train_df, subset=\"train\")\ntrain_df.head()","metadata":{"execution":{"iopub.status.busy":"2022-06-25T08:15:31.497572Z","iopub.execute_input":"2022-06-25T08:15:31.49803Z","iopub.status.idle":"2022-06-25T08:15:31.567517Z","shell.execute_reply.started":"2022-06-25T08:15:31.49799Z","shell.execute_reply":"2022-06-25T08:15:31.566698Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_df=restructure(test_df, subset=\"test\")\ntest_df.head()","metadata":{"execution":{"iopub.status.busy":"2022-06-25T08:04:25.723776Z","iopub.execute_input":"2022-06-25T08:04:25.724033Z","iopub.status.idle":"2022-06-25T08:04:25.744353Z","shell.execute_reply.started":"2022-06-25T08:04:25.723999Z","shell.execute_reply":"2022-06-25T08:04:25.74351Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Remove mislabeled training data\ntrain_df = train_df[(train_df['case']!=7)|(train_df['day']!=0)].reset_index(drop=True)\ntrain_df = train_df[(train_df['case']!=81)|(train_df['day']!=30)].reset_index(drop=True)","metadata":{"execution":{"iopub.status.busy":"2022-06-25T08:04:25.74561Z","iopub.execute_input":"2022-06-25T08:04:25.745838Z","iopub.status.idle":"2022-06-25T08:04:25.772805Z","shell.execute_reply.started":"2022-06-25T08:04:25.745806Z","shell.execute_reply":"2022-06-25T08:04:25.772129Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"testdf=preprocessing(testdf, subset=\"train\")\ntestdf=restructure(testdf, subset=\"train\")\ntestdf.head()","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Garbage collection\ngc.collect()","metadata":{"execution":{"iopub.status.busy":"2022-06-25T08:04:25.774067Z","iopub.execute_input":"2022-06-25T08:04:25.774315Z","iopub.status.idle":"2022-06-25T08:04:25.967065Z","shell.execute_reply.started":"2022-06-25T08:04:25.774283Z","shell.execute_reply":"2022-06-25T08:04:25.966228Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(train_df.shape, test_df.shape)","metadata":{"execution":{"iopub.status.busy":"2022-06-21T07:16:27.202857Z","iopub.execute_input":"2022-06-21T07:16:27.203188Z","iopub.status.idle":"2022-06-21T07:16:27.208247Z","shell.execute_reply.started":"2022-06-21T07:16:27.203148Z","shell.execute_reply":"2022-06-21T07:16:27.20755Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Helper functions","metadata":{}},{"cell_type":"code","source":"def rle_decode(mask_rle, shape, color=1):\n    '''\n    mask_rle: run-length as string formated (start length)\n    shape: (height,width) of array to return \n    Returns numpy array, 1 - mask, 0 - background\n    '''\n    s = np.array(mask_rle.split(), dtype=int)   \n    starts = s[0::2] - 1 # Every even value is the start, every odd value is the \"run\" length\n    lengths = s[1::2]\n    ends = starts + lengths\n    if len(shape)==3:\n        h, w, d = shape\n        img = np.zeros((h * w, d), dtype=np.float32)\n    else:\n        h, w = shape\n        img = np.zeros((h * w,), dtype=np.float32)\n    for lo, hi in zip(starts, ends):\n        img[lo : hi] = color    \n    return img.reshape(shape)    ","metadata":{"execution":{"iopub.status.busy":"2022-06-25T08:04:29.296809Z","iopub.execute_input":"2022-06-25T08:04:29.297062Z","iopub.status.idle":"2022-06-25T08:04:29.303935Z","shell.execute_reply.started":"2022-06-25T08:04:29.297033Z","shell.execute_reply":"2022-06-25T08:04:29.30322Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#run length encoding\ndef rle_encode(img):\n    '''\n    img: numpy array, 1 - mask, 0 - background\n    Returns run length as string formated\n    '''\n    pixels = img.flatten()\n    pixels = np.concatenate([[0], pixels, [0]])\n    runs = np.where(pixels[1:] != pixels[:-1])[0] + 1\n    runs[1::2] -= runs[::2]\n    return ' '.join(str(x) for x in runs)","metadata":{"execution":{"iopub.status.busy":"2022-06-25T08:04:31.28688Z","iopub.execute_input":"2022-06-25T08:04:31.287403Z","iopub.status.idle":"2022-06-25T08:04:31.294464Z","shell.execute_reply.started":"2022-06-25T08:04:31.287356Z","shell.execute_reply":"2022-06-25T08:04:31.293494Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Metrics\ndef dice_coef(y_true, y_pred, smooth=1):\n    y_true_f = K.flatten(y_true)\n    y_pred_f = K.flatten(y_pred)\n    intersection = K.sum(y_true_f * y_pred_f)\n    return (2. * intersection + smooth) / (K.sum(y_true_f) + K.sum(y_pred_f) + smooth)\n\ndef iou_coef(y_true, y_pred, smooth=1):\n    intersection = K.sum(K.abs(y_true * y_pred), axis=[1,2,3])\n    union = K.sum(y_true,[1,2,3])+K.sum(y_pred,[1,2,3])-intersection\n    iou = K.mean((intersection + smooth) / (union + smooth), axis=0)\n    return iou\n\ndef dice_loss(y_true, y_pred):\n    smooth = 1.\n    y_true_f = K.flatten(y_true)\n    y_pred_f = K.flatten(y_pred)\n    intersection = y_true_f * y_pred_f\n    score = (2. * K.sum(intersection) + smooth) / (K.sum(y_true_f) + K.sum(y_pred_f) + smooth)\n    return 1. - score\n\ndef bce_dice_loss(y_true, y_pred):\n    return binary_crossentropy(tf.cast(y_true, tf.float32), y_pred) + dice_loss(tf.cast(y_true, tf.float32), y_pred)","metadata":{"execution":{"iopub.status.busy":"2022-06-25T08:04:43.852573Z","iopub.execute_input":"2022-06-25T08:04:43.853055Z","iopub.status.idle":"2022-06-25T08:04:43.861747Z","shell.execute_reply.started":"2022-06-25T08:04:43.85302Z","shell.execute_reply":"2022-06-25T08:04:43.861022Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def tversky(y_true, y_pred):\n    smooth = 1\n    y_true_pos = K.flatten(y_true)\n    y_pred_pos = K.flatten(y_pred)\n    true_pos = K.sum(y_true_pos * y_pred_pos)\n    false_neg = K.sum(y_true_pos * (1-y_pred_pos))\n    false_pos = K.sum((1-y_true_pos)*y_pred_pos)\n    alpha = 0.7\n    return (true_pos + smooth)/(true_pos + alpha*false_neg + (1-alpha)*false_pos + smooth)\n\ndef focal_tversky(y_true,y_pred):\n    pt_1 = tversky(y_true, y_pred)\n    gamma = 0.75\n    return K.pow((1-pt_1), gamma)","metadata":{"execution":{"iopub.status.busy":"2022-06-25T20:07:03.252949Z","iopub.execute_input":"2022-06-25T20:07:03.25415Z","iopub.status.idle":"2022-06-25T20:07:03.28079Z","shell.execute_reply.started":"2022-06-25T20:07:03.254028Z","shell.execute_reply":"2022-06-25T20:07:03.2797Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class DataGenerator(tf.keras.utils.Sequence):\n    def __init__(self, df, batch_size = BATCH_SIZE, subset=\"train\", shuffle=False, width=IMAGE_WIDTH, height=IMAGE_HEIGHT):\n        super().__init__()\n        self.df = df\n        self.shuffle = shuffle\n        self.subset = subset\n        self.batch_size = batch_size\n        self.indexes = np.arange(len(df))\n        self.width=width\n        self.height=height\n        self.on_epoch_end()\n\n    def __len__(self):\n        return int(np.floor(len(self.df) / self.batch_size))\n    \n    def on_epoch_end(self):\n        if self.shuffle == True:\n            np.random.shuffle(self.indexes)\n    \n    def __getitem__(self, index):\n        X = np.empty((self.batch_size,self.width,self.height,3))\n        y = np.empty((self.batch_size,self.width,self.height,3))\n        indexes = self.indexes[index*self.batch_size:(index+1)*self.batch_size]\n        for i, img_path in enumerate(self.df['path'].iloc[indexes]):\n            w=self.df['width'].iloc[indexes[i]]\n            h=self.df['height'].iloc[indexes[i]]\n            img = self.__load_grayscale(img_path)\n            X[i,] =img  \n            if self.subset == 'train':\n                for k,j in enumerate([\"large_bowel\",\"small_bowel\",\"stomach\"]):\n                    rles = self.df[j].iloc[indexes[i]]\n                    mask = rle_decode(rles, shape=(h, w, 1))\n                    mask = cv2.resize(mask, (self.width, self.height))\n                    y[i,:,:,k] = mask\n        if self.subset == 'train':\n            return X,y\n        else: \n            return X\n        \n    def __load_grayscale(self, img_path):\n        img = cv2.imread(img_path, cv2.IMREAD_ANYDEPTH)\n        dsize = (self.width, self.height)\n        img = cv2.resize(img, dsize)\n        img = ((img-img.min())/(img.max()-img.min())).astype(np.float32)\n        #img = img.astype(np.float32) / 255.\n        img = np.expand_dims(img, axis=-1)\n        return img","metadata":{"execution":{"iopub.status.busy":"2022-06-25T08:04:44.721617Z","iopub.execute_input":"2022-06-25T08:04:44.722225Z","iopub.status.idle":"2022-06-25T08:04:45.068818Z","shell.execute_reply.started":"2022-06-25T08:04:44.722191Z","shell.execute_reply":"2022-06-25T08:04:45.068083Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# def scheduler(epoch, lr):\n#     if epoch < 18:\n#         return lr\n#     else:\n#         return lr * tf.math.exp(-0.1)\n\n# lr_scheduler = tf.keras.callbacks.LearningRateScheduler(scheduler)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"lr_schedule = tf.keras.experimental.CosineDecay(initial_learning_rate=5e-4, decay_steps=30 + 2, alpha=5e-4 / 1e2)\nlr_scheduler = tf.keras.callbacks.LearningRateScheduler(lr_schedule, verbose=0)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# EDA","metadata":{}},{"cell_type":"code","source":"def open_gray16(_path, normalize=True, to_rgb=False):\n    if normalize:\n        if to_rgb:\n            return np.tile(np.expand_dims(cv2.imread(_path, cv2.IMREAD_ANYDEPTH)/255., axis=-1), 3)\n        else:\n            return cv2.imread(_path, cv2.IMREAD_ANYDEPTH)/255.\n    else:\n        if to_rgb:\n            return np.tile(np.expand_dims(cv2.imread(_path, cv2.IMREAD_ANYDEPTH), axis=-1), 3)\n        else:\n            return cv2.imread(_path, cv2.IMREAD_ANYDEPTH)","metadata":{"execution":{"iopub.status.busy":"2022-06-25T08:04:46.88552Z","iopub.execute_input":"2022-06-25T08:04:46.88612Z","iopub.status.idle":"2022-06-25T08:04:46.893506Z","shell.execute_reply.started":"2022-06-25T08:04:46.886076Z","shell.execute_reply":"2022-06-25T08:04:46.892818Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def examine_id(DEMO_ID, seg_masks=False):\n  demo_ex = train_df[train_df.id==DEMO_ID].squeeze()\n  display(demo_ex.to_frame())\n\n  print(f\"\\n\\n...IMAGE ...\\n\")\n  plt.figure(figsize=(6,6))\n  plt.imshow(open_gray16(demo_ex.path), cmap=\"gray\")\n  plt.title(f\"Original Grayscale Image For ID: {demo_ex.id}\", fontweight=\"bold\")\n  plt.axis(False)\n  plt.show()\n\n  if(seg_masks):\n    print(f\"\\n\\n... 3 SEGMENTATION MASKS ...\\n\")\n\n    plt.figure(figsize=(14,7))\n    for i, _seg_type in enumerate([\"large_bowel\", \"small_bowel\", \"stomach\"]):\n        if pd.isna(demo_ex[f\"{_seg_type}\"]): continue\n        plt.subplot(1,3,i+1)\n        s = demo_ex[f\"{_seg_type}\"]\n        plt.imshow(rle_decode(demo_ex[f\"{_seg_type}\"], shape=(demo_ex.height, demo_ex.width), color=1))\n        plt.title(f\"RLE Encoding For {_seg_type} Segmentation\", fontweight=\"bold\")\n        plt.axis(False)\n    plt.tight_layout()\n    plt.show()\n\n  print(f\"\\n\\n...IMAGE WITH AN RGB SEGMENTATION MASK OVERLAY ...\\n\")\n\n  _img = open_gray16(demo_ex.path, to_rgb=True)\n  _img = ((_img-_img.min())/(_img.max()-_img.min())).astype(np.float32)\n  _seg_rgb = np.stack([rle_decode(demo_ex[f\"{_seg_type}\"], shape=(demo_ex.height, demo_ex.width), color=1) if not pd.isna(demo_ex[f\"{_seg_type}\"]) else np.zeros((demo_ex.height, demo_ex.width)) for _seg_type in [\"large_bowel\", \"small_bowel\", \"stomach\"]], axis=-1).astype(np.float32)\n  seg_overlay = cv2.addWeighted(src1=_img, alpha=0.99, src2=_seg_rgb, beta=0.33, gamma=0.0)\n\n  plt.figure(figsize=(6,6))\n  plt.imshow(seg_overlay)\n  plt.title(f\"Segmentation Overlay For ID: {demo_ex.id}\", fontweight=\"bold\")\n  handles = [Rectangle((0,0),1,1, color=_c) for _c in [(0.667,0.0,0.0), (0.0,0.667,0.0), (0.0,0.0,0.667)]]\n  labels = [\"Large Bowel Segmentation Map\", \"Small Bowel Segmentation Map\", \"Stomach Segmentation Map\"]\n  plt.legend(handles,labels)\n  plt.axis(False)\n  plt.show()\n","metadata":{"execution":{"iopub.status.busy":"2022-06-25T08:04:47.922247Z","iopub.execute_input":"2022-06-25T08:04:47.922487Z","iopub.status.idle":"2022-06-25T08:04:47.93777Z","shell.execute_reply.started":"2022-06-25T08:04:47.92246Z","shell.execute_reply":"2022-06-25T08:04:47.936769Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(\"\\n... SINGLE ID EXPLORATION ...\\n\\n\")\nDEMO_ID = \"case123_day20_slice_0082\"\nexamine_id(DEMO_ID, seg_masks=True)","metadata":{"execution":{"iopub.status.busy":"2022-06-25T08:04:49.87736Z","iopub.execute_input":"2022-06-25T08:04:49.877882Z","iopub.status.idle":"2022-06-25T08:04:50.539082Z","shell.execute_reply.started":"2022-06-25T08:04:49.877844Z","shell.execute_reply":"2022-06-25T08:04:50.538335Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Cross-validation","metadata":{}},{"cell_type":"code","source":"# Group by case id\nskf = StratifiedGroupKFold(n_splits=n_splits, shuffle=True, random_state=42)\nfor fold, (_, val_idx) in enumerate(skf.split(X=train_df, y=train_df['count'], groups=train_df['case']), 1):\n    train_df.loc[val_idx, 'fold'] = fold\n\ntrain_df['fold'] = train_df['fold'].astype(np.uint8)\n\ntrain_ids = train_df[train_df[\"fold\"]!=fold_selected].index\nvalid_ids = train_df[train_df[\"fold\"]==fold_selected].index\n\nX_train = train_df[train_df.index.isin(train_ids)]\nX_valid = train_df[train_df.index.isin(valid_ids)]\n\ntrain_df.groupby('fold').size()","metadata":{"execution":{"iopub.status.busy":"2022-06-25T08:20:29.692099Z","iopub.execute_input":"2022-06-25T08:20:29.692372Z","iopub.status.idle":"2022-06-25T08:20:29.862786Z","shell.execute_reply.started":"2022-06-25T08:20:29.692343Z","shell.execute_reply":"2022-06-25T08:20:29.862081Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Fold sizes\ntrain_df.groupby(['fold','count'])['id'].count()","metadata":{"execution":{"iopub.status.busy":"2022-06-25T08:20:32.751904Z","iopub.execute_input":"2022-06-25T08:20:32.752522Z","iopub.status.idle":"2022-06-25T08:20:32.769068Z","shell.execute_reply.started":"2022-06-25T08:20:32.75248Z","shell.execute_reply":"2022-06-25T08:20:32.768277Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Model","metadata":{}},{"cell_type":"code","source":"#Data generators \ntrain_generator = DataGenerator(X_train, shuffle=True)\nval_generator = DataGenerator(X_valid)","metadata":{"execution":{"iopub.status.busy":"2022-06-25T08:04:59.159772Z","iopub.execute_input":"2022-06-25T08:04:59.160022Z","iopub.status.idle":"2022-06-25T08:04:59.200745Z","shell.execute_reply.started":"2022-06-25T08:04:59.159992Z","shell.execute_reply":"2022-06-25T08:04:59.199567Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!pip install segmentation-models","metadata":{"execution":{"iopub.status.busy":"2022-06-23T09:06:27.381717Z","iopub.execute_input":"2022-06-23T09:06:27.382021Z","iopub.status.idle":"2022-06-23T09:06:42.655209Z","shell.execute_reply.started":"2022-06-23T09:06:27.381984Z","shell.execute_reply":"2022-06-23T09:06:42.654357Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"! pip install git+https://github.com/qubvel/segmentation_models","metadata":{"execution":{"iopub.status.busy":"2022-06-23T09:06:42.65711Z","iopub.execute_input":"2022-06-23T09:06:42.657379Z","iopub.status.idle":"2022-06-23T09:06:54.084771Z","shell.execute_reply.started":"2022-06-23T09:06:42.657343Z","shell.execute_reply":"2022-06-23T09:06:54.083923Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import segmentation_models as sm\nsm.set_framework('tf.keras')\nsm.framework()","metadata":{"execution":{"iopub.status.busy":"2022-06-23T09:06:54.086397Z","iopub.execute_input":"2022-06-23T09:06:54.086758Z","iopub.status.idle":"2022-06-23T09:06:59.890123Z","shell.execute_reply.started":"2022-06-23T09:06:54.086716Z","shell.execute_reply":"2022-06-23T09:06:59.889355Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from segmentation_models import PSPNet\nfrom segmentation_models.utils import set_trainable\n\nmodel = PSPNet(backbone_name='resnet18', input_shape= (288, 288, 3), classes=3, activation='sigmoid')\nmodel.compile(optimizer='adam', loss=bce_dice_loss, metrics=[dice_coef,iou_coef])","metadata":{"_kg_hide-output":true,"execution":{"iopub.status.busy":"2022-06-23T09:07:25.530641Z","iopub.execute_input":"2022-06-23T09:07:25.53091Z","iopub.status.idle":"2022-06-23T09:07:26.192835Z","shell.execute_reply.started":"2022-06-23T09:07:25.53088Z","shell.execute_reply":"2022-06-23T09:07:26.192096Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Training model","metadata":{}},{"cell_type":"code","source":"checkpoint = ModelCheckpoint(\n    'PSPNet_model',\n    monitor='val_loss',\n    verbose=1,\n    save_best_only=True,\n    save_weights_only=False,\n    mode='auto',\n)\n\nearly_stopping = EarlyStopping(\n    patience=5,\n    min_delta=0.0001,\n    restore_best_weights=True,\n)","metadata":{"execution":{"iopub.status.busy":"2022-06-21T07:16:50.965277Z","iopub.execute_input":"2022-06-21T07:16:50.96554Z","iopub.status.idle":"2022-06-21T07:16:50.975411Z","shell.execute_reply.started":"2022-06-21T07:16:50.965506Z","shell.execute_reply":"2022-06-21T07:16:50.974012Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"history = model.fit(\n    train_generator,\n    validation_data=val_generator,\n    callbacks=[checkpoint, lr_scheduler, early_stopping],\n    epochs=EPOCHS\n)","metadata":{"_kg_hide-output":true,"execution":{"iopub.status.busy":"2022-06-21T07:16:50.976845Z","iopub.execute_input":"2022-06-21T07:16:50.977096Z","iopub.status.idle":"2022-06-21T11:01:12.58752Z","shell.execute_reply.started":"2022-06-21T07:16:50.977061Z","shell.execute_reply":"2022-06-21T11:01:12.586763Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# History\nhist_df = pd.DataFrame(history.history)\nhist_df.to_csv('history.csv')\n\n# PLOT TRAINING\nplt.figure(figsize=(15,5))\nplt.subplot(1,3,1)\nplt.plot(range(history.epoch[-1]+1),history.history['loss'],label='Train_Loss')\nplt.plot(range(history.epoch[-1]+1),history.history['val_loss'],label='Val_loss')\nplt.title('LOSS'); plt.xlabel('Epoch'); plt.ylabel('loss');plt.legend();\n\nplt.subplot(1,3,2)\nplt.plot(range(history.epoch[-1]+1),history.history['dice_coef'],label='Train_dice_coef')\nplt.plot(range(history.epoch[-1]+1),history.history['val_dice_coef'],label='Val_dice_coef')\nplt.title('DICE'); plt.xlabel('Epoch'); plt.ylabel('dice_coef');plt.legend(); ","metadata":{"execution":{"iopub.status.busy":"2022-06-21T11:01:12.588707Z","iopub.execute_input":"2022-06-21T11:01:12.589115Z","iopub.status.idle":"2022-06-21T11:01:12.943118Z","shell.execute_reply.started":"2022-06-21T11:01:12.589078Z","shell.execute_reply":"2022-06-21T11:01:12.942454Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Evaluation","metadata":{}},{"cell_type":"code","source":"custom_objects = custom_objects={\n    'dice_coef': dice_coef,\n    'iou_coef': iou_coef,\n    'bce_dice_loss': bce_dice_loss\n}\n\nmodel = load_model('./PSPNet_model', custom_objects=custom_objects)\n","metadata":{"execution":{"iopub.status.busy":"2022-06-25T08:13:16.393187Z","iopub.execute_input":"2022-06-25T08:13:16.394022Z","iopub.status.idle":"2022-06-25T08:13:19.737538Z","shell.execute_reply.started":"2022-06-25T08:13:16.393956Z","shell.execute_reply":"2022-06-25T08:13:19.736615Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Preview predictions**","metadata":{}},{"cell_type":"code","source":"print(X_valid.shape)","metadata":{"execution":{"iopub.status.busy":"2022-06-21T11:16:21.394744Z","iopub.execute_input":"2022-06-21T11:16:21.395599Z","iopub.status.idle":"2022-06-21T11:16:21.40114Z","shell.execute_reply.started":"2022-06-21T11:16:21.395552Z","shell.execute_reply":"2022-06-21T11:16:21.400374Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"pred_batches = DataGenerator(testdf, batch_size = 1, subset=\"train\", shuffle=False)\npreds = model.predict_generator(pred_batches,verbose=1)","metadata":{"execution":{"iopub.status.busy":"2022-06-25T08:21:16.196073Z","iopub.execute_input":"2022-06-25T08:21:16.196327Z","iopub.status.idle":"2022-06-25T08:21:16.392199Z","shell.execute_reply.started":"2022-06-25T08:21:16.196298Z","shell.execute_reply":"2022-06-25T08:21:16.391488Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.evaluate(pred_batches)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"Threshold = 0.5\n# Visualizing\nfig = plt.figure(figsize=(10, 25))\ngs = gridspec.GridSpec(nrows=10, ncols=3)\ncolors = ['yellow','green','red']\nlabels = [\"Large Bowel\", \"Small Bowel\", \"Stomach\"]\npatches = [ mpatches.Patch(color=colors[i], label=f\"{labels[i]}\") for i in range(len(labels))]\n\ncmap1 = mpl.colors.ListedColormap(colors[0])\ncmap2 = mpl.colors.ListedColormap(colors[1])\ncmap3= mpl.colors.ListedColormap(colors[2])\n\nfor i in range(10):\n    images, mask = pred_batches[i]\n    sample_img=images[0,:,:,0]\n    mask1=mask[0,:,:,0]\n    mask2=mask[0,:,:,1]\n    mask3=mask[0,:,:,2]\n    \n    pre=preds[i]\n    predict1=pre[:,:,0]\n    predict2=pre[:,:,1]\n    predict3=pre[:,:,2]\n    \n    predict1= (predict1 > Threshold).astype(np.float32)\n    predict2= (predict2 > Threshold).astype(np.float32)\n    predict3= (predict3 > Threshold).astype(np.float32)\n    \n    ax0 = fig.add_subplot(gs[i, 0])\n    im = ax0.imshow(sample_img, cmap='bone')\n    ax0.set_title(\"Image\", fontsize=12, y=1.01)\n    #--------------------------\n    ax1 = fig.add_subplot(gs[i, 1])\n    ax1.set_title(\"Mask\", fontsize=12,  y=1.01)\n    l0 = ax1.imshow(sample_img, cmap='bone')\n    l1 = ax1.imshow(np.ma.masked_where(mask1== False,  mask1),cmap=cmap1, alpha=1)\n    l2 = ax1.imshow(np.ma.masked_where(mask2== False,  mask2),cmap=cmap2, alpha=1)\n    l3 = ax1.imshow(np.ma.masked_where(mask3== False,  mask3),cmap=cmap3, alpha=1)\n    #--------------------------\n    ax2 = fig.add_subplot(gs[i, 2])\n    ax2.set_title(\"Predict\", fontsize=12, y=1.01)\n    l0 = ax2.imshow(sample_img, cmap='bone')\n    l1 = ax2.imshow(np.ma.masked_where(predict1== False,  predict1),cmap=cmap1, alpha=1)\n    l2 = ax2.imshow(np.ma.masked_where(predict2== False,  predict2),cmap=cmap2, alpha=1)\n    l3 = ax2.imshow(np.ma.masked_where(predict3== False,  predict3),cmap=cmap3, alpha=1)\n   \n\n    _ = [ax.set_axis_off() for ax in [ax0,ax1,ax2]]\n    colors = [im.cmap(im.norm(1)) for im in [l1,l2, l3]]\n    plt.legend(handles=patches, bbox_to_anchor=(1.1, 0.65), loc=2, borderaxespad=0.4,fontsize = 12,title='Mask Labels', title_fontsize=12, edgecolor=\"black\",  facecolor='#c5c6c7')\n","metadata":{"execution":{"iopub.status.busy":"2022-06-25T08:21:32.0685Z","iopub.execute_input":"2022-06-25T08:21:32.069057Z","iopub.status.idle":"2022-06-25T08:21:35.414315Z","shell.execute_reply.started":"2022-06-25T08:21:32.069019Z","shell.execute_reply":"2022-06-25T08:21:35.413538Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Test set predictions","metadata":{}},{"cell_type":"code","source":"#testdf=test_df\n#testdf[\"segmentation\"]=''\n#testdf=testdf.rename(columns={\"segmentation\":\"predicted\"})\n\npred_batches = DataGenerator(test_df, batch_size = BATCH_SIZE, subset=\"test\", shuffle=False)\nnum_batches = int(len(test_df)/BATCH_SIZE)\nsubmission1 = submission.copy()\nfor i in range(num_batches):\n    # Predict\n    preds = model.predict(pred_batches,verbose=0)\n\n    # Rle encode\n    for j in range(BATCH_SIZE):\n        for k in range(3):\n            pred_img = cv2.resize(preds[i*BATCH_SIZE+j,:,:,k], (test_df.loc[i*BATCH_SIZE+j,\"width\"], test_df.loc[i*BATCH_SIZE+j,\"height\"]), interpolation=cv2.INTER_NEAREST) # resize probabilities to original shape\n            pred_img = (pred_img>0.5).astype(dtype='uint8') # classify\n            submission.loc[115188 + 3*(i*BATCH_SIZE+j)+k,'segmentation'] = rle_encode(pred_img)\n            submission1.iloc[3*(i*BATCH_SIZE+j)+k,2] = rle_encode(pred_img)\n            #submission1=submission1.rename(columns={\"segmentation\":\"predicted\"})","metadata":{"execution":{"iopub.status.busy":"2022-06-25T08:17:53.600086Z","iopub.execute_input":"2022-06-25T08:17:53.600525Z","iopub.status.idle":"2022-06-25T08:18:00.846833Z","shell.execute_reply.started":"2022-06-25T08:17:53.600488Z","shell.execute_reply":"2022-06-25T08:18:00.845998Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Save predictions**","metadata":{}},{"cell_type":"code","source":"submission1.to_csv('submission.csv',index=False)\nsubmission1.sample(20)","metadata":{"execution":{"iopub.status.busy":"2022-06-25T08:18:00.848489Z","iopub.execute_input":"2022-06-25T08:18:00.848748Z","iopub.status.idle":"2022-06-25T08:18:00.868289Z","shell.execute_reply.started":"2022-06-25T08:18:00.848714Z","shell.execute_reply":"2022-06-25T08:18:00.867463Z"},"trusted":true},"execution_count":null,"outputs":[]}]}