{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.7.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"gpu","dataSources":[{"sourceId":4104,"databundleVersionId":46661,"sourceType":"competition"},{"sourceId":265751,"sourceType":"datasetVersion","datasetId":110097},{"sourceId":2269470,"sourceType":"datasetVersion","datasetId":1366461}],"dockerImageVersionId":30162,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import numpy as np\nimport matplotlib.pyplot as plt\nimport tensorflow as tf\n# from keras.preprocessing.image import img_to_array\n# from keras.preprocessing.image import array_to_img\n# from sklearn.model_selection import train_test_split\n# from PIL import Image\n# import scipy\n\nimport tensorflow as tf\nfrom tensorflow.keras.applications import *\nfrom tensorflow.keras.optimizers import *\nfrom tensorflow.keras.losses import *\nfrom tensorflow.keras.layers import *\nfrom tensorflow.keras.models import *\nfrom tensorflow.keras.callbacks import *\nfrom tensorflow.keras.preprocessing.image import *\nfrom tensorflow.keras.utils import *\n# import pydot\nfrom sklearn.metrics import *\nfrom sklearn.model_selection import *\nimport tensorflow.keras.backend as K\n\n# from tqdm import tqdm, tqdm_notebook\n# from colorama import Fore\n# import json\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nfrom glob import glob\nfrom skimage.io import *\n%config Completer.use_jedi = False\n# import time\n# from sklearn.decomposition import PCA\n# from sklearn.svm import LinearSVC\n# from sklearn.linear_model import LogisticRegression\n# from sklearn.metrics import accuracy_score\n# import lightgbm as lgb\n# import xgboost as xgb\n# !pip install livelossplot\n# import livelossplot\n# from livelossplot import PlotLossesKeras\nimport warnings\nwarnings.filterwarnings('ignore')\nprint(\"All modules have been imported\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-26T06:00:35.206796Z","iopub.execute_input":"2025-04-26T06:00:35.207026Z","iopub.status.idle":"2025-04-26T06:00:42.009608Z","shell.execute_reply.started":"2025-04-26T06:00:35.206965Z","shell.execute_reply":"2025-04-26T06:00:42.008799Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"!unzip ../input/diabetic-retinopathy-detection/trainLabels.csv.zip","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-26T06:01:19.804313Z","iopub.execute_input":"2025-04-26T06:01:19.805041Z","iopub.status.idle":"2025-04-26T06:01:20.927770Z","shell.execute_reply.started":"2025-04-26T06:01:19.805004Z","shell.execute_reply":"2025-04-26T06:01:20.926762Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Importing labels","metadata":{}},{"cell_type":"code","source":"import pandas as pd\n\ntrainLabels = pd.read_csv(\"./trainLabels.csv\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-26T06:01:28.313749Z","iopub.execute_input":"2025-04-26T06:01:28.314377Z","iopub.status.idle":"2025-04-26T06:01:28.344253Z","shell.execute_reply.started":"2025-04-26T06:01:28.314333Z","shell.execute_reply":"2025-04-26T06:01:28.343577Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"!apt install p7zip-full -y\n!7z x ../input/diabetic-retinopathy-detection/train.zip.001 \"-i!train/11*.jpeg\" -y # restrict extracted file to about 100 for the disk restriction\n!mkdir data\n!mv train data/train_11\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-26T06:01:31.135356Z","iopub.execute_input":"2025-04-26T06:01:31.136080Z","iopub.status.idle":"2025-04-26T06:02:07.702619Z","shell.execute_reply.started":"2025-04-26T06:01:31.136044Z","shell.execute_reply":"2025-04-26T06:02:07.701530Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from PIL import Image\n\nimg = Image.open(\"./data/train_11/1116_right.jpeg\")\n\nimport matplotlib.pyplot as plt\n\nplt.imshow(img)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-26T06:02:44.301108Z","iopub.execute_input":"2025-04-26T06:02:44.301864Z","iopub.status.idle":"2025-04-26T06:02:46.026682Z","shell.execute_reply.started":"2025-04-26T06:02:44.301809Z","shell.execute_reply":"2025-04-26T06:02:46.025915Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"%reload_ext autoreload\n%autoreload 2\n%matplotlib inline","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-26T06:02:50.153377Z","iopub.execute_input":"2025-04-26T06:02:50.154166Z","iopub.status.idle":"2025-04-26T06:02:50.237208Z","shell.execute_reply.started":"2025-04-26T06:02:50.154129Z","shell.execute_reply":"2025-04-26T06:02:50.236713Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Filtering csv file","metadata":{}},{"cell_type":"code","source":"import os\nbase_image_dir = os.path.join('.', 'data/train_11')\ndf = pd.read_csv(os.path.join('./trainLabels.csv'))\ndf['path'] = df['image'].map(lambda x: os.path.join(base_image_dir,'{}.jpeg'.format(x)))\ndf['exists'] = df['path'].map(os.path.exists) #Most of the files do not exist because this is a sample of the original dataset\ndf = df[df['exists']]\ndf = df.drop(columns=['image','exists'])\ndf = df.sample(frac=1).reset_index(drop=True)#shuffle dataframe\ndf['level'] = df['level'].astype(str)\ndf.head(10)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-26T06:02:52.803299Z","iopub.execute_input":"2025-04-26T06:02:52.804035Z","iopub.status.idle":"2025-04-26T06:02:53.124237Z","shell.execute_reply.started":"2025-04-26T06:02:52.803996Z","shell.execute_reply":"2025-04-26T06:02:53.123515Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"### The dataset is highly imbalanced, with many samples for level 0, and very little for the rest of the levels.\n","metadata":{}},{"cell_type":"code","source":"df['level'].hist(figsize = (10, 5))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-26T06:02:59.832812Z","iopub.execute_input":"2025-04-26T06:02:59.833406Z","iopub.status.idle":"2025-04-26T06:03:00.017912Z","shell.execute_reply.started":"2025-04-26T06:02:59.833368Z","shell.execute_reply":"2025-04-26T06:03:00.017121Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def balance_data(class_size,df):\n    train_df = df.groupby(['level']).apply(lambda x: x.sample(class_size, replace = True)).reset_index(drop = True)\n    train_df = train_df.sample(frac=1).reset_index(drop=True)\n    print('New Data Size:', train_df.shape[0], 'Old Size:', df.shape[0])\n    train_df['level'].hist(figsize = (10, 5))\n    return train_df\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-26T06:03:02.918701Z","iopub.execute_input":"2025-04-26T06:03:02.919412Z","iopub.status.idle":"2025-04-26T06:03:02.973578Z","shell.execute_reply.started":"2025-04-26T06:03:02.919381Z","shell.execute_reply":"2025-04-26T06:03:02.972980Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from sklearn.model_selection import train_test_split\ntrain_df, val_df = train_test_split(df,test_size=0.2) # Here we will perform an 80%/20% split of the dataset, with stratification to keep similar distribution in validation set\ntrain_df['level'].hist(figsize = (10, 5))\nlen(val_df)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-26T06:03:05.982921Z","iopub.execute_input":"2025-04-26T06:03:05.983528Z","iopub.status.idle":"2025-04-26T06:03:06.224685Z","shell.execute_reply.started":"2025-04-26T06:03:05.983494Z","shell.execute_reply":"2025-04-26T06:03:06.224037Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_df = balance_data(train_df.pivot_table(index='level', aggfunc=len).max().max(),train_df) # I will oversample such that all classes have the same number of images as the maximum\ntrain_df['level'].hist(figsize = (10, 5))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-26T06:03:13.093023Z","iopub.execute_input":"2025-04-26T06:03:13.093629Z","iopub.status.idle":"2025-04-26T06:03:13.370652Z","shell.execute_reply.started":"2025-04-26T06:03:13.093592Z","shell.execute_reply":"2025-04-26T06:03:13.369919Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df = pd.concat([train_df,val_df]) #beginning of this dataframe is the oversampled training set, end is the validation set\nlen(df)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-26T06:03:21.497084Z","iopub.execute_input":"2025-04-26T06:03:21.497624Z","iopub.status.idle":"2025-04-26T06:03:21.553675Z","shell.execute_reply.started":"2025-04-26T06:03:21.497586Z","shell.execute_reply":"2025-04-26T06:03:21.552951Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_datagen = ImageDataGenerator(\n    rescale=1.0/255,\n    horizontal_flip = True,\n    zoom_range=0.2\n)\n\ntest_datagen = ImageDataGenerator(\n    rescale=1.0/255,\n    validation_split = 0.2\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-26T06:03:37.810187Z","iopub.execute_input":"2025-04-26T06:03:37.810934Z","iopub.status.idle":"2025-04-26T06:03:37.871186Z","shell.execute_reply.started":"2025-04-26T06:03:37.810900Z","shell.execute_reply":"2025-04-26T06:03:37.870287Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"x_train = train_datagen.flow_from_dataframe(\n        train_df,\n        directory=\".\",\n        x_col=\"path\",\n        y_col=\"level\",\n        target_size=(256, 256),\n        batch_size=32,\n        class_mode='categorical')\nx_test = test_datagen.flow_from_dataframe(\n        val_df,\n        x_col=\"path\",\n        y_col=\"level\",\n        directory=\".\",\n        target_size=(256, 256),\n        batch_size=32,\n        class_mode='categorical')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-26T06:03:49.295864Z","iopub.execute_input":"2025-04-26T06:03:49.296127Z","iopub.status.idle":"2025-04-26T06:03:49.379095Z","shell.execute_reply.started":"2025-04-26T06:03:49.296098Z","shell.execute_reply":"2025-04-26T06:03:49.378515Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import itertools\ndef plot_confusion_matrix(cm, classes,\n                          normalize=False,\n                          title='Confusion matrix',\n                          cmap=plt.cm.Blues):\n    \"\"\"\n    This function prints and plots the confusion matrix.\n    Normalization can be applied by setting `normalize=True`.\n    \"\"\"\n    plt.figure(figsize = (6,6))\n    plt.imshow(cm, interpolation='nearest', cmap=cmap)\n    plt.title(title)\n    plt.colorbar()\n    tick_marks = np.arange(len(classes))\n    plt.xticks(tick_marks, classes, rotation=90)\n    plt.yticks(tick_marks, classes)\n    if normalize:\n        cm = cm.astype('float') / cm.sum(axis=1)[:, np.newaxis]\n\n    thresh = cm.max() / 2.\n    cm = np.round(cm,2)\n    for i, j in itertools.product(range(cm.shape[0]), range(cm.shape[1])):\n        plt.text(j, i, cm[i, j],\n                 horizontalalignment=\"center\",\n                 color=\"white\" if cm[i, j] > thresh else \"black\")\n    plt.tight_layout()\n    plt.ylabel('True label')\n    plt.xlabel('Predicted label')\n    plt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-26T06:04:03.701968Z","iopub.execute_input":"2025-04-26T06:04:03.702743Z","iopub.status.idle":"2025-04-26T06:04:03.760149Z","shell.execute_reply.started":"2025-04-26T06:04:03.702708Z","shell.execute_reply":"2025-04-26T06:04:03.759342Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Image Data Generator","metadata":{}},{"cell_type":"code","source":"train_datagen = ImageDataGenerator(\n        rescale=1./255,\n        shear_range=0.2,\n        zoom_range=0.2,\n        horizontal_flip=True)\ntest_datagen = ImageDataGenerator(rescale=1./255)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-26T06:05:51.409423Z","iopub.execute_input":"2025-04-26T06:05:51.410224Z","iopub.status.idle":"2025-04-26T06:05:51.466138Z","shell.execute_reply.started":"2025-04-26T06:05:51.410183Z","shell.execute_reply":"2025-04-26T06:05:51.465381Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"t_x, t_y = next(x_train)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-26T06:05:55.757444Z","iopub.execute_input":"2025-04-26T06:05:55.757771Z","iopub.status.idle":"2025-04-26T06:05:59.865099Z","shell.execute_reply.started":"2025-04-26T06:05:55.757739Z","shell.execute_reply":"2025-04-26T06:05:59.864521Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## CNN Models","metadata":{}},{"cell_type":"code","source":"def create_CNN_model(model):\n    model.add(Conv2D(32, (3, 3), padding='same', activation='relu', input_shape=(264,264,3)))\n    model.add(MaxPooling2D(pool_size=(2, 2)))\n    model.add(Dropout(0.25))\n\n    model.add(Conv2D(64, (3, 3), padding='same', activation='relu'))\n    model.add(Conv2D(64, (3, 3), padding='same', activation='relu'))\n    model.add(MaxPooling2D(pool_size=(2, 2)))\n    model.add(Dropout(0.25))\n\n    model.add(Conv2D(128, (3, 3), padding='same', activation='relu'))\n    model.add(Conv2D(128, (3, 3), padding='same', activation='relu'))\n    model.add(MaxPooling2D(pool_size=(2, 2)))\n    model.add(Dropout(0.25))\n\n    model.add(Conv2D(256, (3, 3), padding='same', activation='relu'))\n    model.add(Conv2D(256, (3, 3), padding='same', activation='relu'))\n    model.add(MaxPooling2D(pool_size=(2, 2)))\n    model.add(Dropout(0.25))\n\n    model.add(Conv2D(128, (3, 3), padding='same', activation='relu'))\n    model.add(Conv2D(128, (3, 3), padding='same', activation='relu'))\n    model.add(MaxPooling2D(pool_size=(2, 2)))\n    model.add(Dropout(0.25))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-26T06:06:05.910430Z","iopub.execute_input":"2025-04-26T06:06:05.910730Z","iopub.status.idle":"2025-04-26T06:06:05.968959Z","shell.execute_reply.started":"2025-04-26T06:06:05.910699Z","shell.execute_reply":"2025-04-26T06:06:05.968211Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# def create_models(model_type):\n#     model = Sequential()\n#     if (model_type==\"cnn\"):\n#         create_CNN_model(model)\n#     elif(model_type == \"resnet\"):\n#         pretrained_model= tf.keras.applications.ResNet50(include_top=False,\n#                    input_shape=(256,256,3),\n#                    pooling='avg',classes=5,\n#                    weights='imagenet')\n#         for layer in pretrained_model.layers:\n#                 layer.trainable=False\n\n#         model.add(pretrained_model)\n#     elif(model_type == \"googlenet\"):\n#         pretrained_model = tf.keras.applications.InceptionV3(\n#                     include_top=True,\n#                     weights=\"imagenet\",\n#                     input_shape=(299,299,3),\n#                     pooling='avg',\n#                     classes=1000)\n#         for layer in pretrained_model.layers:\n#                 layer.trainable=False\n#         model.add(pretrained_model)\n        \n#     model.add(Flatten())\n#     model.add(Dense(512, activation='relu'))\n#     model.add(Dropout(0.5))\n#     model.add(Dense(256, activation='relu'))\n#     model.add(Dropout(0.5))\n#     model.add(Dense(128, activation='relu'))\n#     model.add(Dropout(0.5))\n#     model.add(Dense(5, activation='softmax'))\n\n#     model.compile(loss='categorical_crossentropy',\n#                   optimizer=Adam(learning_rate=0.002),\n#                   metrics=['accuracy',\"AUC\"])\n#     return model;\n\nfrom keras.applications.vgg16 import VGG16 as PTModel\nfrom keras.applications.inception_resnet_v2 import InceptionResNetV2 as PTModel\nfrom keras.applications.inception_v3 import InceptionV3 as PTModel\nfrom tensorflow.keras.applications import VGG16\nfrom tensorflow.keras.applications import InceptionResNetV2\nfrom tensorflow.keras.applications import InceptionV3\n\nfrom keras.layers import GlobalAveragePooling2D, Dense, Dropout, Flatten, Input, Conv2D, multiply, LocallyConnected2D, Lambda\nfrom keras.models import Model\nin_lay = Input(t_x.shape[1:])\nbase_pretrained_model = PTModel(input_shape =  t_x.shape[1:], include_top = False, weights = 'imagenet')\nbase_pretrained_model.trainable = False\npt_depth = 2048\npt_features = base_pretrained_model(in_lay)\nfrom keras.layers import BatchNormalization\nbn_features = BatchNormalization()(pt_features)\n\n\n# here we do an attention mechanism to turn pixels in the GAP on an off\n\nattn_layer = Conv2D(64, kernel_size = (1,1), padding = 'same', activation = 'relu')(Dropout(0.5)(bn_features))\nattn_layer = Conv2D(16, kernel_size = (1,1), padding = 'same', activation = 'relu')(attn_layer)\nattn_layer = Conv2D(8, kernel_size = (1,1), padding = 'same', activation = 'relu')(attn_layer)\nattn_layer = Conv2D(1, \n                    kernel_size = (1,1), \n                    padding = 'valid', \n                    activation = 'sigmoid')(attn_layer)\n# fan it out to all of the channels\nup_c2_w = np.ones((1, 1, 1, pt_depth))\nup_c2 = Conv2D(pt_depth, kernel_size = (1,1), padding = 'same', \n               activation = 'linear', use_bias = False, weights = [up_c2_w])\nup_c2.trainable = False\nattn_layer = up_c2(attn_layer)\n\nmask_features = multiply([attn_layer, bn_features])\ngap_features = GlobalAveragePooling2D()(mask_features)\ngap_mask = GlobalAveragePooling2D()(attn_layer)\n# to account for missing values from the attention model\ngap = Lambda(lambda x: x[0]/x[1], name = 'RescaleGAP')([gap_features, gap_mask])\ngap_dr = Dropout(0.25)(gap)\ndr_steps = Dropout(0.25)(Dense(128, activation = 'relu')(gap_dr))\nout_layer = Dense(t_y.shape[-1], activation = 'softmax')(dr_steps)\nmodel = Model(inputs = [in_lay], outputs = [out_layer])\nfrom keras.metrics import top_k_categorical_accuracy\ndef top_2_accuracy(in_gt, in_pred):\n    return top_k_categorical_accuracy(in_gt, in_pred, k=2)\n\nmodel.compile(optimizer = 'adam', loss = 'categorical_crossentropy',\n                           metrics = ['categorical_accuracy', top_2_accuracy])\nmodel.summary()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-26T06:06:34.727262Z","iopub.execute_input":"2025-04-26T06:06:34.727548Z","iopub.status.idle":"2025-04-26T06:06:43.845649Z","shell.execute_reply.started":"2025-04-26T06:06:34.727517Z","shell.execute_reply":"2025-04-26T06:06:43.844945Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model.summary()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-26T06:06:52.518883Z","iopub.execute_input":"2025-04-26T06:06:52.519144Z","iopub.status.idle":"2025-04-26T06:06:52.592202Z","shell.execute_reply.started":"2025-04-26T06:06:52.519115Z","shell.execute_reply":"2025-04-26T06:06:52.591447Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Callbacks for Parameter Tuning","metadata":{}},{"cell_type":"code","source":"filepath = \"dr-detector.hdf5\"\ncheckpoint = ModelCheckpoint(filepath,\n                             monitor=\"val_top2_accuracy\",\n                             verbose=1,\n                             save_best_only=True,\n                             mode=\"max\")\n\nearlystop = EarlyStopping(monitor='val_categorical_accuracy',\n                          verbose=1, \n                          min_delta=0, \n                          patience=15, \n                          restore_best_weights=True)\n\nreduce_lr = ReduceLROnPlateau(monitor='val_loss', \n                              verbose=1,\n                              factor=0.2, \n                              patience=6, \n                              min_delta=0.0001,\n                              cooldown=0,\n                              min_lr=0.001)\n\n\ncallbacks = [checkpoint, earlystop, reduce_lr]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-26T06:07:00.606348Z","iopub.execute_input":"2025-04-26T06:07:00.607089Z","iopub.status.idle":"2025-04-26T06:07:00.662256Z","shell.execute_reply.started":"2025-04-26T06:07:00.607052Z","shell.execute_reply":"2025-04-26T06:07:00.661606Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"history = model.fit(\n        x_train,\n        steps_per_epoch=x_train.samples // 64,\n        epochs=50,\n        validation_data=x_test,\n        validation_steps=x_test.samples // 64,\n        callbacks=callbacks)\nmodel.save_weights(\"dr_messidor.h5\")\n","metadata":{"trusted":true,"execution":{"execution_failed":"2025-04-26T08:29:30.867Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Evaluate the model on the training set\ntrain_results = model.evaluate(x_train)\ntrain_loss = train_results[0]  # Loss value\ntrain_accu = train_results[1]  # Accuracy value\n\n# Evaluate the model on the test set\ntest_results = model.evaluate(x_test)\ntest_loss = test_results[0]  # Loss value\ntest_accu = test_results[1]  # Accuracy value\n\n# Print the results\nprint(\"Final training accuracy = {:.2f} , validation accuracy = {:.2f}\".format(train_accu * 100, test_accu * 100))\nprint(\"Final training loss = {:.2f} , validation loss = {:.2f}\".format(train_loss, test_loss))\n","metadata":{"trusted":true,"execution":{"execution_failed":"2025-04-26T08:29:30.857Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"history.history","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-25T18:01:07.883400Z","iopub.execute_input":"2025-04-25T18:01:07.883808Z","iopub.status.idle":"2025-04-25T18:01:08.017709Z","shell.execute_reply.started":"2025-04-25T18:01:07.883753Z","shell.execute_reply":"2025-04-25T18:01:08.016976Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Check available keys in history.history\nprint(\"Available keys in history:\", history.history.keys())\n\n# Plot the accuracy and loss graphs\nplt.figure(figsize=(14, 5))\n\n# Accuracy Plot\nplt.subplot(1, 2, 1)\nplt.plot(history.history['categorical_accuracy'], label='train accuracy')\nplt.plot(history.history['val_categorical_accuracy'], label='test accuracy')\nplt.title('Model Accuracy')\nplt.xlabel('Epochs')\nplt.ylabel('Accuracy')\nplt.legend(loc='upper left')\n\n# Loss Plot\nplt.subplot(1, 2, 2)\nplt.plot(history.history['loss'], label='train loss')\nplt.plot(history.history['val_loss'], label='test loss')\nplt.title('Model Loss')\nplt.xlabel('Epochs')\nplt.ylabel('Loss')\nplt.legend(loc='upper left')\n\nplt.show()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-25T18:01:12.917786Z","iopub.execute_input":"2025-04-25T18:01:12.918150Z","iopub.status.idle":"2025-04-25T18:01:13.318411Z","shell.execute_reply.started":"2025-04-25T18:01:12.918110Z","shell.execute_reply":"2025-04-25T18:01:13.317623Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"y_pred = model.predict(x_train)\ny_pred = np.argmax(y_pred, axis=1)\nclass_labels = x_test.class_indices\nclass_labels = {v:k for k,v in class_labels.items()}\n\nfrom sklearn.metrics import classification_report, confusion_matrix\ncm_train = confusion_matrix(x_train.classes, y_pred)\nprint('Confusion Matrix')\nprint(cm_train)\nprint('Classification Report')\ntarget_names = list(class_labels.values())\nprint(classification_report(x_train.classes, y_pred, target_names=target_names))\n\nplt.figure(figsize=(8,8))\nplt.imshow(cm_train, interpolation='nearest')\nplt.colorbar()\ntick_mark = np.arange(len(target_names))\n_ = plt.xticks(tick_mark, target_names, rotation=90)\n_ = plt.yticks(tick_mark, target_names)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-25T18:01:16.818823Z","iopub.execute_input":"2025-04-25T18:01:16.819176Z","iopub.status.idle":"2025-04-25T18:06:07.852874Z","shell.execute_reply.started":"2025-04-25T18:01:16.819145Z","shell.execute_reply":"2025-04-25T18:06:07.851979Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Print all layer names with their indices and types to identify the correct last conv layer\nfor i, layer in enumerate(model.layers):\n    print(f\"Layer {i}: Name = {layer.name}, Type = {type(layer)}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-25T18:08:43.868106Z","iopub.execute_input":"2025-04-25T18:08:43.868733Z","iopub.status.idle":"2025-04-25T18:08:43.973080Z","shell.execute_reply.started":"2025-04-25T18:08:43.868699Z","shell.execute_reply":"2025-04-25T18:08:43.972487Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import tensorflow as tf\nfrom tensorflow.keras import models\nimport cv2\nimport numpy as np\nimport matplotlib.pyplot as plt\nfrom PIL import Image\n\n# Path to your image\nimg_path = \"./data/train_11/1116_right.jpeg\"\n\n# Open image using PIL and preprocess it\nimg = Image.open(img_path)\nimg = img.resize((256, 256))  # Resize to match model's expected input size\nimg_array = np.array(img)  # Convert to array\nimg_array = np.expand_dims(img_array, axis=0)  # Add batch dimension\nimg_array = img_array / 255.0  # Normalize if necessary\n\n# Define the Grad-CAM function\ndef get_gradcam_heatmap(model, img_array, class_idx, last_conv_layer_name):\n    # Get the last convolutional layer\n    grad_model = models.Model(\n        [model.inputs], [model.get_layer(last_conv_layer_name).output, model.output]\n    )\n\n    # Calculate the gradients of the top predicted class for the input image\n    with tf.GradientTape() as tape:\n        conv_outputs, predictions = grad_model(img_array)\n        loss = predictions[:, class_idx]\n\n    # Get the gradients of the loss with respect to the convolutional output\n    grads = tape.gradient(loss, conv_outputs)\n    \n    # Pool the gradients over all the filters\n    pooled_grads = tf.reduce_mean(grads, axis=(0, 1, 2))\n    \n    # Multiply each channel in the feature map array by the corresponding gradient\n    conv_outputs = conv_outputs[0]\n    heatmap = conv_outputs @ pooled_grads[..., tf.newaxis]\n    heatmap = tf.squeeze(heatmap)\n\n    # Apply ReLU to discard negative values and normalize between 0 and 1\n    heatmap = np.maximum(heatmap, 0) / np.max(heatmap)\n    return heatmap\n\n# Assuming the model has already been loaded and defined\n# Replace `model` with your model instance\n# Example: model = tf.keras.models.load_model('path/to/your/model')\n\n# Predict the class of the image and generate heatmap if infected\npreds = model.predict(img_array)\npred_class_idx = np.argmax(preds[0])  # Class with the highest prediction probability\n\n# Define the dictionary to map class names to indices (adjust to your model's classes)\nclass_labels = {'infected': 1, 'healthy': 0}  # Example class labels\n\n# Use 'conv2d_98' as the last conv layer\nlast_conv_layer_name = 'conv2d_98'\n\n# Only show heatmap if the prediction is for an infected class\nif pred_class_idx == class_labels.get('infected', None):\n    # Obtain the heatmap for the infected class\n    heatmap = get_gradcam_heatmap(model, img_array, pred_class_idx, last_conv_layer_name)\n\n    # Overlay the heatmap on the original image\n    original_img = cv2.imread(img_path)\n    heatmap = cv2.resize(heatmap, (original_img.shape[1], original_img.shape[0]))\n    heatmap = np.uint8(255 * heatmap)\n    heatmap = cv2.applyColorMap(heatmap, cv2.COLORMAP_JET)\n\n    # Overlay the heatmap on the original image with transparency\n    superimposed_img = cv2.addWeighted(heatmap, 0.4, original_img, 0.6, 0)\n    plt.figure(figsize=(8, 8))\n    plt.imshow(superimposed_img[..., ::-1])  # Convert BGR to RGB for matplotlib\n    plt.title(\"Infected Area Highlighted\")\n    plt.axis(\"off\")\n    plt.show()\nelse:\n    print(\"The model did not detect an infected area in this sample image.\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-25T18:08:47.210409Z","iopub.execute_input":"2025-04-25T18:08:47.211136Z","iopub.status.idle":"2025-04-25T18:08:51.008765Z","shell.execute_reply.started":"2025-04-25T18:08:47.211095Z","shell.execute_reply":"2025-04-25T18:08:51.008063Z"}},"outputs":[],"execution_count":null}]}