{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.12.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[],"dockerImageVersionId":28755,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# ============================================================\n# CELL 1: IMPORT REQUIRED LIBRARIES\n# ============================================================\n\nimport os\nimport numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport seaborn as sns\n\n# Image processing\nfrom PIL import Image\n\n# Progress bar\nfrom tqdm import tqdm\n\n# Train / validation / test splitting\nfrom sklearn.model_selection import train_test_split\n\nprint(\"All libraries imported successfully!\")","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2026-09-27T15:16:21.599749Z","iopub.execute_input":"2026-09-27T15:16:21.600452Z","iopub.status.idle":"2026-09-27T15:16:21.640284Z","shell.execute_reply.started":"2026-09-27T15:16:21.600406Z","shell.execute_reply":"2026-09-27T15:16:21.639496Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# CELL 2: DEFINE DATASET PATHS\n# ============================================================\n\n# APTOS dataset path\nAPTOS_PATH = \"/kaggle/input/competitions/aptos2019-blindness-detection\"\n\n# EyePACS dataset path\nEYEPACS_PATH = \"/kaggle/input/datasets/faizan729/diabetic-retinopathy-detection\"\n\n# APTOS training images\nAPTOS_IMAGE_PATH = os.path.join(\n    APTOS_PATH,\n    \"train_images\"\n)\n\n# EyePACS training images\nEYEPACS_IMAGE_PATH = os.path.join(\n    EYEPACS_PATH,\n    \"train\"\n)\n\nprint(\"APTOS path:\")\nprint(APTOS_IMAGE_PATH)\n\nprint(\"\\nEyePACS path:\")\nprint(EYEPACS_IMAGE_PATH)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-27T15:16:25.629482Z","iopub.execute_input":"2026-09-27T15:16:25.630441Z","iopub.status.idle":"2026-09-27T15:16:25.63533Z","shell.execute_reply.started":"2026-09-27T15:16:25.630392Z","shell.execute_reply":"2026-09-27T15:16:25.634429Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# CELL 3: CHECK WHETHER DATASET PATHS EXIST\n# ============================================================\n\nprint(\n    \"APTOS dataset exists:\",\n    os.path.exists(APTOS_PATH)\n)\n\nprint(\n    \"APTOS images folder exists:\",\n    os.path.exists(APTOS_IMAGE_PATH)\n)\n\nprint(\n    \"EyePACS dataset exists:\",\n    os.path.exists(EYEPACS_PATH)\n)\n\nprint(\n    \"EyePACS images folder exists:\",\n    os.path.exists(EYEPACS_IMAGE_PATH)\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-27T15:16:38.701336Z","iopub.execute_input":"2026-09-27T15:16:38.702101Z","iopub.status.idle":"2026-09-27T15:16:38.707461Z","shell.execute_reply.started":"2026-09-27T15:16:38.70207Z","shell.execute_reply":"2026-09-27T15:16:38.706768Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# CELL 4: DISPLAY DATASET CONTENTS\n# ============================================================\n\nprint(\"APTOS dataset contents:\")\nprint(os.listdir(APTOS_PATH))\n\nprint(\"\\nEyePACS dataset contents:\")\nprint(os.listdir(EYEPACS_PATH))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-27T15:16:41.255705Z","iopub.execute_input":"2026-09-27T15:16:41.25618Z","iopub.status.idle":"2026-09-27T15:16:41.266622Z","shell.execute_reply.started":"2026-09-27T15:16:41.256155Z","shell.execute_reply":"2026-09-27T15:16:41.265898Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# CELL 5: LOAD APTOS LABEL CSV\n# ============================================================\n\nAPTOS_CSV = os.path.join(\n    APTOS_PATH,\n    \"train.csv\"\n)\n\naptos_df = pd.read_csv(APTOS_CSV)\n\nprint(\"APTOS dataset shape:\")\nprint(aptos_df.shape)\n\nprint(\"\\nFirst 5 rows:\")\ndisplay(aptos_df.head())\n\nprint(\"\\nColumns:\")\nprint(aptos_df.columns)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-27T15:16:45.066009Z","iopub.execute_input":"2026-09-27T15:16:45.066417Z","iopub.status.idle":"2026-09-27T15:16:45.160426Z","shell.execute_reply.started":"2026-09-27T15:16:45.066388Z","shell.execute_reply":"2026-09-27T15:16:45.159687Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# CELL 6: CHECK APTOS CLASS DISTRIBUTION\n# ============================================================\n\nprint(\"APTOS class distribution:\")\n\nprint(\n    aptos_df[\"diagnosis\"].value_counts().sort_index()\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-27T15:16:48.441933Z","iopub.execute_input":"2026-09-27T15:16:48.442723Z","iopub.status.idle":"2026-09-27T15:16:48.474787Z","shell.execute_reply.started":"2026-09-27T15:16:48.442695Z","shell.execute_reply":"2026-09-27T15:16:48.474199Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# CELL 7: LOAD EYEPACS TRAINING LABELS\n# ============================================================\n\n# EyePACS training folder\nEYEPACS_TRAIN_PATH = os.path.join(\n    EYEPACS_PATH,\n    \"train\"\n)\n\n# EyePACS training CSV\nEYEPACS_CSV = os.path.join(\n    EYEPACS_TRAIN_PATH,\n    \"_classes.csv\"\n)\n\n# Load CSV\neye_df = pd.read_csv(EYEPACS_CSV)\n\nprint(\"EyePACS training dataset shape:\")\nprint(eye_df.shape)\n\nprint(\"\\nFirst 5 rows:\")\ndisplay(eye_df.head())\n\nprint(\"\\nColumns:\")\nprint(eye_df.columns.tolist())","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-27T15:16:51.042427Z","iopub.execute_input":"2026-09-27T15:16:51.04307Z","iopub.status.idle":"2026-09-27T15:16:51.082972Z","shell.execute_reply.started":"2026-09-27T15:16:51.04304Z","shell.execute_reply":"2026-09-27T15:16:51.082355Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# CELL 8: CONVERT EYEPACS LABELS INTO CLASS NUMBERS\n# ============================================================\n\nlabel_columns = [\n    \" No_DR\",\n    \" Mild\",\n    \" Moderate\",\n    \" Severe\",\n    \" Proliferate_DR\"\n]\n\n# Convert one-hot labels into a single class number\neye_df[\"diagnosis\"] = (\n    eye_df[label_columns]\n    .values\n    .argmax(axis=1)\n)\n\nprint(\n    eye_df[\n        [\"filename\", \"diagnosis\"]\n    ].head()\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-27T15:16:57.419553Z","iopub.execute_input":"2026-09-27T15:16:57.420246Z","iopub.status.idle":"2026-09-27T15:16:57.427916Z","shell.execute_reply.started":"2026-09-27T15:16:57.420218Z","shell.execute_reply":"2026-09-27T15:16:57.427166Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# DEFINE DIABETIC RETINOPATHY CLASS NAMES\n# ============================================================\n\nclass_names = [\n    \"No DR\",\n    \"Mild\",\n    \"Moderate\",\n    \"Severe\",\n    \"Proliferative DR\"\n]\n\nprint(\"Classes:\")\n\nfor i, name in enumerate(class_names):\n    print(f\"Class {i}: {name}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-27T15:17:07.725804Z","iopub.execute_input":"2026-09-27T15:17:07.72671Z","iopub.status.idle":"2026-09-27T15:17:07.731546Z","shell.execute_reply.started":"2026-09-27T15:17:07.726659Z","shell.execute_reply":"2026-09-27T15:17:07.730684Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# CELL 9: CHECK EYEPACS CLASS DISTRIBUTION\n# ============================================================\n\nprint(\"EyePACS class distribution:\\n\")\n\nunique, counts = np.unique(\n    eye_df[\"diagnosis\"],\n    return_counts=True\n)\n\nfor class_id, count in zip(unique, counts):\n\n    print(\n        f\"Class {class_id} \"\n        f\"({class_names[class_id]}): \"\n        f\"{count}\"\n    )","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-27T15:17:15.17653Z","iopub.execute_input":"2026-09-27T15:17:15.176924Z","iopub.status.idle":"2026-09-27T15:17:15.183247Z","shell.execute_reply.started":"2026-09-27T15:17:15.176898Z","shell.execute_reply":"2026-09-27T15:17:15.182495Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"EYEPACS_IMAGE_PATH = os.path.join(\n    EYEPACS_PATH,\n    \"train\"\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-27T15:17:19.039684Z","iopub.execute_input":"2026-09-27T15:17:19.040486Z","iopub.status.idle":"2026-09-27T15:17:19.044163Z","shell.execute_reply.started":"2026-09-27T15:17:19.040442Z","shell.execute_reply":"2026-09-27T15:17:19.043411Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# CELL 10: VERIFY EYEPACS TRAINING IMAGE PATH\n# ============================================================\n\nprint(\"EyePACS training image path:\")\nprint(EYEPACS_TRAIN_PATH)\n\nprint(\n    \"\\nFolder exists:\",\n    os.path.exists(EYEPACS_TRAIN_PATH)\n)\n\nprint(\"\\nFirst few files:\")\n\nprint(\n    os.listdir(EYEPACS_TRAIN_PATH)[:10]\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-27T15:19:17.096444Z","iopub.execute_input":"2026-09-27T15:19:17.097186Z","iopub.status.idle":"2026-09-27T15:19:17.10793Z","shell.execute_reply.started":"2026-09-27T15:19:17.097158Z","shell.execute_reply":"2026-09-27T15:19:17.107231Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"\nIMG_SIZE = 128\n\nprint(\"Image size:\", IMG_SIZE, \"x\", IMG_SIZE)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-27T15:19:20.91821Z","iopub.execute_input":"2026-09-27T15:19:20.918474Z","iopub.status.idle":"2026-09-27T15:19:20.922812Z","shell.execute_reply.started":"2026-09-27T15:19:20.918452Z","shell.execute_reply":"2026-09-27T15:19:20.921923Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# CELL 12: LOAD APTOS IMAGES\n# ============================================================\n\nX_aptos = []\ny_aptos = []\n\nprint(\"Loading APTOS images...\")\n\nfor _, row in tqdm(\n    aptos_df.iterrows(),\n    total=len(aptos_df)\n):\n\n    image_name = row[\"id_code\"] + \".png\"\n\n    image_path = os.path.join(\n        APTOS_IMAGE_PATH,\n        image_name\n    )\n\n    # Check if image exists\n    if os.path.exists(image_path):\n\n        # Open image\n        image = Image.open(image_path)\n\n        # Convert to RGB\n        image = image.convert(\"RGB\")\n\n        # Resize image\n        image = image.resize(\n            (IMG_SIZE, IMG_SIZE)\n        )\n\n        # Convert image to NumPy array\n        image = np.array(image)\n\n        X_aptos.append(image)\n        y_aptos.append(row[\"diagnosis\"])\n\n# Convert lists to NumPy arrays\nX_aptos = np.array(X_aptos)\ny_aptos = np.array(y_aptos)\n\nprint(\"\\nAPTOS images shape:\", X_aptos.shape)\nprint(\"APTOS labels shape:\", y_aptos.shape)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-27T15:19:24.729493Z","iopub.execute_input":"2026-09-27T15:19:24.729875Z","iopub.status.idle":"2026-09-27T15:31:38.218004Z","shell.execute_reply.started":"2026-09-27T15:19:24.729847Z","shell.execute_reply":"2026-09-27T15:31:38.217187Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# CELL 13: DISPLAY SAMPLE APTOS IMAGES\n# ============================================================\n\nplt.figure(figsize=(12, 8))\n\nfor i in range(10):\n\n    plt.subplot(2, 5, i + 1)\n\n    plt.imshow(X_aptos[i])\n\n    plt.title(\n        class_names[y_aptos[i]]\n    )\n\n    plt.axis(\"off\")\n\nplt.tight_layout()\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-27T16:35:58.672434Z","iopub.execute_input":"2026-09-27T16:35:58.672686Z","iopub.status.idle":"2026-09-27T16:35:59.323104Z","shell.execute_reply.started":"2026-09-27T16:35:58.672664Z","shell.execute_reply":"2026-09-27T16:35:59.322369Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# CELL 14: LOAD EYEPACS IMAGES\n# ============================================================\n\nX_eye = []\ny_eye = []\n\nprint(\"Loading EyePACS images...\")\n\nfor _, row in tqdm(\n    eye_df.iterrows(),\n    total=len(eye_df)\n):\n\n    image_name = row[\"filename\"]\n\n    image_path = os.path.join(\n        EYEPACS_IMAGE_PATH,\n        image_name\n    )\n\n    # Check whether image exists\n    if os.path.exists(image_path):\n\n        # Open image\n        image = Image.open(image_path)\n\n        # Convert to RGB\n        image = image.convert(\"RGB\")\n\n        # Resize to 128 x 128\n        image = image.resize(\n            (IMG_SIZE, IMG_SIZE)\n        )\n\n        # Convert to NumPy array\n        image = np.array(image)\n\n        X_eye.append(image)\n        y_eye.append(row[\"diagnosis\"])\n\n# Convert lists to NumPy arrays\nX_eye = np.array(X_eye)\ny_eye = np.array(y_eye)\n\nprint(\"\\nEyePACS images shape:\", X_eye.shape)\nprint(\"EyePACS labels shape:\", y_eye.shape)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-27T15:31:52.03088Z","iopub.execute_input":"2026-09-27T15:31:52.031592Z","iopub.status.idle":"2026-09-27T15:33:50.318091Z","shell.execute_reply.started":"2026-09-27T15:31:52.031558Z","shell.execute_reply":"2026-09-27T15:33:50.317294Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# CELL 15: DISPLAY SAMPLE EYEPACS IMAGES\n# ============================================================\n\nplt.figure(figsize=(12, 8))\n\nfor i in range(10):\n\n    plt.subplot(2, 5, i + 1)\n\n    plt.imshow(X_eye[i])\n\n    plt.title(\n        class_names[y_eye[i]]\n    )\n\n    plt.axis(\"off\")\n\nplt.tight_layout()\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-27T12:15:23.974344Z","iopub.execute_input":"2026-09-27T12:15:23.974766Z","iopub.status.idle":"2026-09-27T12:15:24.618608Z","shell.execute_reply.started":"2026-09-27T12:15:23.974738Z","shell.execute_reply":"2026-09-27T12:15:24.617768Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# CELL 16: CHECK BOTH DATASETS BEFORE COMBINING\n# ============================================================\n\nprint(\"APTOS:\")\nprint(\"Images:\", X_aptos.shape)\nprint(\"Labels:\", y_aptos.shape)\n\nprint(\"\\nEyePACS:\")\nprint(\"Images:\", X_eye.shape)\nprint(\"Labels:\", y_eye.shape)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-27T15:34:01.477667Z","iopub.execute_input":"2026-09-27T15:34:01.478393Z","iopub.status.idle":"2026-09-27T15:34:01.482771Z","shell.execute_reply.started":"2026-09-27T15:34:01.478363Z","shell.execute_reply":"2026-09-27T15:34:01.482194Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# CELL 17: COMBINE APTOS AND EYEPACS DATASETS\n# ============================================================\n\nX_combined = np.concatenate(\n    [X_eye, X_aptos],\n    axis=0\n)\n\ny_combined = np.concatenate(\n    [y_eye, y_aptos],\n    axis=0\n)\n\nprint(\"Combined images shape:\")\nprint(X_combined.shape)\n\nprint(\"\\nCombined labels shape:\")\nprint(y_combined.shape)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-27T15:34:04.724256Z","iopub.execute_input":"2026-09-27T15:34:04.72451Z","iopub.status.idle":"2026-09-27T15:34:04.876825Z","shell.execute_reply.started":"2026-09-27T15:34:04.724489Z","shell.execute_reply":"2026-09-27T15:34:04.87619Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# CELL 18: SCALE PIXEL VALUES\n# ============================================================\n\nX_combined = X_combined.astype(\"float32\") / 255.0\n\nprint(\"Minimum pixel value:\", X_combined.min())\nprint(\"Maximum pixel value:\", X_combined.max())","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-27T15:34:08.717951Z","iopub.execute_input":"2026-09-27T15:34:08.718481Z","iopub.status.idle":"2026-09-27T15:34:09.929629Z","shell.execute_reply.started":"2026-09-27T15:34:08.718451Z","shell.execute_reply":"2026-09-27T15:34:09.928961Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# CELL 19: CHECK COMBINED CLASS DISTRIBUTION\n# ============================================================\n\nunique, counts = np.unique(\n    y_combined,\n    return_counts=True\n)\n\nprint(\"Combined dataset class distribution:\\n\")\n\nfor class_id, count in zip(unique, counts):\n\n    print(\n        f\"Class {class_id} \"\n        f\"({class_names[class_id]}): \"\n        f\"{count}\"\n    )","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-27T15:34:12.863051Z","iopub.execute_input":"2026-09-27T15:34:12.863312Z","iopub.status.idle":"2026-09-27T15:34:12.86882Z","shell.execute_reply.started":"2026-09-27T15:34:12.86329Z","shell.execute_reply":"2026-09-27T15:34:12.868243Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# CELL 20: VISUALIZE CLASS DISTRIBUTION\n# ============================================================\n\nplt.figure(figsize=(10, 6))\n\nplt.bar(\n    class_names,\n    counts\n)\n\nplt.xlabel(\"Diabetic Retinopathy Class\")\nplt.ylabel(\"Number of Images\")\nplt.title(\"Combined EyePACS + APTOS Class Distribution\")\n\nplt.xticks(\n    rotation=20\n)\n\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-27T12:16:28.835447Z","iopub.execute_input":"2026-09-27T12:16:28.835936Z","iopub.status.idle":"2026-09-27T12:16:28.948223Z","shell.execute_reply.started":"2026-09-27T12:16:28.835908Z","shell.execute_reply":"2026-09-27T12:16:28.947541Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# CELL 20: VISUALIZE CLASS DISTRIBUTION\n# ============================================================\n\nplt.figure(figsize=(10, 6))\n\nplt.bar(\n    class_names,\n    counts\n)\n\nplt.xlabel(\"Diabetic Retinopathy Class\")\nplt.ylabel(\"Number of Images\")\nplt.title(\"Combined EyePACS + APTOS Class Distribution\")\n\nplt.xticks(\n    rotation=20\n)\n\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-27T12:16:58.539791Z","iopub.execute_input":"2026-09-27T12:16:58.540214Z","iopub.status.idle":"2026-09-27T12:16:58.650728Z","shell.execute_reply.started":"2026-09-27T12:16:58.540184Z","shell.execute_reply":"2026-09-27T12:16:58.649952Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# CELL 22: SPLIT DATA INTO TRAINING AND TESTING\n# ============================================================\n\nX_temp, X_test, y_temp, y_test = train_test_split(\n    X_combined,\n    y_combined,\n    test_size=0.20,\n    random_state=42,\n    stratify=y_combined\n)\n\nprint(\"Temporary training data:\", X_temp.shape)\nprint(\"Testing data:\", X_test.shape)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-27T15:34:22.709444Z","iopub.execute_input":"2026-09-27T15:34:22.710025Z","iopub.status.idle":"2026-09-27T15:34:23.203859Z","shell.execute_reply.started":"2026-09-27T15:34:22.709994Z","shell.execute_reply":"2026-09-27T15:34:23.203205Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# CELL 23: SPLIT TRAINING DATA INTO TRAINING + VALIDATION\n# ============================================================\n\nX_train, X_val, y_train, y_val = train_test_split(\n    X_temp,\n    y_temp,\n    test_size=0.20,\n    random_state=42,\n    stratify=y_temp\n)\n\nprint(\"Training data:\", X_train.shape)\nprint(\"Validation data:\", X_val.shape)\nprint(\"Testing data:\", X_test.shape)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-27T15:34:27.226042Z","iopub.execute_input":"2026-09-27T15:34:27.226684Z","iopub.status.idle":"2026-09-27T15:34:27.626445Z","shell.execute_reply.started":"2026-09-27T15:34:27.226655Z","shell.execute_reply":"2026-09-27T15:34:27.625717Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# CELL 24: VERIFY CLASS DISTRIBUTION\n# ============================================================\n\nprint(\"TRAINING DISTRIBUTION\")\nprint(np.bincount(y_train))\n\nprint(\"\\nVALIDATION DISTRIBUTION\")\nprint(np.bincount(y_val))\n\nprint(\"\\nTESTING DISTRIBUTION\")\nprint(np.bincount(y_test))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-27T15:34:36.697417Z","iopub.execute_input":"2026-09-27T15:34:36.698092Z","iopub.status.idle":"2026-09-27T15:34:36.703408Z","shell.execute_reply.started":"2026-09-27T15:34:36.698065Z","shell.execute_reply":"2026-09-27T15:34:36.702682Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# CELL 25: FINAL DATASET INFORMATION\n# ============================================================\n\nprint(\"=\" * 50)\nprint(\"FINAL DATASET INFORMATION\")\nprint(\"=\" * 50)\n\nprint(\"Training images:   \", X_train.shape)\nprint(\"Validation images: \", X_val.shape)\nprint(\"Testing images:    \", X_test.shape)\n\nprint(\"\\nNumber of classes:\", len(class_names))\n\nprint(\"\\nClass names:\")\n\nfor i, name in enumerate(class_names):\n    print(f\"{i}: {name}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-27T15:34:42.812895Z","iopub.execute_input":"2026-09-27T15:34:42.813499Z","iopub.status.idle":"2026-09-27T15:34:42.81885Z","shell.execute_reply.started":"2026-09-27T15:34:42.813468Z","shell.execute_reply":"2026-09-27T15:34:42.818057Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# GOOGLENET / INCEPTION MODEL FOR DIABETIC RETINOPATHY\n# ============================================================\n\nimport numpy as np\nimport matplotlib.pyplot as plt\nimport seaborn as sns\n\nfrom tensorflow.keras import models\nfrom tensorflow.keras.layers import (\n    Input,\n    Conv2D,\n    MaxPooling2D,\n    GlobalAveragePooling2D,\n    Dense,\n    Dropout,\n    concatenate\n)\n\nfrom sklearn.metrics import (\n    confusion_matrix,\n    classification_report,\n    accuracy_score,\n    f1_score,\n    cohen_kappa_score\n)\n\n\n# ============================================================\n# INCEPTION MODULE\n# ============================================================\n\n# This function defines ONE Inception module\n# Different filter sizes are applied in parallel\n# and their outputs are combined together\n\ndef inception_module(\n    x,\n    f1,\n    f3_reduce,\n    f3,\n    f5_reduce,\n    f5,\n    pool_proj\n):\n\n    # Branch 1: 1x1 convolution\n    conv1 = Conv2D(\n        f1,\n        (1, 1),\n        padding=\"same\",\n        activation=\"relu\"\n    )(x)\n\n    # Branch 2: 1x1 reduction + 3x3 convolution\n    conv3 = Conv2D(\n        f3_reduce,\n        (1, 1),\n        padding=\"same\",\n        activation=\"relu\"\n    )(x)\n\n    conv3 = Conv2D(\n        f3,\n        (3, 3),\n        padding=\"same\",\n        activation=\"relu\"\n    )(conv3)\n\n    # Branch 3: 1x1 reduction + 5x5 convolution\n    conv5 = Conv2D(\n        f5_reduce,\n        (1, 1),\n        padding=\"same\",\n        activation=\"relu\"\n    )(x)\n\n    conv5 = Conv2D(\n        f5,\n        (5, 5),\n        padding=\"same\",\n        activation=\"relu\"\n    )(conv5)\n\n    # Branch 4: max pooling + 1x1 convolution\n    pool = MaxPooling2D(\n        (3, 3),\n        strides=(1, 1),\n        padding=\"same\"\n    )(x)\n\n    pool = Conv2D(\n        pool_proj,\n        (1, 1),\n        padding=\"same\",\n        activation=\"relu\"\n    )(pool)\n\n    # Combine all four branches\n    output = concatenate(\n        [conv1, conv3, conv5, pool],\n        axis=-1\n    )\n\n    return output\n\n\n# ============================================================\n# BUILD GOOGLENET\n# ============================================================\n\ndef build_googlenet(\n    input_shape=(128, 128, 3),\n    num_classes=5\n):\n\n    input_layer = Input(\n        shape=input_shape\n    )\n\n    # Initial feature extraction\n    x = Conv2D(\n        64,\n        (7, 7),\n        strides=(2, 2),\n        padding=\"same\",\n        activation=\"relu\"\n    )(input_layer)\n\n    x = MaxPooling2D(\n        (3, 3),\n        strides=(2, 2),\n        padding=\"same\"\n    )(x)\n\n    x = Conv2D(\n        64,\n        (1, 1),\n        padding=\"same\",\n        activation=\"relu\"\n    )(x)\n\n    x = Conv2D(\n        192,\n        (3, 3),\n        padding=\"same\",\n        activation=\"relu\"\n    )(x)\n\n    x = MaxPooling2D(\n        (3, 3),\n        strides=(2, 2),\n        padding=\"same\"\n    )(x)\n\n\n    # ========================================================\n    # Inception modules\n    # ========================================================\n\n    x = inception_module(\n        x,\n        64,\n        96,\n        128,\n        16,\n        32,\n        32\n    )\n\n    x = inception_module(\n        x,\n        128,\n        128,\n        192,\n        32,\n        96,\n        64\n    )\n\n    x = MaxPooling2D(\n        (3, 3),\n        strides=(2, 2),\n        padding=\"same\"\n    )(x)\n\n\n    x = inception_module(\n        x,\n        192,\n        96,\n        208,\n        16,\n        48,\n        64\n    )\n\n    x = inception_module(\n        x,\n        160,\n        112,\n        224,\n        24,\n        64,\n        64\n    )\n\n    x = inception_module(\n        x,\n        128,\n        128,\n        256,\n        24,\n        64,\n        64\n    )\n\n    x = inception_module(\n        x,\n        112,\n        144,\n        288,\n        32,\n        64,\n        64\n    )\n\n    x = inception_module(\n        x,\n        256,\n        160,\n        320,\n        32,\n        128,\n        128\n    )\n\n    x = MaxPooling2D(\n        (3, 3),\n        strides=(2, 2),\n        padding=\"same\"\n    )(x)\n\n\n    x = inception_module(\n        x,\n        256,\n        160,\n        320,\n        32,\n        128,\n        128\n    )\n\n    x = inception_module(\n        x,\n        384,\n        192,\n        384,\n        48,\n        128,\n        128\n    )\n\n\n    # ========================================================\n    # Classification head\n    # ========================================================\n\n    x = GlobalAveragePooling2D()(x)\n\n    x = Dropout(\n        0.4\n    )(x)\n\n    output_layer = Dense(\n        num_classes,\n        activation=\"softmax\"\n    )(x)\n\n    model = models.Model(\n        inputs=input_layer,\n        outputs=output_layer\n    )\n\n    return model\n\n\n# ============================================================\n# CREATE GOOGLENET MODEL\n# ============================================================\n\ngooglenet_model = build_googlenet(\n    input_shape=(128, 128, 3),\n    num_classes=5\n)\n\ngooglenet_model.summary()\n\n\n# ============================================================\n# COMPILE MODEL\n# ============================================================\n\ngooglenet_model.compile(\n    optimizer=\"adam\",\n    loss=\"sparse_categorical_crossentropy\",\n    metrics=[\"accuracy\"]\n)\n\n\n# ============================================================\n# TRAIN GOOGLENET\n# ============================================================\n\ngooglenet_history = googlenet_model.fit(\n    X_train,\n    y_train,\n    validation_data=(X_val, y_val),\n    epochs=10,\n    batch_size=32,\n    verbose=1\n)\n\n\n# ============================================================\n# EVALUATE MODEL\n# ============================================================\n\ntest_loss, test_accuracy = googlenet_model.evaluate(\n    X_test,\n    y_test,\n    verbose=1\n)\n\nprint(\"GoogLeNet Test Loss:\", test_loss)\nprint(\"GoogLeNet Test Accuracy:\", test_accuracy)\nprint(\n    f\"GoogLeNet Test Accuracy: {test_accuracy:.4f}\"\n)\n\n\n# ============================================================\n# TRAINING ACCURACY GRAPH\n# ============================================================\n\nplt.figure(figsize=(10, 6))\n\nplt.plot(\n    googlenet_history.history[\"accuracy\"],\n    label=\"Training Accuracy\"\n)\n\nplt.plot(\n    googlenet_history.history[\"val_accuracy\"],\n    label=\"Validation Accuracy\"\n)\n\nplt.title(\n    \"GoogLeNet Training and Validation Accuracy\"\n)\n\nplt.xlabel(\n    \"Epochs\"\n)\n\nplt.ylabel(\n    \"Accuracy\"\n)\n\nplt.legend()\n\nplt.grid(\n    True,\n    alpha=0.3\n)\n\nplt.show()\n\n\n# ============================================================\n# TRAINING LOSS GRAPH\n# ============================================================\n\nplt.figure(figsize=(10, 6))\n\nplt.plot(\n    googlenet_history.history[\"loss\"],\n    label=\"Training Loss\"\n)\n\nplt.plot(\n    googlenet_history.history[\"val_loss\"],\n    label=\"Validation Loss\"\n)\n\nplt.title(\n    \"GoogLeNet Training and Validation Loss\"\n)\n\nplt.xlabel(\n    \"Epochs\"\n)\n\nplt.ylabel(\n    \"Loss\"\n)\n\nplt.legend()\n\nplt.grid(\n    True,\n    alpha=0.3\n)\n\nplt.show()\n\n\n# ============================================================\n# PREDICTIONS\n# ============================================================\n\ny_true = []\ny_pred = []\n\ny_true = np.array(y_train)\n\npredictions = googlenet_model.predict(\n    X_train,\n    verbose=1\n)\n\ny_pred = np.argmax(\n    predictions,\n    axis=1\n)\n\n\n# ============================================================\n# ACCURACY\n# ============================================================\n\naccuracy = accuracy_score(\n    y_true,\n    y_pred\n)\n\nprint(\n    f\"Accuracy: {accuracy:.4f}\"\n)\n\n\n# ============================================================\n# MACRO F1 SCORE\n# ============================================================\n\nmacro_f1 = f1_score(\n    y_true,\n    y_pred,\n    average=\"macro\"\n)\n\nprint(\n    f\"Macro F1 Score: {macro_f1:.4f}\"\n)\n\n\n# ============================================================\n# WEIGHTED F1 SCORE\n# ============================================================\n\nweighted_f1 = f1_score(\n    y_true,\n    y_pred,\n    average=\"weighted\"\n)\n\nprint(\n    f\"Weighted F1 Score: {weighted_f1:.4f}\"\n)\n\n\n# ============================================================\n# QUADRATIC WEIGHTED KAPPA\n# ============================================================\n\nqwk = cohen_kappa_score(\n    y_true,\n    y_pred,\n    weights=\"quadratic\"\n)\n\nprint(\n    f\"Quadratic Weighted Kappa: {qwk:.4f}\"\n)\n\n\n# ============================================================\n# CLASSIFICATION REPORT\n# ============================================================\n\nprint(\"\\nClassification Report:\\n\")\n\nprint(\n    classification_report(\n        y_true,\n        y_pred,\n        target_names=[\n    \"No DR\",\n    \"Mild\",\n    \"Moderate\",\n    \"Severe\",\n    \"Proliferative DR\"\n],\n        digits=4\n    )\n)\n\n\n# ============================================================\n# CONFUSION MATRIX\n# ============================================================\n\ncm = confusion_matrix(\n    y_true,\n    y_pred\n)\n\n\n# ============================================================\n# CONFUSION MATRIX GRAPH\n# ============================================================\n\nplt.figure(\n    figsize=(9, 7)\n)\n\nsns.heatmap(\n    cm,\n    annot=True,\n    fmt=\"d\",\n    cmap=\"Blues\",\n   xticklabels=[\n    \"No DR\",\n    \"Mild\",\n    \"Moderate\",\n    \"Severe\",\n    \"Proliferative DR\"\n],\nyticklabels=[\n    \"No DR\",\n    \"Mild\",\n    \"Moderate\",\n    \"Severe\",\n    \"Proliferative DR\"\n]\n)\n\nplt.title(\n    \"GoogLeNet Confusion Matrix\"\n)\n\nplt.xlabel(\n    \"Predicted Class\"\n)\n\nplt.ylabel(\n    \"Actual Class\"\n)\n\nplt.tight_layout()\n\nplt.show()\n\n\n# ============================================================\n# NORMALIZED CONFUSION MATRIX\n# ============================================================\n\ncm_normalized = (\n    cm.astype(\"float\")\n    / cm.sum(axis=1)[:, np.newaxis]\n)\n\n\nplt.figure(\n    figsize=(9, 7)\n)\n\nsns.heatmap(\n    cm_normalized,\n    annot=True,\n    fmt=\".2f\",\n    cmap=\"Blues\",\n   xticklabels=[\n    \"No DR\",\n    \"Mild\",\n    \"Moderate\",\n    \"Severe\",\n    \"Proliferative DR\"\n],\nyticklabels=[\n    \"No DR\",\n    \"Mild\",\n    \"Moderate\",\n    \"Severe\",\n    \"Proliferative DR\"\n]\n)\n\nplt.title(\n    \"GoogLeNet Normalized Confusion Matrix\"\n)\n\nplt.xlabel(\n    \"Predicted Class\"\n)\n\nplt.ylabel(\n    \"Actual Class\"\n)\n\nplt.tight_layout()\n\nplt.show()\n\n\n# ============================================================\n# SAVE MODEL\n# ============================================================\n\ngooglenet_model.save(\n    \"googlenet_diabetic_retinopathy.keras\"\n)\n\n\n# ============================================================\n# FINAL RESULTS\n# ============================================================\n\ngooglenet_results = pd.DataFrame({\n    \"Model\": [\"GoogLeNet\"],\n    \"Accuracy\": [accuracy],\n    \"Macro F1\": [macro_f1],\n    \"Weighted F1\": [weighted_f1],\n    \"QWK\": [qwk]\n})\n\nprint(\n    googlenet_results\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-27T16:09:10.898723Z","iopub.execute_input":"2026-09-27T16:09:10.899108Z","iopub.status.idle":"2026-09-27T16:11:44.255148Z","shell.execute_reply.started":"2026-09-27T16:09:10.89908Z","shell.execute_reply":"2026-09-27T16:11:44.254414Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# several overfitting-reduction techniques: data augmentation, dropout, L2 regularization,\n# reduced model capacity, Global Average Pooling, lower learning rate, and EarlyStopping.\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-27T16:19:46.337385Z","iopub.execute_input":"2026-09-27T16:19:46.338053Z","iopub.status.idle":"2026-09-27T16:19:46.34159Z","shell.execute_reply.started":"2026-09-27T16:19:46.338025Z","shell.execute_reply":"2026-09-27T16:19:46.340896Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# IMPORTS\n# ============================================================\n\nimport numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport tensorflow as tf\n\nfrom tensorflow.keras import layers, models, regularizers\nfrom tensorflow.keras.layers import (\n    Input,\n    Conv2D,\n    MaxPooling2D,\n    GlobalAveragePooling2D,\n    Dense,\n    Dropout,\n    concatenate\n)\n\nfrom tensorflow.keras.optimizers import Adam\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator\nfrom tensorflow.keras.callbacks import EarlyStopping, ReduceLROnPlateau\n\nfrom sklearn.metrics import (\n    accuracy_score,\n    f1_score,\n    cohen_kappa_score,\n    classification_report,\n    confusion_matrix\n)\n\nimport seaborn as sns","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-27T16:20:03.736296Z","iopub.execute_input":"2026-09-27T16:20:03.737002Z","iopub.status.idle":"2026-09-27T16:20:03.741731Z","shell.execute_reply.started":"2026-09-27T16:20:03.73697Z","shell.execute_reply":"2026-09-27T16:20:03.741138Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# CLASS NAMES\n# ============================================================\n\nclass_names = [\n    \"No DR\",\n    \"Mild\",\n    \"Moderate\",\n    \"Severe\",\n    \"Proliferative DR\"\n]\n\nnum_classes = 5\n\nprint(\"Classes:\", class_names)\nprint(\"Number of classes:\", num_classes)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-27T16:20:25.313191Z","iopub.execute_input":"2026-09-27T16:20:25.313451Z","iopub.status.idle":"2026-09-27T16:20:25.318091Z","shell.execute_reply.started":"2026-09-27T16:20:25.31343Z","shell.execute_reply":"2026-09-27T16:20:25.317168Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# CHECK DATASET SHAPES\n# ============================================================\n\nprint(\"X_train:\", X_train.shape)\nprint(\"y_train:\", y_train.shape)\n\nprint(\"X_val:\", X_val.shape)\nprint(\"y_val:\", y_val.shape)\n\nprint(\"X_test:\", X_test.shape)\nprint(\"y_test:\", y_test.shape\n     )","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-27T16:20:50.462726Z","iopub.execute_input":"2026-09-27T16:20:50.46347Z","iopub.status.idle":"2026-09-27T16:20:50.467816Z","shell.execute_reply.started":"2026-09-27T16:20:50.463441Z","shell.execute_reply":"2026-09-27T16:20:50.467182Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# DATA AUGMENTATION - GENTLE AUGMENTATION\n# ============================================================\n\n# ============================================================\n# LIGHT DATA AUGMENTATION\n# ============================================================\n\ntrain_datagen = ImageDataGenerator(\n    rotation_range=5,\n    width_shift_range=0.02,\n    height_shift_range=0.02,\n    zoom_range=0.05,\n    horizontal_flip=True,\n    fill_mode=\"nearest\"\n)\n\ntrain_generator = train_datagen.flow(\n    X_train,\n    y_train,\n    batch_size=32,\n    shuffle=True\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-27T18:15:42.923431Z","iopub.execute_input":"2026-09-27T18:15:42.924016Z","iopub.status.idle":"2026-09-27T18:15:42.928452Z","shell.execute_reply.started":"2026-09-27T18:15:42.923988Z","shell.execute_reply":"2026-09-27T18:15:42.927648Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"\n# ============================================================\n# INCEPTION MODULE - HIGHER CAPACITY\n# ============================================================\n\ndef inception_module(\n    x,\n    f1,\n    f3_reduce,\n    f3,\n    f5_reduce,\n    f5,\n    pool_proj\n):\n\n    # 1x1 branch\n    conv1 = Conv2D(\n        f1,\n        (1, 1),\n        padding=\"same\",\n        activation=\"relu\"\n    )(x)\n\n    # 3x3 branch\n    conv3 = Conv2D(\n        f3_reduce,\n        (1, 1),\n        padding=\"same\",\n        activation=\"relu\"\n    )(x)\n\n    conv3 = Conv2D(\n        f3,\n        (3, 3),\n        padding=\"same\",\n        activation=\"relu\"\n    )(conv3)\n\n    # 5x5 branch\n    conv5 = Conv2D(\n        f5_reduce,\n        (1, 1),\n        padding=\"same\",\n        activation=\"relu\"\n    )(x)\n\n    conv5 = Conv2D(\n        f5,\n        (5, 5),\n        padding=\"same\",\n        activation=\"relu\"\n    )(conv5)\n\n    # Pooling branch\n    pool = MaxPooling2D(\n        (3, 3),\n        strides=(1, 1),\n        padding=\"same\"\n    )(x)\n\n    pool = Conv2D(\n        pool_proj,\n        (1, 1),\n        padding=\"same\",\n        activation=\"relu\"\n    )(pool)\n\n    # Combine branches\n    output = concatenate([\n        conv1,\n        conv3,\n        conv5,\n        pool\n    ])\n\n    return output","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-27T18:15:55.026052Z","iopub.execute_input":"2026-09-27T18:15:55.026477Z","iopub.status.idle":"2026-09-27T18:15:55.032496Z","shell.execute_reply.started":"2026-09-27T18:15:55.026449Z","shell.execute_reply":"2026-09-27T18:15:55.03183Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# INCEPTION MODULE - BALANCED REGULARIZATION\n# ============================================================\n\nfrom tensorflow.keras.regularizers import l2\n\n\ndef inception_module(\n    x,\n    f1,\n    f3_reduce,\n    f3,\n    f5_reduce,\n    f5,\n    pool_proj\n):\n\n    # --------------------------------------------------------\n    # 1x1 branch\n    # --------------------------------------------------------\n    conv1 = Conv2D(\n        f1,\n        (1, 1),\n        padding=\"same\",\n        activation=\"relu\",\n        kernel_regularizer=l2(1e-5)\n    )(x)\n\n    # --------------------------------------------------------\n    # 3x3 branch\n    # --------------------------------------------------------\n    conv3 = Conv2D(\n        f3_reduce,\n        (1, 1),\n        padding=\"same\",\n        activation=\"relu\",\n        kernel_regularizer=l2(1e-5)\n    )(x)\n\n    conv3 = Conv2D(\n        f3,\n        (3, 3),\n        padding=\"same\",\n        activation=\"relu\",\n        kernel_regularizer=l2(1e-5)\n    )(conv3)\n\n    # --------------------------------------------------------\n    # 5x5 branch\n    # --------------------------------------------------------\n    conv5 = Conv2D(\n        f5_reduce,\n        (1, 1),\n        padding=\"same\",\n        activation=\"relu\",\n        kernel_regularizer=l2(1e-5)\n    )(x)\n\n    conv5 = Conv2D(\n        f5,\n        (5, 5),\n        padding=\"same\",\n        activation=\"relu\",\n        kernel_regularizer=l2(1e-5)\n    )(conv5)\n\n    # --------------------------------------------------------\n    # Pooling branch\n    # --------------------------------------------------------\n    pool = MaxPooling2D(\n        (3, 3),\n        strides=(1, 1),\n        padding=\"same\"\n    )(x)\n\n    pool = Conv2D(\n        pool_proj,\n        (1, 1),\n        padding=\"same\",\n        activation=\"relu\",\n        kernel_regularizer=l2(1e-5)\n    )(pool)\n\n    # --------------------------------------------------------\n    # Combine all branches\n    # --------------------------------------------------------\n    output = concatenate([\n        conv1,\n        conv3,\n        conv5,\n        pool\n    ])\n\n    return output","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-27T18:14:16.783044Z","iopub.execute_input":"2026-09-27T18:14:16.78387Z","iopub.status.idle":"2026-09-27T18:14:16.805038Z","shell.execute_reply.started":"2026-09-27T18:14:16.783839Z","shell.execute_reply":"2026-09-27T18:14:16.80441Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"\n# ============================================================\n# HIGH-CAPACITY GoogLeNet\n# ============================================================\n\ndef build_googlenet(\n    input_shape=(128, 128, 3),\n    num_classes=5\n):\n\n    input_layer = Input(\n        shape=input_shape\n    )\n\n    # ========================================================\n    # INITIAL BLOCK\n    # ========================================================\n\n    x = Conv2D(\n        64,\n        (7, 7),\n        strides=(2, 2),\n        padding=\"same\",\n        activation=\"relu\"\n    )(input_layer)\n\n    x = MaxPooling2D(\n        (3, 3),\n        strides=(2, 2),\n        padding=\"same\"\n    )(x)\n\n    # ========================================================\n    # SECOND BLOCK\n    # ========================================================\n\n    x = Conv2D(\n        64,\n        (1, 1),\n        padding=\"same\",\n        activation=\"relu\"\n    )(x)\n\n    x = Conv2D(\n        192,\n        (3, 3),\n        padding=\"same\",\n        activation=\"relu\"\n    )(x)\n\n    x = MaxPooling2D(\n        (3, 3),\n        strides=(2, 2),\n        padding=\"same\"\n    )(x)\n\n    # ========================================================\n    # INCEPTION 3A\n    # ========================================================\n\n    x = inception_module(\n        x,\n        64, 96, 128,\n        16, 32, 32\n    )\n\n    # ========================================================\n    # INCEPTION 3B\n    # ========================================================\n\n    x = inception_module(\n        x,\n        128, 128, 192,\n        32, 96, 64\n    )\n\n    x = MaxPooling2D(\n        (3, 3),\n        strides=(2, 2),\n        padding=\"same\"\n    )(x)\n\n    # ========================================================\n    # INCEPTION 4A\n    # ========================================================\n\n    x = inception_module(\n        x,\n        192, 96, 208,\n        16, 48, 64\n    )\n\n    # ========================================================\n    # INCEPTION 4B\n    # ========================================================\n\n    x = inception_module(\n        x,\n        160, 112, 224,\n        24, 64, 64\n    )\n\n    # ========================================================\n    # INCEPTION 4C\n    # ========================================================\n\n    x = inception_module(\n        x,\n        128, 128, 256,\n        24, 64, 64\n    )\n\n    # ========================================================\n    # INCEPTION 4D\n    # ========================================================\n\n    x = inception_module(\n        x,\n        112, 144, 288,\n        32, 64, 64\n    )\n\n    # ========================================================\n    # INCEPTION 4E\n    # ========================================================\n\n    x = inception_module(\n        x,\n        256, 160, 320,\n        32, 128, 128\n    )\n\n    x = MaxPooling2D(\n        (3, 3),\n        strides=(2, 2),\n        padding=\"same\"\n    )(x)\n\n    # ========================================================\n    # INCEPTION 5A\n    # ========================================================\n\n    x = inception_module(\n        x,\n        256, 160, 320,\n        32, 128, 128\n    )\n\n    # ========================================================\n    # INCEPTION 5B\n    # ========================================================\n\n    x = inception_module(\n        x,\n        384, 192, 384,\n        48, 128, 128\n    )\n\n    # ========================================================\n    # GLOBAL AVERAGE POOLING\n    # ========================================================\n\n    x = GlobalAveragePooling2D()(x)\n\n    # ========================================================\n    # SMALL DROPOUT\n    # ========================================================\n\n    x = Dropout(0.20)(x)\n\n    # ========================================================\n    # OUTPUT\n    # ========================================================\n\n    output_layer = Dense(\n        num_classes,\n        activation=\"softmax\"\n    )(x)\n\n    model = models.Model(\n        inputs=input_layer,\n        outputs=output_layer\n    )\n\n    return model","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-27T18:14:45.357873Z","iopub.execute_input":"2026-09-27T18:14:45.358613Z","iopub.status.idle":"2026-09-27T18:14:45.36843Z","shell.execute_reply.started":"2026-09-27T18:14:45.358583Z","shell.execute_reply":"2026-09-27T18:14:45.367717Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# CREATE GoogLeNet MODEL\n# ============================================================\n\ngooglenet_model = build_googlenet(\n    input_shape=(128, 128, 3),\n    num_classes=5\n)\n\ngooglenet_model.summary()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-27T17:44:11.462299Z","iopub.execute_input":"2026-09-27T17:44:11.462682Z","iopub.status.idle":"2026-09-27T17:44:11.893772Z","shell.execute_reply.started":"2026-09-27T17:44:11.462654Z","shell.execute_reply":"2026-09-27T17:44:11.893181Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# CREATE MODEL\n# ============================================================\n\ngooglenet_model = build_googlenet(\n    input_shape=(128, 128, 3),\n    num_classes=5\n)\n\n\n# ============================================================\n# COMPILE\n# ============================================================\n\ngooglenet_model.compile(\n    optimizer=Adam(\n        learning_rate=0.0003\n    ),\n    loss=\"sparse_categorical_crossentropy\",\n    metrics=[\"accuracy\"]\n)\n\ngooglenet_model.summary()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-27T17:44:27.176718Z","iopub.execute_input":"2026-09-27T17:44:27.177153Z","iopub.status.idle":"2026-09-27T17:44:27.618141Z","shell.execute_reply.started":"2026-09-27T17:44:27.177088Z","shell.execute_reply":"2026-09-27T17:44:27.617367Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# EARLY STOPPING\n# ============================================================\n\nearly_stop = EarlyStopping(\n    monitor=\"val_accuracy\",\n    mode=\"max\",\n    patience=12,\n    restore_best_weights=True,\n    verbose=1\n)\n\n\n\n\n# ============================================================\n# REDUCE LEARNING RATE\n# ============================================================\n\nreduce_lr = ReduceLROnPlateau(\n    monitor=\"val_accuracy\",\n    mode=\"max\",\n    factor=0.5,\n    patience=5,\n    min_lr=1e-6,\n    verbose=1\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-27T18:18:22.764218Z","iopub.execute_input":"2026-09-27T18:18:22.764731Z","iopub.status.idle":"2026-09-27T18:18:22.769763Z","shell.execute_reply.started":"2026-09-27T18:18:22.764705Z","shell.execute_reply":"2026-09-27T18:18:22.769193Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# TRAIN MODEL\n# ============================================================\n\nhistory = googlenet_model.fit(\n    train_generator,\n\n    validation_data=(\n        X_val,\n        y_val\n    ),\n\n    epochs=50,\n\n    callbacks=[\n        early_stop,\n        reduce_lr\n    ],\n\n    verbose=1\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-27T18:18:27.761654Z","iopub.execute_input":"2026-09-27T18:18:27.762369Z","iopub.status.idle":"2026-09-27T18:25:56.472668Z","shell.execute_reply.started":"2026-09-27T18:18:27.762341Z","shell.execute_reply":"2026-09-27T18:25:56.472022Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# alexnet","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-27T18:29:52.041577Z","iopub.execute_input":"2026-09-27T18:29:52.041973Z","iopub.status.idle":"2026-09-27T18:29:52.045832Z","shell.execute_reply.started":"2026-09-27T18:29:52.041946Z","shell.execute_reply":"2026-09-27T18:29:52.045061Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# ALEXNET MODEL\n# ============================================================\n\nfrom tensorflow.keras import models\nfrom tensorflow.keras.layers import (\n    Input,\n    Conv2D,\n    MaxPooling2D,\n    Flatten,\n    Dense,\n    Dropout\n)\nfrom tensorflow.keras.optimizers import Adam\nfrom tensorflow.keras.callbacks import (\n    EarlyStopping,\n    ReduceLROnPlateau\n)\nfrom tensorflow.keras.regularizers import l2\n\n\ndef build_alexnet(\n    input_shape=(128, 128, 3),\n    num_classes=5\n):\n\n    # ========================================================\n    # INPUT\n    # ========================================================\n\n    input_layer = Input(\n        shape=input_shape\n    )\n\n    # ========================================================\n    # CONVOLUTIONAL BLOCK 1\n    # ========================================================\n\n    x = Conv2D(\n        96,\n        (11, 11),\n        strides=(4, 4),\n        padding=\"same\",\n        activation=\"relu\",\n        kernel_regularizer=l2(1e-5)\n    )(input_layer)\n\n    x = MaxPooling2D(\n        pool_size=(3, 3),\n        strides=(2, 2)\n    )(x)\n\n    # ========================================================\n    # CONVOLUTIONAL BLOCK 2\n    # ========================================================\n\n    x = Conv2D(\n        256,\n        (5, 5),\n        padding=\"same\",\n        activation=\"relu\",\n        kernel_regularizer=l2(1e-5)\n    )(x)\n\n    x = MaxPooling2D(\n        pool_size=(3, 3),\n        strides=(2, 2)\n    )(x)\n\n    # ========================================================\n    # CONVOLUTIONAL BLOCK 3\n    # ========================================================\n\n    x = Conv2D(\n        384,\n        (3, 3),\n        padding=\"same\",\n        activation=\"relu\",\n        kernel_regularizer=l2(1e-5)\n    )(x)\n\n    # ========================================================\n    # CONVOLUTIONAL BLOCK 4\n    # ========================================================\n\n    x = Conv2D(\n        384,\n        (3, 3),\n        padding=\"same\",\n        activation=\"relu\",\n        kernel_regularizer=l2(1e-5)\n    )(x)\n\n    # ========================================================\n    # CONVOLUTIONAL BLOCK 5\n    # ========================================================\n\n    x = Conv2D(\n        256,\n        (3, 3),\n        padding=\"same\",\n        activation=\"relu\",\n        kernel_regularizer=l2(1e-5)\n    )(x)\n\n    x = MaxPooling2D(\n        pool_size=(3, 3),\n        strides=(2, 2)\n    )(x)\n\n    # ========================================================\n    # FLATTEN\n    # ========================================================\n\n    x = Flatten()(x)\n\n    # ========================================================\n    # FULLY CONNECTED LAYER 1\n    # ========================================================\n\n    x = Dense(\n        1024,\n        activation=\"relu\",\n        kernel_regularizer=l2(1e-5)\n    )(x)\n\n    x = Dropout(0.40)(x)\n\n    # ========================================================\n    # FULLY CONNECTED LAYER 2\n    # ========================================================\n\n    x = Dense(\n        1024,\n        activation=\"relu\",\n        kernel_regularizer=l2(1e-5)\n    )(x)\n\n    x = Dropout(0.40)(x)\n\n    # ========================================================\n    # OUTPUT LAYER\n    # ========================================================\n\n    output_layer = Dense(\n        num_classes,\n        activation=\"softmax\"\n    )(x)\n\n    # ========================================================\n    # CREATE MODEL\n    # ========================================================\n\n    model = models.Model(\n        inputs=input_layer,\n        outputs=output_layer\n    )\n\n    return model","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-27T18:30:06.847936Z","iopub.execute_input":"2026-09-27T18:30:06.848525Z","iopub.status.idle":"2026-09-27T18:30:06.858619Z","shell.execute_reply.started":"2026-09-27T18:30:06.848496Z","shell.execute_reply":"2026-09-27T18:30:06.857831Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# BUILD ALEXNET\n# ============================================================\n\nalexnet_model = build_alexnet(\n    input_shape=(128, 128, 3),\n    num_classes=5\n)\n\n# ============================================================\n# COMPILE\n# ============================================================\n\nalexnet_model.compile(\n    optimizer=Adam(\n        learning_rate=0.0003\n    ),\n    loss=\"sparse_categorical_crossentropy\",\n    metrics=[\"accuracy\"]\n)\n\n# Show model architecture\nalexnet_model.summary()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-27T18:30:23.711222Z","iopub.execute_input":"2026-09-27T18:30:23.711629Z","iopub.status.idle":"2026-09-27T18:30:23.807844Z","shell.execute_reply.started":"2026-09-27T18:30:23.711599Z","shell.execute_reply":"2026-09-27T18:30:23.807182Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# EARLY STOPPING\n# ============================================================\n\nearly_stop = EarlyStopping(\n    monitor=\"val_accuracy\",\n    mode=\"max\",\n    patience=12,\n    restore_best_weights=True,\n    verbose=1\n)\n\n# ============================================================\n# REDUCE LEARNING RATE\n# ============================================================\n\nreduce_lr = ReduceLROnPlateau(\n    monitor=\"val_accuracy\",\n    mode=\"max\",\n    factor=0.5,\n    patience=5,\n    min_lr=1e-6,\n    verbose=1\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-27T18:31:05.046499Z","iopub.execute_input":"2026-09-27T18:31:05.047286Z","iopub.status.idle":"2026-09-27T18:31:05.052236Z","shell.execute_reply.started":"2026-09-27T18:31:05.047255Z","shell.execute_reply":"2026-09-27T18:31:05.051189Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# TRAIN ALEXNET\n# ============================================================\n\nhistory_alexnet = alexnet_model.fit(\n    train_generator,\n    validation_data=(X_val, y_val),\n    epochs=60,\n    callbacks=[\n        early_stop,\n        reduce_lr\n    ],\n    verbose=1\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-27T18:31:18.232657Z","iopub.execute_input":"2026-09-27T18:31:18.233334Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}