{"metadata":{"kernelspec":{"name":"python3","display_name":"Python 3","language":"python"},"language_info":{"name":"python","version":"3.10.14","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"colab":{"provenance":[],"gpuType":"T4","authorship_tag":"ABX9TyMMoH7HODhckK0EGkumTl22"},"accelerator":"GPU","kaggle":{"accelerator":"gpu","dataSources":[{"sourceId":2516988,"sourceType":"datasetVersion","datasetId":1172856}],"dockerImageVersionId":30775,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport cv2\nimport os\nfrom sklearn.metrics import classification_report, confusion_matrix, precision_score, recall_score\nimport tensorflow as tf\nfrom tensorflow import keras\nfrom tensorflow.keras import layers, models,callbacks,optimizers\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator\nfrom tensorflow.keras.applications import ResNet50, Xception\nfrom tensorflow.keras.callbacks import EarlyStopping, ReduceLROnPlateau\nfrom tensorflow.keras.models import Model\nfrom tensorflow.keras.layers import Dense, GlobalAveragePooling2D,Dense,concatenate,Input,Dropout,BatchNormalization, GaussianNoise\nfrom tensorflow.keras.optimizers import Adam\nfrom sklearn.metrics import ConfusionMatrixDisplay\nfrom glob import glob\nfrom sklearn.metrics import roc_curve, auc, cohen_kappa_score\nfrom sklearn.preprocessing import label_binarize\nfrom sklearn.metrics import RocCurveDisplay\nfrom itertools import cycle\nfrom sklearn.metrics import f1_score","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-24T23:37:16.221041Z","iopub.execute_input":"2024-11-24T23:37:16.221385Z","iopub.status.idle":"2024-11-24T23:37:27.846445Z","shell.execute_reply.started":"2024-11-24T23:37:16.221356Z","shell.execute_reply":"2024-11-24T23:37:27.845568Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Check if GPU is available\nprint(\"Num GPUs Available: \", len(tf.config.list_physical_devices('GPU')))\n\n# To check GPU status\n!nvidia-smi","metadata":{"id":"U9Iovhk8SDOk","executionInfo":{"status":"ok","timestamp":1727607130036,"user_tz":-330,"elapsed":369,"user":{"displayName":"Akshayana","userId":"01322199543632063170"}},"trusted":true,"execution":{"iopub.status.busy":"2024-11-24T23:37:27.848021Z","iopub.execute_input":"2024-11-24T23:37:27.848947Z","iopub.status.idle":"2024-11-24T23:37:29.081420Z","shell.execute_reply.started":"2024-11-24T23:37:27.848904Z","shell.execute_reply":"2024-11-24T23:37:29.080300Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"for dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\ntrain_dir = r\"/kaggle/input/diabetic-retinopathy-level-detection/preprocessed dataset/preprocessed dataset/training\"\ntest_dir = r\"/kaggle/input/diabetic-retinopathy-level-detection/preprocessed dataset/preprocessed dataset/testing\"","metadata":{"id":"R5ESrSPTSYpu","executionInfo":{"status":"ok","timestamp":1727607136314,"user_tz":-330,"elapsed":372,"user":{"displayName":"Akshayana","userId":"01322199543632063170"}},"outputId":"87b298f4-1b19-4573-9639-ecea581c8e76","trusted":true,"execution":{"iopub.status.busy":"2024-11-24T23:37:29.082928Z","iopub.execute_input":"2024-11-24T23:37:29.083242Z","iopub.status.idle":"2024-11-24T23:37:41.622278Z","shell.execute_reply.started":"2024-11-24T23:37:29.083212Z","shell.execute_reply":"2024-11-24T23:37:41.621371Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Image parameters\nIMG_HEIGHT, IMG_WIDTH = 224, 224  # ResNet50 and Xception input size\nBATCH_SIZE = 64","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-24T23:37:41.624761Z","iopub.execute_input":"2024-11-24T23:37:41.625034Z","iopub.status.idle":"2024-11-24T23:37:41.628830Z","shell.execute_reply.started":"2024-11-24T23:37:41.625006Z","shell.execute_reply":"2024-11-24T23:37:41.627987Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Image enhancement function using histogram equalization and intensity normalization\ndef enhance_image(img):\n    # Histogram Equalization\n    img_yuv = cv2.cvtColor(img, cv2.COLOR_RGB2YUV)\n    img_yuv[:, :, 0] = cv2.equalizeHist(img_yuv[:, :, 0])\n    img_enhanced = cv2.cvtColor(img_yuv, cv2.COLOR_YUV2RGB)\n\n    # Intensity Normalization\n    img_normalized = (img_enhanced - img_enhanced.min()) / (img_enhanced.max() - img_enhanced.min())\n\n    return img_normalized","metadata":{"id":"TY8XRU9cSt4S","executionInfo":{"status":"ok","timestamp":1727607487938,"user_tz":-330,"elapsed":353,"user":{"displayName":"Akshayana","userId":"01322199543632063170"}},"trusted":true,"execution":{"iopub.status.busy":"2024-11-24T23:37:41.629793Z","iopub.execute_input":"2024-11-24T23:37:41.630001Z","iopub.status.idle":"2024-11-24T23:37:41.638699Z","shell.execute_reply.started":"2024-11-24T23:37:41.629979Z","shell.execute_reply":"2024-11-24T23:37:41.637969Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Data generators with enhancement\nclass EnhancedImageDataGenerator(ImageDataGenerator):\n    def __init__(self, **kwargs):\n        super().__init__(**kwargs)\n\n    def flow_from_directory(self, directory, *args, **kwargs):\n        generator = super().flow_from_directory(directory, *args, **kwargs)\n        while True:\n            batch_x, batch_y = next(generator)\n            batch_x = np.array([enhance_image(img) for img in batch_x])\n            yield batch_x, batch_y","metadata":{"id":"n0ml7mimS7kz","trusted":true,"execution":{"iopub.status.busy":"2024-11-24T23:37:41.639697Z","iopub.execute_input":"2024-11-24T23:37:41.639929Z","iopub.status.idle":"2024-11-24T23:37:41.650680Z","shell.execute_reply.started":"2024-11-24T23:37:41.639907Z","shell.execute_reply":"2024-11-24T23:37:41.649930Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_datagen = ImageDataGenerator(\n    rescale=1.0/255,\n    rotation_range=40,\n    width_shift_range=0.2,\n    height_shift_range=0.3,\n    shear_range=0.2,\n    zoom_range=0.3,\n    horizontal_flip=True,\n    fill_mode='nearest'\n)\n\ntest_datagen = ImageDataGenerator(rescale=1.0/255)\ntrain_generator = train_datagen.flow_from_directory(\n    train_dir,\n    target_size=(IMG_HEIGHT, IMG_WIDTH),\n    batch_size=BATCH_SIZE,\n    class_mode='categorical'\n)\n\ntest_generator = test_datagen.flow_from_directory(\n    test_dir,\n    target_size=(IMG_HEIGHT, IMG_WIDTH),\n    batch_size=BATCH_SIZE,\n    class_mode='categorical',\n    shuffle=False\n)","metadata":{"id":"0qpxjjvhWCD9","trusted":true,"execution":{"iopub.status.busy":"2024-11-24T23:37:41.651609Z","iopub.execute_input":"2024-11-24T23:37:41.651860Z","iopub.status.idle":"2024-11-24T23:37:43.110973Z","shell.execute_reply.started":"2024-11-24T23:37:41.651823Z","shell.execute_reply":"2024-11-24T23:37:43.110122Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import matplotlib.pyplot as plt\nimport cv2\nimport os\nimport numpy as np\nimport random\n\n# Function to load one random image per class\ndef load_one_image_per_class(directory, target_size=(224, 224)):\n    images = []\n    labels = []\n    class_labels = sorted(os.listdir(directory))  # Ensure classes are sorted for consistency\n    for class_idx, class_name in enumerate(class_labels):\n        class_path = os.path.join(directory, class_name)\n        if os.path.isdir(class_path):\n            image_files = os.listdir(class_path)\n            if image_files:  # Ensure the class has at least one image\n                random_file = random.choice(image_files)  # Pick one random image\n                img_path = os.path.join(class_path, random_file)\n                img = cv2.imread(img_path)  # Read image\n                if img is not None:\n                    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)  # Convert to RGB\n                    img = cv2.resize(img, target_size)  # Resize to uniform dimensions\n                    images.append(img)\n                    labels.append(class_idx)\n        # Stop after collecting one image per class if we reach the desired count\n        if len(images) == 5:  # Ensure only 5 images are selected\n            break\n    return np.array(images), np.array(labels)\n\n# Load 5 random images, each from a different class\nraw_images, raw_labels = load_one_image_per_class(train_dir, target_size=(IMG_HEIGHT, IMG_WIDTH))\n\n# Apply image enhancement to the raw images\nenhanced_images = np.array([enhance_image(img) for img in raw_images])\n\n# Visualize raw and enhanced images side-by-side\nplt.figure(figsize=(15, 6))\n\nfor i in range(5):  # Iterate over the 5 selected images\n    # Raw Image\n    plt.subplot(2, 5, i + 1)\n    plt.imshow(raw_images[i])\n    plt.title(f\"Raw\\nClass: {raw_labels[i]}\")\n    plt.axis(\"off\")\n\n    # Enhanced Image\n    plt.subplot(2, 5, i + 1 + 5)\n    plt.imshow(enhanced_images[i])\n    plt.title(f\"Enhanced\\nClass: {raw_labels[i]}\")\n    plt.axis(\"off\")\n\nplt.tight_layout()\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-24T23:59:22.735817Z","iopub.execute_input":"2024-11-24T23:59:22.736661Z","iopub.status.idle":"2024-11-24T23:59:24.904417Z","shell.execute_reply.started":"2024-11-24T23:59:22.736625Z","shell.execute_reply":"2024-11-24T23:59:24.903572Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from tensorflow.keras.applications import InceptionV3\nfrom tensorflow.keras.models import Model\nfrom tensorflow.keras.layers import Dense, Dropout, BatchNormalization, GlobalAveragePooling2D, Input\nfrom tensorflow.keras.optimizers import Adam\n\n# Ensure GPU utilization\nwith tf.device('/GPU:0'):\n    def create_inceptionv3_model():\n        # Load the InceptionV3 base model\n        base_model = InceptionV3(weights='imagenet', include_top=False, input_shape=(IMG_HEIGHT, IMG_WIDTH, 3))\n\n        # Make the last few layers trainable for fine-tuning\n        for layer in base_model.layers:\n            layer.trainable = True\n\n        # Input layer\n        inputs = Input(shape=(IMG_HEIGHT, IMG_WIDTH, 3))\n\n        # Connect inputs to the base model\n        x = base_model(inputs, training=False)\n\n        # Add Global Average Pooling\n        x = GlobalAveragePooling2D()(x)\n\n        # Add Fully Connected layers\n        x = Dense(256, activation='relu')(x)\n        x = BatchNormalization()(x)\n        x = Dropout(0.5)(x)\n\n        # Add output layer with softmax activation\n        outputs = Dense(train_generator.num_classes, activation='softmax')(x)\n\n        # Create the model\n        model = Model(inputs, outputs)\n        model.compile(optimizer=Adam(learning_rate=0.001), loss='categorical_crossentropy', metrics=['accuracy'])\n\n        return model\n\n# Instantiate the InceptionV3-based model\nmodel = create_inceptionv3_model()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-24T23:37:53.360417Z","iopub.status.idle":"2024-11-24T23:37:53.360736Z","shell.execute_reply.started":"2024-11-24T23:37:53.360584Z","shell.execute_reply":"2024-11-24T23:37:53.360600Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Callbacks for early stopping and learning rate adjustment\nearly_stopping = callbacks.EarlyStopping(monitor='val_loss', patience=10, restore_best_weights=True)  # Patience reduced from 10 to 5\nreduce_lr = callbacks.ReduceLROnPlateau(monitor='val_loss', factor=0.1, patience=3, min_lr=1e-6)","metadata":{"id":"YFrXOLg3TAJg","trusted":true,"execution":{"iopub.status.busy":"2024-11-24T23:37:53.362303Z","iopub.status.idle":"2024-11-24T23:37:53.362738Z","shell.execute_reply.started":"2024-11-24T23:37:53.362507Z","shell.execute_reply":"2024-11-24T23:37:53.362529Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class_names = {0: 'no_DR', 1: 'mild_DR', 2: 'moderate_DR', 3: 'severe_DR', 4: 'proliferative_DR'}\ndata = []\n\n# Loop through the training directory and collect image names and their labels\nfor class_id in class_names.keys():\n    class_folder = os.path.join(train_dir, str(class_id))\n    for filename in os.listdir(class_folder):\n        if filename.endswith(\".png\"):  # or your image extension\n            data.append([filename, class_id])\n\n# Create a DataFrame and save it as CSV\nlabels_df = pd.DataFrame(data, columns=['image', 'level'])\nlabels_df.to_csv('/kaggle/working/trainLabels.csv', index=False)\n\nlabels_csv = r\"/kaggle/working/trainLabels.csv\"  # Update this path\nlabels_df = pd.read_csv(labels_csv)\nfrom sklearn.utils.class_weight import compute_class_weight\n\nclass_weights = compute_class_weight(\n    'balanced', \n    classes=np.unique(labels_df['level']),  # Unique class labels\n    y=labels_df['level']  # The actual labels\n)\n\nclass_weights_dict = {i: weight for i, weight in enumerate(class_weights)}\nprint(class_weights_dict)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-24T23:37:53.364077Z","iopub.status.idle":"2024-11-24T23:37:53.364522Z","shell.execute_reply.started":"2024-11-24T23:37:53.364304Z","shell.execute_reply":"2024-11-24T23:37:53.364328Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"with tf.device('/GPU:0'):\n    history = model.fit(\n        train_generator,  # Subset used\n        validation_data=test_generator,\n        epochs=50,  # Reduced from 50 to 20 epochs\n        steps_per_epoch=len(train_generator) // BATCH_SIZE,\n        validation_steps=len(test_generator) // BATCH_SIZE,\n        class_weight=class_weights_dict,  # Use class weights\n        callbacks=[early_stopping, reduce_lr]\n    )","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-24T23:37:53.366396Z","iopub.status.idle":"2024-11-24T23:37:53.366717Z","shell.execute_reply.started":"2024-11-24T23:37:53.366567Z","shell.execute_reply":"2024-11-24T23:37:53.366582Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Save the trained model\nmodel.save('Updated-Xception-ResNet50-diabetic-retinopathy.h5')","metadata":{"id":"de81ykGRTnHL","trusted":true,"execution":{"iopub.status.busy":"2024-11-24T23:37:53.367734Z","iopub.status.idle":"2024-11-24T23:37:53.368019Z","shell.execute_reply.started":"2024-11-24T23:37:53.367880Z","shell.execute_reply":"2024-11-24T23:37:53.367894Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Evaluate the model\nwith tf.device('/GPU:0'):\n  test_loss, test_accuracy = model.evaluate(test_generator)","metadata":{"id":"Sy1C1T2WWqgp","trusted":true,"execution":{"iopub.status.busy":"2024-11-24T23:37:53.369210Z","iopub.status.idle":"2024-11-24T23:37:53.369471Z","shell.execute_reply.started":"2024-11-24T23:37:53.369341Z","shell.execute_reply":"2024-11-24T23:37:53.369354Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Generate predictions\nwith tf.device('/GPU:0'):\n  predictions = model.predict(test_generator)\ny_pred = np.argmax(predictions, axis=1)\ny_true = test_generator.classes  # True labels","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-24T23:37:53.370260Z","iopub.status.idle":"2024-11-24T23:37:53.370554Z","shell.execute_reply.started":"2024-11-24T23:37:53.370412Z","shell.execute_reply":"2024-11-24T23:37:53.370429Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Calculate evaluation metrics\nprecision = precision_score(y_true, y_pred, average='weighted')\nsensitivity = recall_score(y_true, y_pred, average='weighted')\nfrom sklearn.metrics import f1_score\nf1 = f1_score(y_true, y_pred, average='weighted')","metadata":{"id":"xqJo7IeJWuG9","trusted":true,"execution":{"iopub.status.busy":"2024-11-24T23:37:53.371671Z","iopub.status.idle":"2024-11-24T23:37:53.371935Z","shell.execute_reply.started":"2024-11-24T23:37:53.371803Z","shell.execute_reply":"2024-11-24T23:37:53.371817Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Calculate confusion matrix for specificity\ncm = confusion_matrix(y_true, y_pred)\nTN = cm.sum() - (cm.sum(axis=0) + cm.sum(axis=1) - cm.diagonal())  # True Negatives\nFP = cm.sum(axis=0) - cm.diagonal()  # False Positives","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-24T23:37:53.373046Z","iopub.status.idle":"2024-11-24T23:37:53.373353Z","shell.execute_reply.started":"2024-11-24T23:37:53.373215Z","shell.execute_reply":"2024-11-24T23:37:53.373230Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Calculate specificity for each class\nspecificity_list = []\nfor i in range(cm.shape[0]):  # Loop through each class\n    TN = cm.sum() - (cm.sum(axis=0)[i] + cm.sum(axis=1)[i] - cm[i, i])  # True Negatives\n    FP = cm.sum(axis=0)[i] - cm[i, i]  # False Positives\n    specificity = TN / (TN + FP) if (TN + FP) > 0 else 0  # Avoid division by zero\n    specificity_list.append(specificity)\naverage_specificity = np.mean(specificity_list)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-24T23:37:53.374764Z","iopub.status.idle":"2024-11-24T23:37:53.375060Z","shell.execute_reply.started":"2024-11-24T23:37:53.374922Z","shell.execute_reply":"2024-11-24T23:37:53.374937Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from sklearn.metrics import roc_curve, auc, cohen_kappa_score\nfrom sklearn.preprocessing import label_binarize\nfrom sklearn.metrics import RocCurveDisplay\nfrom itertools import cycle\n\n# Binarize the output for ROC Curve (one-vs-all approach)\ny_true_binarized = label_binarize(y_true, classes=np.arange(train_generator.num_classes))\nn_classes = y_true_binarized.shape[1]\nkappa = cohen_kappa_score(y_true, y_pred)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-24T23:37:53.376070Z","iopub.status.idle":"2024-11-24T23:37:53.376400Z","shell.execute_reply.started":"2024-11-24T23:37:53.376244Z","shell.execute_reply":"2024-11-24T23:37:53.376259Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Print metrics\nprint(f\"Test Accuracy: {test_accuracy:.4f}\")\nprint(f\"Precision: {precision:.4f}\")\nprint(f\"Sensitivity (Recall): {sensitivity:.4f}\")\nprint(f\"F1 Score: {f1:.4f}\")\nfor i, spec in enumerate(specificity_list):\n    print(f\"Class {i}: Specificity: {spec:.4f}\")\nprint(f\"Specificty : {average_specificity :.4f}\")\nprint(f\"Cohen's Kappa Score: {kappa:.4f}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-24T23:37:53.377898Z","iopub.status.idle":"2024-11-24T23:37:53.378231Z","shell.execute_reply.started":"2024-11-24T23:37:53.378051Z","shell.execute_reply":"2024-11-24T23:37:53.378065Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Plotting the evaluation metrics\nepochs = range(len(history.history['accuracy']))\nn_classes = len(specificity_list)\ncolors = cycle(['blue', 'red', 'green', 'orange', 'purple'])\nplt.figure(figsize=(18, 20))\nplt.plot(epochs, history.history['accuracy'], label='Train Accuracy')\nplt.plot(epochs, history.history['val_accuracy'], label='Validation Accuracy')\nplt.title('Accuracy')\nplt.xlabel('Epochs')\nplt.ylabel('Accuracy')\nplt.legend()\nplt.show()\n\n# Loss plot\nplt.plot(epochs, history.history['loss'], label='Train Loss')\nplt.plot(epochs, history.history['val_loss'], label='Validation Loss')\nplt.title('Loss')\nplt.xlabel('Epochs')\nplt.ylabel('Loss')\nplt.legend()\nplt.show()\n\n# ROC Curve\nfor i, color in zip(range(n_classes), colors):\n    fpr, tpr, _ = roc_curve(y_true_binarized[:, i], predictions[:, i])\n    roc_auc = auc(fpr, tpr)\n    plt.plot(fpr, tpr, color=color, lw=2,\n             label=f'Class {i} (AUC = {roc_auc:.2f})')\nplt.plot([0, 1], [0, 1], 'k--', lw=2)\nplt.xlim([0.0, 1.0])\nplt.ylim([0.0, 1.05])\nplt.xlabel('False Positive Rate')\nplt.ylabel('True Positive Rate')\nplt.title('Receiver Operating Characteristic (ROC) Curve')\nplt.legend(loc=\"lower right\")\n\nplt.show()\n# Confusion Matrix\nConfusionMatrixDisplay(confusion_matrix=cm, display_labels=test_generator.class_indices).plot(cmap=plt.cm.Blues)\nplt.title('Confusion Matrix')\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-24T23:37:53.379497Z","iopub.status.idle":"2024-11-24T23:37:53.379924Z","shell.execute_reply.started":"2024-11-24T23:37:53.379707Z","shell.execute_reply":"2024-11-24T23:37:53.379731Z"}},"outputs":[],"execution_count":null}]}