{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"gpu","dataSources":[{"sourceId":14774,"databundleVersionId":875431,"sourceType":"competition"},{"sourceId":9900,"sourceType":"datasetVersion","datasetId":6209}],"dockerImageVersionId":30665,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import os\nimport cv2\nimport random\nimport warnings\nimport numpy as np\nimport pandas as pd\nimport seaborn as sns\nimport matplotlib.pyplot as plt\nfrom sklearn.metrics import confusion_matrix, cohen_kappa_score\nfrom keras.models import Model\nfrom keras import optimizers, applications\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator\nfrom keras.callbacks import EarlyStopping, ReduceLROnPlateau\nfrom keras.layers import Dense, Dropout, GlobalAveragePooling2D, Input\n\n# Set seeds to make the experiment more reproducible.\nfrom tensorflow.random import set_seed\ndef seed_everything(seed=0):\n    random.seed(seed)\n    os.environ['PYTHONHASHSEED'] = str(seed)\n    np.random.seed(seed)\n    set_seed(0)\nseed_everything()\n\n%matplotlib inline\nsns.set(style=\"whitegrid\")\nwarnings.filterwarnings(\"ignore\")","metadata":{"execution":{"iopub.status.busy":"2024-03-10T21:58:36.696092Z","iopub.execute_input":"2024-03-10T21:58:36.697121Z","iopub.status.idle":"2024-03-10T21:58:49.009866Z","shell.execute_reply.started":"2024-03-10T21:58:36.697088Z","shell.execute_reply":"2024-03-10T21:58:49.009011Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train = pd.read_csv('../input/aptos2019-blindness-detection/train.csv')\ntest = pd.read_csv('../input/aptos2019-blindness-detection/test.csv')","metadata":{"execution":{"iopub.status.busy":"2024-03-10T21:58:49.011447Z","iopub.execute_input":"2024-03-10T21:58:49.012151Z","iopub.status.idle":"2024-03-10T21:58:49.034424Z","shell.execute_reply.started":"2024-03-10T21:58:49.012104Z","shell.execute_reply":"2024-03-10T21:58:49.033560Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# EDA Part and Data Overview\nprint('Number of train samples: ', train.shape[0])\nprint('Number of test samples: ', test.shape[0])\ndisplay(train.head())","metadata":{"execution":{"iopub.status.busy":"2024-03-10T21:58:49.035537Z","iopub.execute_input":"2024-03-10T21:58:49.035804Z","iopub.status.idle":"2024-03-10T21:58:49.051457Z","shell.execute_reply.started":"2024-03-10T21:58:49.035782Z","shell.execute_reply":"2024-03-10T21:58:49.050391Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Label Class Distribution\nf, ax = plt.subplots(figsize=(14, 8.7))\nax = sns.countplot(x=\"diagnosis\", data=train, palette=\"GnBu_d\")\nsns.despine()\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2024-03-10T21:58:49.053362Z","iopub.execute_input":"2024-03-10T21:58:49.053626Z","iopub.status.idle":"2024-03-10T21:58:49.337862Z","shell.execute_reply.started":"2024-03-10T21:58:49.053604Z","shell.execute_reply":"2024-03-10T21:58:49.336985Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sns.set_style(\"white\")\ncount = 1\nplt.figure(figsize=[20, 20])\nfor img_name in train['id_code'][:15]:\n    img = cv2.imread(\"../input/aptos2019-blindness-detection/train_images/%s.png\" % img_name)[...,[2, 1, 0]]\n    plt.subplot(5, 5, count)\n    plt.imshow(img)\n    plt.title(\"Image %s\" % count)\n    count += 1\n    \nplt.show()","metadata":{"execution":{"iopub.status.busy":"2024-03-10T21:58:49.339144Z","iopub.execute_input":"2024-03-10T21:58:49.339514Z","iopub.status.idle":"2024-03-10T21:59:02.381042Z","shell.execute_reply.started":"2024-03-10T21:58:49.339482Z","shell.execute_reply":"2024-03-10T21:59:02.379746Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Path specifications\nKAGGLE_DIR = '../input/aptos2019-blindness-detection/'\nTRAIN_DF_PATH = KAGGLE_DIR + \"train.csv\"\nTEST_DF_PATH = KAGGLE_DIR + 'test.csv'\nTRAIN_IMG_PATH = KAGGLE_DIR + \"train_images/\"\nTEST_IMG_PATH = KAGGLE_DIR + 'test_images/'","metadata":{"execution":{"iopub.status.busy":"2024-03-10T21:59:02.382753Z","iopub.execute_input":"2024-03-10T21:59:02.383070Z","iopub.status.idle":"2024-03-10T21:59:02.387608Z","shell.execute_reply.started":"2024-03-10T21:59:02.383045Z","shell.execute_reply":"2024-03-10T21:59:02.386706Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# creating dataframes train and test\nprint(\"Image IDs and Labels (TRAIN)\")\ntrain_df = pd.read_csv(TRAIN_DF_PATH)\n# Add extension to id_code\ntrain_df['id_code'] = train_df['id_code'] + \".png\"\nprint(f\"Training images: {train_df.shape[0]}\")\ndisplay(train_df.head())\nprint(\"Image IDs (TEST)\")\ntest_df = pd.read_csv(TEST_DF_PATH)\n# Add extension to id_code\ntest_df['id_code'] = test_df['id_code'] + \".png\"\nprint(f\"Testing Images: {test_df.shape[0]}\")\ndisplay(test_df.head())","metadata":{"execution":{"iopub.status.busy":"2024-03-10T21:59:02.388685Z","iopub.execute_input":"2024-03-10T21:59:02.388979Z","iopub.status.idle":"2024-03-10T21:59:02.417064Z","shell.execute_reply.started":"2024-03-10T21:59:02.388955Z","shell.execute_reply":"2024-03-10T21:59:02.416282Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\n# Labels for training data\ny_labels = train_df['diagnosis'].values\ny_labels[:5]","metadata":{"execution":{"iopub.status.busy":"2024-03-10T21:59:02.418261Z","iopub.execute_input":"2024-03-10T21:59:02.418523Z","iopub.status.idle":"2024-03-10T21:59:02.424850Z","shell.execute_reply.started":"2024-03-10T21:59:02.418500Z","shell.execute_reply":"2024-03-10T21:59:02.423954Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\n# taking a look at image from each class\nimport cv2\nSEED = 42\nfig, ax = plt.subplots(1,5,figsize = (15,5))\nfor i in range(5):\n    sample = train_df[train_df.diagnosis == i].sample(1,random_state=SEED)\n    image_name = sample['id_code'].item()\n    X = cv2.imread(f'{TRAIN_IMG_PATH}{image_name}')\n    ax[i].set_title(f\"Image: {image_name}\\n Label = {sample['diagnosis'].item()}\", weight='bold', fontsize=10)\n    ax[i].axis('off')\n    ax[i].imshow(X)\n    ","metadata":{"execution":{"iopub.status.busy":"2024-03-10T21:59:02.425973Z","iopub.execute_input":"2024-03-10T21:59:02.426308Z","iopub.status.idle":"2024-03-10T21:59:07.321262Z","shell.execute_reply.started":"2024-03-10T21:59:02.426281Z","shell.execute_reply":"2024-03-10T21:59:07.320148Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def crop_image_from_gray(img, tol=7):\n    \"\"\"\n    Applies masks to the orignal image and \n    returns the a preprocessed image with \n    3 channels\n    \"\"\"\n    # If for some reason we only have two channels\n    if img.ndim == 2:\n        mask = img > tol\n        return img[np.ix_(mask.any(1),mask.any(0))]\n    # If we have a normal RGB images\n    elif img.ndim == 3:\n        gray_img = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)\n        mask = gray_img > tol\n        \n        check_shape = img[:,:,0][np.ix_(mask.any(1),mask.any(0))].shape[0]\n        if (check_shape == 0): # image is too dark so that we crop out everything,\n            return img # return original image\n        else:\n            img1=img[:,:,0][np.ix_(mask.any(1),mask.any(0))]\n            img2=img[:,:,1][np.ix_(mask.any(1),mask.any(0))]\n            img3=img[:,:,2][np.ix_(mask.any(1),mask.any(0))]\n            img = np.stack([img1,img2,img3],axis=-1)\n        return img\n\ndef preprocess_image(image, sigmaX=10):\n    \"\"\"\n    The whole preprocessing pipeline:\n    1. Read in image\n    2. Apply masks\n    3. Resize image to desired size\n    4. Add Gaussian noise to increase Robustness\n    \"\"\"\n    image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\n    image = crop_image_from_gray(image)\n    image = cv2.resize(image, (512,512))\n    image = cv2.addWeighted (image,4, cv2.GaussianBlur(image, (0,0) ,sigmaX), -4, 128)\n    return image","metadata":{"execution":{"iopub.status.busy":"2024-03-10T21:59:07.324793Z","iopub.execute_input":"2024-03-10T21:59:07.325106Z","iopub.status.idle":"2024-03-10T21:59:07.336309Z","shell.execute_reply.started":"2024-03-10T21:59:07.325081Z","shell.execute_reply":"2024-03-10T21:59:07.335341Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Specify image size\nIMG_WIDTH = 224\nIMG_HEIGHT = 224\nCHANNELS = 3\n\nimport cv2\n\nfig, ax = plt.subplots(1,5,figsize = (15,5))\nfor i in range(5):\n    sample = train_df[train_df.diagnosis == i].sample(1,random_state=SEED)\n    image_name = sample['id_code'].item()\n    X = preprocess_image(cv2.imread(f'{TRAIN_IMG_PATH}{image_name}'))\n    ax[i].set_title(f\"Image: {image_name}\\n Label = {sample['diagnosis'].item()}\", weight='bold', fontsize=10)\n    ax[i].axis('off')\n    ax[i].imshow(X)","metadata":{"execution":{"iopub.status.busy":"2024-03-10T21:59:07.337402Z","iopub.execute_input":"2024-03-10T21:59:07.337705Z","iopub.status.idle":"2024-03-10T21:59:09.730858Z","shell.execute_reply.started":"2024-03-10T21:59:07.337681Z","shell.execute_reply":"2024-03-10T21:59:09.729892Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Setting the model parameters\nBATCH_SIZE =32\nEPOCHS = 20\nWARMUP_EPOCHS = 2\nLEARNING_RATE = 1e-4\nWARMUP_LEARNING_RATE = 1e-3\nHEIGHT = 224\nWIDTH = 224\nCANAL = 3\nN_CLASSES = train['diagnosis'].nunique()\nES_PATIENCE = 5\nRLROP_PATIENCE = 3\nDECAY_DROP = 0.5","metadata":{"execution":{"iopub.status.busy":"2024-03-10T21:59:09.732135Z","iopub.execute_input":"2024-03-10T21:59:09.732520Z","iopub.status.idle":"2024-03-10T21:59:09.739172Z","shell.execute_reply.started":"2024-03-10T21:59:09.732487Z","shell.execute_reply":"2024-03-10T21:59:09.738211Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Preprocecss data\ntrain[\"id_code\"] = train[\"id_code\"].apply(lambda x: x + \".png\")\ntest[\"id_code\"] = test[\"id_code\"].apply(lambda x: x + \".png\")\ntrain['diagnosis'] = train['diagnosis'].astype('str')\ntrain.head()","metadata":{"execution":{"iopub.status.busy":"2024-03-10T21:59:09.740419Z","iopub.execute_input":"2024-03-10T21:59:09.740774Z","iopub.status.idle":"2024-03-10T21:59:09.762358Z","shell.execute_reply.started":"2024-03-10T21:59:09.740742Z","shell.execute_reply":"2024-03-10T21:59:09.761495Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Data Generator for train, test and validation\ntrain_datagen=ImageDataGenerator(rescale=1./255, \n                                 validation_split=0.2,\n                                 horizontal_flip=True\n                                )\n\ntrain_generator=train_datagen.flow_from_dataframe(\n    dataframe=train,\n    directory=\"../input/aptos2019-blindness-detection/train_images/\",\n    x_col=\"id_code\",\n    y_col=\"diagnosis\",\n    batch_size=BATCH_SIZE,\n    class_mode=\"categorical\",\n    target_size=(HEIGHT, WIDTH),\n    subset='training')\n\nvalid_generator=train_datagen.flow_from_dataframe(\n    dataframe=train,\n    directory=\"../input/aptos2019-blindness-detection/train_images/\",\n    x_col=\"id_code\",\n    y_col=\"diagnosis\",\n    batch_size=BATCH_SIZE,\n    class_mode=\"categorical\",    \n    target_size=(HEIGHT, WIDTH),\n    subset='validation')\n\ntest_datagen = ImageDataGenerator(rescale=1./255)\n\ntest_generator = test_datagen.flow_from_dataframe(  \n        dataframe=test,\n        directory = \"../input/aptos2019-blindness-detection/test_images/\",\n        x_col=\"id_code\",\n        target_size=(HEIGHT, WIDTH),\n        batch_size=1,\n        shuffle=False,\n        class_mode=None)","metadata":{"execution":{"iopub.status.busy":"2024-03-10T21:59:09.763568Z","iopub.execute_input":"2024-03-10T21:59:09.763905Z","iopub.status.idle":"2024-03-10T21:59:23.210829Z","shell.execute_reply.started":"2024-03-10T21:59:09.763876Z","shell.execute_reply":"2024-03-10T21:59:23.209839Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from tensorflow.keras import applications, optimizers\nfrom tensorflow.keras.layers import Input, GlobalAveragePooling2D, Dense, Dropout\nfrom tensorflow.keras.models import Model\n\ndef create_model(input_shape, n_out):\n    input_tensor = Input(shape=input_shape)\n    base_model = applications.ResNet50(weights='imagenet', \n                                       include_top=False,\n                                       input_tensor=input_tensor)\n\n    x = GlobalAveragePooling2D()(base_model.output)\n    x = Dropout(0.5)(x)\n    x = Dense(2048, activation='relu')(x)\n    x = Dropout(0.5)(x)\n    final_output = Dense(n_out, activation='softmax', name='final_output')(x)\n    model = Model(input_tensor, final_output)\n    \n    return model","metadata":{"execution":{"iopub.status.busy":"2024-03-10T21:59:23.211991Z","iopub.execute_input":"2024-03-10T21:59:23.212305Z","iopub.status.idle":"2024-03-10T21:59:23.224021Z","shell.execute_reply.started":"2024-03-10T21:59:23.212279Z","shell.execute_reply":"2024-03-10T21:59:23.222679Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model = create_model(input_shape=(HEIGHT, WIDTH, CANAL), n_out=N_CLASSES)\n\n# Freeze all layers and then unfreeze the last 5\nfor layer in model.layers:\n    layer.trainable = False\n\nfor i in range(-5, 0):\n    model.layers[i].trainable = True\n\n# Learning rate warm-up\nmetric_list = [\"accuracy\"]\nWARMUP_LEARNING_RATE = 1e-4\noptimizer = optimizers.Adam(learning_rate=WARMUP_LEARNING_RATE)\nmodel.compile(optimizer=optimizer, loss=\"categorical_crossentropy\", metrics=metric_list)\n\nmodel.summary()","metadata":{"execution":{"iopub.status.busy":"2024-03-10T21:59:23.225003Z","iopub.execute_input":"2024-03-10T21:59:23.225317Z","iopub.status.idle":"2024-03-10T21:59:28.886133Z","shell.execute_reply.started":"2024-03-10T21:59:23.225293Z","shell.execute_reply":"2024-03-10T21:59:28.885293Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os\n\nos.environ['TF_XLA_FLAGS'] = '--tf_xla_auto_jit=2'","metadata":{"execution":{"iopub.status.busy":"2024-03-10T21:59:28.887303Z","iopub.execute_input":"2024-03-10T21:59:28.887578Z","iopub.status.idle":"2024-03-10T21:59:28.891586Z","shell.execute_reply.started":"2024-03-10T21:59:28.887554Z","shell.execute_reply":"2024-03-10T21:59:28.890654Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Train the top layers of the model\nSTEP_SIZE_TRAIN = train_generator.n//train_generator.batch_size\nSTEP_SIZE_VALID = valid_generator.n//valid_generator.batch_size\n\nhistory_warmup = model.fit(\n    train_generator,\n    steps_per_epoch=STEP_SIZE_TRAIN,\n    validation_data=valid_generator,\n    validation_steps=STEP_SIZE_VALID,\n    epochs=WARMUP_EPOCHS,\n    verbose=1\n).history","metadata":{"execution":{"iopub.status.busy":"2024-03-10T21:59:28.892741Z","iopub.execute_input":"2024-03-10T21:59:28.893008Z","iopub.status.idle":"2024-03-10T22:07:22.200748Z","shell.execute_reply.started":"2024-03-10T21:59:28.892986Z","shell.execute_reply":"2024-03-10T22:07:22.199923Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Finetune the complete model\nfor layer in model.layers:\n    layer.trainable = True\n\n# es = EarlyStopping(monitor='val_loss', mode='min', patience=ES_PATIENCE, restore_best_weights=True, verbose=1)\nrlrop = ReduceLROnPlateau(monitor='val_loss', mode='min', patience=RLROP_PATIENCE, factor=DECAY_DROP, min_lr=1e-6, verbose=1)\n\n# callback_list = [es, rlrop]\ncallback_list = [rlrop]\noptimizer = optimizers.Adam(learning_rate=LEARNING_RATE)\nmodel.compile(optimizer=optimizer, loss=\"binary_crossentropy\",  metrics=metric_list)\nmodel.summary()","metadata":{"execution":{"iopub.status.busy":"2024-03-10T22:07:22.201947Z","iopub.execute_input":"2024-03-10T22:07:22.202261Z","iopub.status.idle":"2024-03-10T22:07:22.444820Z","shell.execute_reply.started":"2024-03-10T22:07:22.202236Z","shell.execute_reply":"2024-03-10T22:07:22.443938Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"try:\n    history_finetuning = model.fit(\n        train_generator,\n        steps_per_epoch=STEP_SIZE_TRAIN,\n        validation_data=valid_generator,\n        validation_steps=STEP_SIZE_VALID,\n        epochs=30,\n        callbacks=callback_list,\n        verbose=1\n    ).history\nexcept Exception as e:\n    print(\"An error occurred during training:\", e)","metadata":{"execution":{"iopub.status.busy":"2024-03-10T22:07:22.445914Z","iopub.execute_input":"2024-03-10T22:07:22.446206Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Model loss graph\nhistory = {\n    'loss': history_warmup['loss'] + history_finetuning['loss'],\n    'val_loss': history_warmup['val_loss'] + history_finetuning['val_loss'],\n    'accuracy': history_warmup['accuracy'] + history_finetuning['accuracy'],\n    'val_accuracy': history_warmup['val_accuracy'] + history_finetuning['val_accuracy']\n}\n\nsns.set_style(\"whitegrid\")\nfig, (ax1, ax2) = plt.subplots(2, 1, sharex='col', figsize=(20, 14))\n\nax1.plot(history['loss'], label='Train loss')\nax1.plot(history['val_loss'], label='Validation loss')\nax1.legend(loc='best')\nax1.set_title('Loss')\n\nax2.plot(history['accuracy'], label='Train Accuracy')\nax2.plot(history['val_accuracy'], label='Validation accuracy')\nax2.legend(loc='best')\nax2.set_title('Accuracy')\n\nplt.xlabel('Epochs')\nsns.despine()\nplt.show()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Model Evaluation\ncomplete_datagen = ImageDataGenerator(rescale=1./255)\ncomplete_generator = complete_datagen.flow_from_dataframe(  \n        dataframe=train,\n        directory = \"../input/aptos2019-blindness-detection/train_images/\",\n        x_col=\"id_code\",\n        target_size=(HEIGHT, WIDTH),\n        batch_size=1,\n        shuffle=False,\n        class_mode=None)\n\nSTEP_SIZE_COMPLETE = complete_generator.n//complete_generator.batch_size\ntrain_preds = model.predict(complete_generator, steps=STEP_SIZE_COMPLETE)\ntrain_preds = [np.argmax(pred) for pred in train_preds]","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Confusion Matrix\nlabels = ['0 - No DR', '1 - Mild', '2 - Moderate', '3 - Severe', '4 - Proliferative DR']\ncnf_matrix = confusion_matrix(train['diagnosis'].astype('int'), train_preds)\ncnf_matrix_norm = cnf_matrix.astype('float') / cnf_matrix.sum(axis=1)[:, np.newaxis]\ndf_cm = pd.DataFrame(cnf_matrix_norm, index=labels, columns=labels)\nplt.figure(figsize=(16, 7))\nsns.heatmap(df_cm, annot=True, fmt='.2f', cmap=\"Blues\")\nplt.show()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Finding the Quadratic Kappa Score\nprint(\"Train Cohen Kappa score: %.3f\" % cohen_kappa_score(train_preds, train['diagnosis'].astype('int'), weights='quadratic'))","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Apply the model to test set and output predictions\ntest_generator.reset()\nSTEP_SIZE_TEST = test_generator.n//test_generator.batch_size\npreds = model.predict(test_generator, steps=STEP_SIZE_TEST)\npredictions = [np.argmax(pred) for pred in preds]","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"filenames = test_generator.filenames\nresults = pd.DataFrame({'id_code':filenames, 'diagnosis':predictions})\nresults['id_code'] = results['id_code'].map(lambda x: str(x)[:-4])\nresults.to_csv('submission.csv',index=False)\nresults.head(10)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Predictions class distribution\nf, ax = plt.subplots(figsize=(14, 8.7))\nax = sns.countplot(x=\"diagnosis\", data=results, palette=\"GnBu_d\")\nsns.despine()\nplt.show()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Save the model\nmodel.save('/kaggle/working/diabetic_retinopathy_model.h5')","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from keras.models import load_model\nfrom keras.preprocessing import image\nimport numpy as np","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Load the saved model\nloaded_model = load_model('diabetic_retinopathy_model.h5')","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Path to the test image you want to predict\ntest_image_path = \"/kaggle/input/aptos2019-blindness-detection/train_images/000c1434d8d7.png\"","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Load and preprocess the test image\nimg = image.load_img(test_image_path, target_size=(HEIGHT, WIDTH))\nimg_array = image.img_to_array(img)\nimg_array = np.expand_dims(img_array, axis=0)\nimg_array /= 255.0","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Make predictions\npredictions = loaded_model.predict(img_array)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Convert predictions to the corresponding class\npredicted_class = np.argmax(predictions)\nprint(\"Predicted Diabetic Retinopathy Stage:\", predicted_class)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from tensorflow.keras import applications\nfrom tensorflow.keras.layers import Input, GlobalAveragePooling2D, Dense, Dropout\nfrom tensorflow.keras.models import Model\n\ndef create_densenet_model(input_shape, n_out):\n    input_tensor = Input(shape=input_shape)\n    base_model = applications.DenseNet121(weights='imagenet', \n                                          include_top=False,\n                                          input_tensor=input_tensor)\n\n    x = GlobalAveragePooling2D()(base_model.output)\n    x = Dropout(0.5)(x)\n    x = Dense(2048, activation='relu')(x)\n    x = Dropout(0.5)(x)\n    final_output = Dense(n_out, activation='softmax', name='final_output')(x)\n    model = Model(input_tensor, final_output)\n    \n    return model\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"DenseNet\n","metadata":{}},{"cell_type":"code","source":"dense_model = create_densenet_model(input_shape=(HEIGHT, WIDTH, CANAL), n_out=N_CLASSES)\n\n# Freeze all layers and then unfreeze the last 5\nfor layer in dense_model.layers:\n    layer.trainable = False\n\nfor i in range(-5, 0):\n    dense_model.layers[i].trainable = True\n\n# Learning rate warm-up\nmetric_list = [\"accuracy\"]\nWARMUP_LEARNING_RATE = 1e-4\noptimizer = optimizers.Adam(learning_rate=WARMUP_LEARNING_RATE)\ndense_model.compile(optimizer=optimizer, loss=\"categorical_crossentropy\", metrics=metric_list)\n\ndense_model.summary()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Train the top layers of the model\nSTEP_SIZE_TRAIN = train_generator.n//train_generator.batch_size\nSTEP_SIZE_VALID = valid_generator.n//valid_generator.batch_size\n\nhistory_warmup = dense_model.fit(\n    train_generator,\n    steps_per_epoch=STEP_SIZE_TRAIN,\n    validation_data=valid_generator,\n    validation_steps=STEP_SIZE_VALID,\n    epochs=WARMUP_EPOCHS,\n    verbose=1\n).history","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Finetune the complete model\nfor layer in dense_model.layers:\n    layer.trainable = True\n\n# es = EarlyStopping(monitor='val_loss', mode='min', patience=ES_PATIENCE, restore_best_weights=True, verbose=1)\nrlrop = ReduceLROnPlateau(monitor='val_loss', mode='min', patience=RLROP_PATIENCE, factor=DECAY_DROP, min_lr=1e-6, verbose=1)\n\n# callback_list = [es, rlrop]\ncallback_list = [rlrop]\noptimizer = optimizers.Adam(learning_rate=LEARNING_RATE)\ndense_model.compile(optimizer=optimizer, loss=\"binary_crossentropy\",  metrics=metric_list)\ndense_model.summary()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"try:\n    history_finetuning = dense_model.fit(\n        train_generator,\n        steps_per_epoch=STEP_SIZE_TRAIN,\n        validation_data=valid_generator,\n        validation_steps=STEP_SIZE_VALID,\n        epochs=30,\n        callbacks=callback_list,\n        verbose=1\n    ).history\nexcept Exception as e:\n    print(\"An error occurred during training:\", e)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Model loss graph\nhistory = {\n    'loss': history_warmup['loss'] + history_finetuning['loss'],\n    'val_loss': history_warmup['val_loss'] + history_finetuning['val_loss'],\n    'accuracy': history_warmup['accuracy'] + history_finetuning['accuracy'],\n    'val_accuracy': history_warmup['val_accuracy'] + history_finetuning['val_accuracy']\n}\n\nsns.set_style(\"whitegrid\")\nfig, (ax1, ax2) = plt.subplots(2, 1, sharex='col', figsize=(20, 14))\n\nax1.plot(history['loss'], label='Train loss')\nax1.plot(history['val_loss'], label='Validation loss')\nax1.legend(loc='best')\nax1.set_title('Loss')\n\nax2.plot(history['accuracy'], label='Train Accuracy')\nax2.plot(history['val_accuracy'], label='Validation accuracy')\nax2.legend(loc='best')\nax2.set_title('Accuracy')\n\nplt.xlabel('Epochs')\nsns.despine()\nplt.show()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Model Evaluation\ncomplete_datagen = ImageDataGenerator(rescale=1./255)\ncomplete_generator = complete_datagen.flow_from_dataframe(  \n        dataframe=train,\n        directory = \"../input/aptos2019-blindness-detection/train_images/\",\n        x_col=\"id_code\",\n        target_size=(HEIGHT, WIDTH),\n        batch_size=1,\n        shuffle=False,\n        class_mode=None)\n\nSTEP_SIZE_COMPLETE = complete_generator.n//complete_generator.batch_size\ntrain_preds = dense_model.predict(complete_generator, steps=STEP_SIZE_COMPLETE)\ntrain_preds = [np.argmax(pred) for pred in train_preds]","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Confusion Matrix\nlabels = ['0 - No DR', '1 - Mild', '2 - Moderate', '3 - Severe', '4 - Proliferative DR']\ncnf_matrix = confusion_matrix(train['diagnosis'].astype('int'), train_preds)\ncnf_matrix_norm = cnf_matrix.astype('float') / cnf_matrix.sum(axis=1)[:, np.newaxis]\ndf_cm = pd.DataFrame(cnf_matrix_norm, index=labels, columns=labels)\nplt.figure(figsize=(16, 7))\nsns.heatmap(df_cm, annot=True, fmt='.2f', cmap=\"Blues\")\nplt.show()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Finding the Quadratic Kappa Score\nprint(\"Train Cohen Kappa score: %.3f\" % cohen_kappa_score(train_preds, train['diagnosis'].astype('int'), weights='quadratic'))","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"dense_model.save(\"/kaggle/working/dense_diabetic_retinopathy_model.h5\")","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"MobileNet","metadata":{}},{"cell_type":"code","source":"from tensorflow.keras import applications\nfrom tensorflow.keras.layers import Input, GlobalAveragePooling2D, Dense, Dropout\nfrom tensorflow.keras.models import Model\n\ndef create_mobilenet_model(input_shape, n_out):\n    input_tensor = Input(shape=input_shape)\n    base_model = applications.MobileNet(weights='imagenet', \n                                        include_top=False,\n                                        input_tensor=input_tensor)\n\n    x = GlobalAveragePooling2D()(base_model.output)\n    x = Dropout(0.5)(x)\n    x = Dense(2048, activation='relu')(x)\n    x = Dropout(0.5)(x)\n    final_output = Dense(n_out, activation='softmax', name='final_output')(x)\n    model = Model(input_tensor, final_output)\n    \n    return model\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"mobilenet_model = create_mobilenet_model(input_shape=(HEIGHT, WIDTH, CANAL), n_out=N_CLASSES)\n\n# Freeze all layers and then unfreeze the last 5\nfor layer in mobilenet_model.layers:\n    layer.trainable = False\n\nfor i in range(-5, 0):\n    mobilenet_model.layers[i].trainable = True\n\n# Learning rate warm-up\nmetric_list = [\"accuracy\"]\nWARMUP_LEARNING_RATE = 1e-4\noptimizer = optimizers.Adam(learning_rate=WARMUP_LEARNING_RATE)\nmobilenet_model.compile(optimizer=optimizer, loss=\"categorical_crossentropy\", metrics=metric_list)\n\nmobilenet_model.summary()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Train the top layers of the model\nSTEP_SIZE_TRAIN = train_generator.n//train_generator.batch_size\nSTEP_SIZE_VALID = valid_generator.n//valid_generator.batch_size\n\nhistory_warmup = mobilenet_model.fit(\n    train_generator,\n    steps_per_epoch=STEP_SIZE_TRAIN,\n    validation_data=valid_generator,\n    validation_steps=STEP_SIZE_VALID,\n    epochs=WARMUP_EPOCHS,\n    verbose=1\n).history","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Finetune the complete model\nfor layer in mobilenet_model.layers:\n    layer.trainable = True\n\n# es = EarlyStopping(monitor='val_loss', mode='min', patience=ES_PATIENCE, restore_best_weights=True, verbose=1)\nrlrop = ReduceLROnPlateau(monitor='val_loss', mode='min', patience=RLROP_PATIENCE, factor=DECAY_DROP, min_lr=1e-6, verbose=1)\n\n# callback_list = [es, rlrop]\ncallback_list = [rlrop]\noptimizer = optimizers.Adam(learning_rate=LEARNING_RATE)\nmobilenet_model.compile(optimizer=optimizer, loss=\"binary_crossentropy\",  metrics=metric_list)\nmobilenet_model.summary()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"try:\n    history_finetuning = mobilenet_model.fit(\n        train_generator,\n        steps_per_epoch=STEP_SIZE_TRAIN,\n        validation_data=valid_generator,\n        validation_steps=STEP_SIZE_VALID,\n        epochs=30,\n        callbacks=callback_list,\n        verbose=1\n    ).history\nexcept Exception as e:\n    print(\"An error occurred during training:\", e)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Model loss graph\nhistory = {\n    'loss': history_warmup['loss'] + history_finetuning['loss'],\n    'val_loss': history_warmup['val_loss'] + history_finetuning['val_loss'],\n    'accuracy': history_warmup['accuracy'] + history_finetuning['accuracy'],\n    'val_accuracy': history_warmup['val_accuracy'] + history_finetuning['val_accuracy']\n}\n\nsns.set_style(\"whitegrid\")\nfig, (ax1, ax2) = plt.subplots(2, 1, sharex='col', figsize=(20, 14))\n\nax1.plot(history['loss'], label='Train loss')\nax1.plot(history['val_loss'], label='Validation loss')\nax1.legend(loc='best')\nax1.set_title('Loss')\n\nax2.plot(history['accuracy'], label='Train Accuracy')\nax2.plot(history['val_accuracy'], label='Validation accuracy')\nax2.legend(loc='best')\nax2.set_title('Accuracy')\n\nplt.xlabel('Epochs')\nsns.despine()\nplt.show()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Model Evaluation\ncomplete_datagen = ImageDataGenerator(rescale=1./255)\ncomplete_generator = complete_datagen.flow_from_dataframe(  \n        dataframe=train,\n        directory = \"../input/aptos2019-blindness-detection/train_images/\",\n        x_col=\"id_code\",\n        target_size=(HEIGHT, WIDTH),\n        batch_size=1,\n        shuffle=False,\n        class_mode=None)\n\nSTEP_SIZE_COMPLETE = complete_generator.n//complete_generator.batch_size\ntrain_preds = mobilenet_model.predict(complete_generator, steps=STEP_SIZE_COMPLETE)\ntrain_preds = [np.argmax(pred) for pred in train_preds]","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Confusion Matrix\nlabels = ['0 - No DR', '1 - Mild', '2 - Moderate', '3 - Severe', '4 - Proliferative DR']\ncnf_matrix = confusion_matrix(train['diagnosis'].astype('int'), train_preds)\ncnf_matrix_norm = cnf_matrix.astype('float') / cnf_matrix.sum(axis=1)[:, np.newaxis]\ndf_cm = pd.DataFrame(cnf_matrix_norm, index=labels, columns=labels)\nplt.figure(figsize=(16, 7))\nsns.heatmap(df_cm, annot=True, fmt='.2f', cmap=\"Blues\")\nplt.show()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Finding the Quadratic Kappa Score\nprint(\"Train Cohen Kappa score: %.3f\" % cohen_kappa_score(train_preds, train['diagnosis'].astype('int'), weights='quadratic'))","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"mobilenet_model.save(\"/kaggle/working/moblenet_diabetic_retinopathy_model.h5\")","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}