{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.12.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"nvidiaTeslaT4","dataSources":[{"sourceId":5909621,"sourceType":"datasetVersion","datasetId":1911713}],"dockerImageVersionId":31236,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import tensorflow as tf\ntf.config.list_physical_devices('GPU')\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-16T17:16:20.472666Z","iopub.execute_input":"2026-01-16T17:16:20.47299Z","iopub.status.idle":"2026-01-16T17:16:36.387928Z","shell.execute_reply.started":"2026-01-16T17:16:20.472962Z","shell.execute_reply":"2026-01-16T17:16:36.387052Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import random\nimport pandas as pd\nimport numpy as np\nimport matplotlib.pyplot as plt\nplt.style.use(\"ggplot\")\n%matplotlib inline\n\nimport cv2\nfrom tqdm import tqdm_notebook, tnrange\nfrom glob import glob\nfrom itertools import chain\nfrom skimage.io import imread, imshow, concatenate_images\nfrom skimage.transform import resize\nfrom skimage.morphology import label\nfrom sklearn.model_selection import train_test_split\nfrom IPython.display import Image, display\n\nimport tensorflow as tf\n#from skimage.color import rgb2gray\nfrom tensorflow.keras import Input\nfrom tensorflow.keras.models import Model, load_model, save_model\nfrom tensorflow.keras.layers import Input, Activation, BatchNormalization, Dropout, Lambda, Conv2D, Conv2DTranspose, MaxPooling2D, concatenate\nfrom tensorflow.keras.optimizers.legacy import Adam\nfrom tensorflow.keras.callbacks import EarlyStopping, ModelCheckpoint\n\nfrom tensorflow.keras import backend as K\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator\nfrom tensorflow.keras.callbacks import EarlyStopping, ModelCheckpoint\n\n\nim_width = 256\nim_height = 256\n\nimage_filename_train = []\n\nmask_files = glob(pathname=r'/kaggle/input/lgg-mri-segmentation/kaggle_3m/**/*_mask*')\nfor i in mask_files:\n    image_filename_train.append(i.replace('_mask',''))\nprint(image_filename_train[:10])\nlen(image_filename_train)\n\ndef plot_from_img_path(rows, columns, list_img_path, list_mask_path):\n    fig = plt.figure(figsize  = (12,12))\n    for i in range(1, rows * columns + 1):\n        fig.add_subplot(rows, columns, i)\n        img_path = list_img_path[i]\n        mask_path = list_mask_path[i]\n        image = cv2.imread(img_path)\n        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\n        mask = cv2.imread(mask_path)\n        plt.imshow(image)\n        plt.imshow(mask, alpha=0.4)\n    plt.show()\n\nplot_from_img_path(3, 3, image_filename_train, mask_files)\n\ndf = pd.DataFrame(data = {'image_filename_train': image_filename_train, 'mask': mask_files})\ndf_train, df_test = train_test_split(df, test_size = 0.05)\ndf_train, df_val = train_test_split(df_train, test_size = 0.05) #90% train, 5% validation, 5% test\n\nprint(df_train.shape)\nprint(df_val.shape)\nprint(df_test.shape)\n\ndef train_generator(\n    data_frame,\n    batch_size,\n    augmentation_dict,\n    image_color_mode=\"rgb\",\n    mask_color_mode=\"grayscale\",\n    image_save_prefix=\"image\",\n    mask_save_prefix=\"mask\",\n    save_to_dir=None,\n    target_size=(256, 256),\n    seed=1,\n):\n    \n    image_datagen = ImageDataGenerator(**augmentation_dict)\n    mask_datagen = ImageDataGenerator(**augmentation_dict)\n\n    image_generator = image_datagen.flow_from_dataframe(\n        data_frame,\n        x_col=\"image_filename_train\",\n        class_mode=None,\n        color_mode=image_color_mode,\n        target_size=target_size,\n        batch_size=batch_size,\n        save_to_dir=save_to_dir,\n        save_prefix=image_save_prefix,\n        seed=seed,\n    )\n    mask_generator = mask_datagen.flow_from_dataframe(\n        data_frame,\n        x_col=\"mask\",\n        class_mode=None,\n        color_mode=mask_color_mode,\n        target_size=target_size,\n        batch_size=batch_size,\n        save_to_dir=save_to_dir,\n        save_prefix=mask_save_prefix,\n        seed=seed,\n    )\n    train_gen = zip(image_generator, mask_generator) #img,mask pairing\n    \n    # Final return Tuple after image Normalization and Diagnostics\n    for (img, mask) in train_gen:\n        img, mask = normalize_and_diagnose(img, mask)\n        yield (img, mask)\n\n\ndef normalize_and_diagnose(img, mask):\n    img = img / 255\n    mask = mask / 255 #scaling\n    mask[mask > 0.5] = 1\n    mask[mask <= 0.5] = 0 #thresholding\n    return(img, mask)\n\ndef dice_coefficients(y_true, y_pred, smooth=1.0): #overlap between predicted & true mask\n    y_true = K.cast(y_true, \"float32\")\n    y_pred = K.cast(y_pred, \"float32\")\n\n    y_true_f = K.flatten(y_true)\n    y_pred_f = K.flatten(y_pred)\n\n    intersection = K.sum(y_true_f * y_pred_f)\n    union = K.sum(y_true_f) + K.sum(y_pred_f)\n    return (2.0 * intersection + smooth) / (union + smooth)\n\ndef dice_coefficients_loss(y_true, y_pred, smooth=1.0):\n    return 1.0 - dice_coefficients(y_true, y_pred, smooth)\n\ndef iou(y_true, y_pred, smooth=1.0):\n    y_true = K.cast(y_true, \"float32\")\n    y_pred = K.cast(y_pred, \"float32\")\n\n    intersection = K.sum(y_true * y_pred)\n    total = K.sum(y_true + y_pred)\n    return (intersection + smooth) / (total - intersection + smooth)\n\ndef jaccard_distance(y_true, y_pred):\n    y_true_flatten = K.flatten(y_true)\n    y_pred_flatten = K.flatten(y_pred)\n    return -iou(y_true_flatten, y_pred_flatten)\n\n#display(Image(filename='Unet_Architecture.png'))\n\ndef unet(input_size=(im_width, im_height, 3)):\n    \n    inputs = Input(input_size)\n\n    # First DownConvolution \n    conv1 = Conv2D(filters=64, kernel_size=(3, 3), padding=\"same\")(inputs)\n    bn1 = Activation(\"relu\")(conv1)\n    conv1 = Conv2D(filters=64, kernel_size=(3, 3), padding=\"same\")(bn1)\n    bn1 = BatchNormalization(axis=3)(conv1)\n    bn1 = Activation(\"relu\")(bn1)\n    pool1 = MaxPooling2D(pool_size=(2, 2))(bn1)\n    # First DownSampling\n    conv2 = Conv2D(filters=128, kernel_size=(3, 3), padding=\"same\")(pool1)\n    bn2 = Activation(\"relu\")(conv2)\n    conv2 = Conv2D(filters=128, kernel_size=(3, 3), padding=\"same\")(bn2)\n    bn2 = BatchNormalization(axis=3)(conv2)\n    bn2 = Activation(\"relu\")(bn2)\n    pool2 = MaxPooling2D(pool_size=(2, 2))(bn2)\n    #Second DownSampling\n    conv3 = Conv2D(filters=256, kernel_size=(3, 3), padding=\"same\")(pool2)\n    bn3 = Activation(\"relu\")(conv3)\n    conv3 = Conv2D(filters=256, kernel_size=(3, 3), padding=\"same\")(bn3)\n    bn3 = BatchNormalization(axis=3)(conv3)\n    bn3 = Activation(\"relu\")(bn3)\n    pool3 = MaxPooling2D(pool_size=(2, 2))(bn3)\n    # Third DownSampling\n    conv4 = Conv2D(filters=512, kernel_size=(3, 3), padding=\"same\")(pool3)\n    bn4 = Activation(\"relu\")(conv4)\n    conv4 = Conv2D(filters=512, kernel_size=(3, 3), padding=\"same\")(bn4)\n    bn4 = BatchNormalization(axis=3)(conv4)\n    bn4 = Activation(\"relu\")(bn4)\n    pool4 = MaxPooling2D(pool_size=(2, 2))(bn4)\n\n    #bottleneck\n    conv5 = Conv2D(filters=1024, kernel_size=(3, 3), padding=\"same\")(pool4)\n    bn5 = Activation(\"relu\")(conv5)\n    conv5 = Conv2D(filters=1024, kernel_size=(3, 3), padding=\"same\")(bn5)\n    bn5 = BatchNormalization(axis=3)(conv5)\n    bn5 = Activation(\"relu\")(bn5)\n\n    #upsampling\n    up6 = concatenate([Conv2DTranspose(512, kernel_size=(2, 2), strides=(2, 2), padding=\"same\")(bn5), conv4], axis=3)\n    \"\"\" After every concatenation we again apply two consecutive regular convolutions so that the model can learn to assemble a more precise output \"\"\"\n    conv6 = Conv2D(filters=512, kernel_size=(3, 3), padding=\"same\")(up6)\n    bn6 = Activation(\"relu\")(conv6)\n    conv6 = Conv2D(filters=512, kernel_size=(3, 3), padding=\"same\")(bn6)\n    bn6 = BatchNormalization(axis=3)(conv6)\n    bn6 = Activation(\"relu\")(bn6)\n\n    up7 = concatenate([Conv2DTranspose(256, kernel_size=(2, 2), strides=(2, 2), padding=\"same\")(bn6),conv3], axis=3)\n    conv7 = Conv2D(filters=256, kernel_size=(3, 3), padding=\"same\")(up7)\n    bn7 = Activation(\"relu\")(conv7)\n    conv7 = Conv2D(filters=256, kernel_size=(3, 3), padding=\"same\")(bn7)\n    bn7 = BatchNormalization(axis=3)(conv7)\n    bn7 = Activation(\"relu\")(bn7)\n\n    up8 = concatenate([Conv2DTranspose(128, kernel_size=(2, 2), strides=(2, 2), padding=\"same\")(bn7),conv2], axis=3)\n    conv8 = Conv2D(filters=128, kernel_size=(3, 3), padding=\"same\")(up8)\n    bn8 = Activation(\"relu\")(conv8)\n    conv8 = Conv2D(filters=128, kernel_size=(3, 3), padding=\"same\")(bn8)\n    bn8 = BatchNormalization(axis=3)(conv8)\n    bn8 = Activation(\"relu\")(bn8)\n\n    up9 = concatenate([Conv2DTranspose(64, kernel_size=(2, 2), strides=(2, 2), padding=\"same\")(bn8),conv1],axis=3)\n    conv9 = Conv2D(filters=64, kernel_size=(3, 3), padding=\"same\")(up9)\n    bn9 = Activation(\"relu\")(conv9)\n    conv9 = Conv2D(filters=64, kernel_size=(3, 3), padding=\"same\")(bn9)\n    bn9 = BatchNormalization(axis=3)(conv9)\n    bn9 = Activation(\"relu\")(bn9)\n\n    #1 channel o/p, sigmoid--> probability map  \n    conv10 = Conv2D(filters=1, kernel_size=(1, 1), activation=\"sigmoid\")(bn9)\n\n    return Model(inputs=[inputs], outputs=[conv10])\n\nEPOCHS = 15\nBATCH_SIZE = 8\nlearning_rate = 1e-4\n\n#data augmentation setting\ntrain_generator_args = dict(rotation_range=0.2,\n                            width_shift_range=0.05,\n                            height_shift_range=0.05,\n                            shear_range=0.05,\n                            zoom_range=0.05,\n                            horizontal_flip=True,\n                            fill_mode='nearest')\n#generator\ntrain_gen = train_generator(df_train, BATCH_SIZE,\n                                train_generator_args,\n                                target_size=(im_height, im_width))\n    \ntest_gener = train_generator(df_val, BATCH_SIZE,\n                                dict(),\n                                target_size=(im_height, im_width))\n    \n#model building\nmodel = unet(input_size=(im_height, im_width, 3))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-16T17:16:36.389207Z","iopub.execute_input":"2026-01-16T17:16:36.389765Z","iopub.status.idle":"2026-01-16T17:16:41.463399Z","shell.execute_reply.started":"2026-01-16T17:16:36.389732Z","shell.execute_reply":"2026-01-16T17:16:41.462592Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# decay_rate = learning_rate / EPOCHS\nfrom tensorflow.keras.optimizers import Adam\n\nopt = Adam(\n    learning_rate=learning_rate,\n    beta_1=0.9,\n    beta_2=0.999\n)\n\nmodel.compile(\n    optimizer=opt,\n    loss=dice_coefficients_loss,\n    metrics=[\"binary_accuracy\", iou, dice_coefficients]\n)\n\nfrom tensorflow.keras.callbacks import ModelCheckpoint\n\ncallbacks = [\n    ModelCheckpoint(\n        'unet_brain_mri_seg.keras',\n        monitor='val_loss',\n        verbose=1,\n        save_best_only=True\n    )\n]\n\nhistory = model.fit(train_gen,\n                    steps_per_epoch = len(df_train) // BATCH_SIZE, \n                    epochs=EPOCHS, \n                    callbacks=callbacks,\n                    validation_data = test_gener,\n                   validation_steps = len(df_val) // BATCH_SIZE)\n\nhistory_post_training = history.history\n\ntrain_dice_coeff_list = history_post_training['dice_coefficients']\ntest_dice_coeff_list = history_post_training['val_dice_coefficients']\n\ntrain_jaccard_list = history_post_training['iou']\ntest_jaccard_list = history_post_training['val_iou']\n\ntrain_loss_list = history_post_training['loss']\ntest_loss_list = history_post_training['val_loss']\n\nplt.figure(1)\nplt.plot(test_loss_list, 'b-')\nplt.plot(train_loss_list, 'r-')\n\nplt.xlabel('iterations')\nplt.ylabel('loss')\nplt.title('loss graph', fontsize=12)\n\nplt.figure(2)\nplt.plot(train_dice_coeff_list, 'b-')\nplt.plot(test_dice_coeff_list, 'r-')\n\nplt.xlabel('iterations')\nplt.ylabel('accuracy')\nplt.title('Accuracy graph', fontsize=12)\nplt.show()\n\n\n#display(Image(filename='Loss Graph.png'))\n\nmodel = load_model(\n    'unet_brain_mri_seg.keras',\n    custom_objects={\n        'dice_coefficients_loss': dice_coefficients_loss,\n        'dice_coefficients': dice_coefficients,\n        'iou': iou\n    }\n)\n\n\ntest_gen = train_generator(df_test, BATCH_SIZE, dict(), target_size=(im_height,im_width))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-16T17:16:41.464385Z","iopub.execute_input":"2026-01-16T17:16:41.464892Z","iopub.status.idle":"2026-01-16T18:15:16.970588Z","shell.execute_reply.started":"2026-01-16T17:16:41.464866Z","shell.execute_reply":"2026-01-16T18:15:16.969919Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"results = model.evaluate(test_gen, steps=len(df_test)//BATCH_SIZE)\n\nprint('Test Loss', results[0])\nprint('Test IOU', results[1])\nprint('Test Dice Coeff', results[2])\n\nfor i in range(20):\n    index = np.random.randint(1, len(df_test.index))\n    img = cv2.imread(df_test['image_filename_train'].iloc[index])\n    img = cv2.resize(img, (im_height,im_width))\n    img = img/255\n    img = img[np.newaxis, : ,:, :]\n    pred_img = model.predict(img)\n    \n    plt.figure(figsize=(12,12))\n    plt.subplot(1, 3, 1)\n    plt.imshow(np.squeeze(img))\n    plt.title(\"Original Image\")\n    plt.subplot(1, 3, 2)\n    plt.imshow(np.squeeze(cv2.imread(df_test['mask'].iloc[index])))\n    plt.title(\"Original Mask\")\n    plt.subplot(1, 3, 3)\n    plt.imshow(np.squeeze(pred_img) > 0.5)\n    plt.title(\"Prediction\")\n    plt.show()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-16T18:15:16.972295Z","iopub.execute_input":"2026-01-16T18:15:16.972505Z","iopub.status.idle":"2026-01-16T18:15:35.956319Z","shell.execute_reply.started":"2026-01-16T18:15:16.972485Z","shell.execute_reply":"2026-01-16T18:15:35.9556Z"}},"outputs":[],"execution_count":null}]}