{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"nvidiaTeslaT4","dataSources":[{"sourceId":14774,"databundleVersionId":875431,"sourceType":"competition"}],"dockerImageVersionId":30887,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import pandas as pd\nimport os\nfrom sklearn.model_selection import train_test_split\n\n# ✅ Step 1: Load CSV Files\ndata_dir = \"/kaggle/input/aptos2019-blindness-detection\"\ntrain_df = pd.read_csv(os.path.join(data_dir, \"train.csv\"))\ntest_df = pd.read_csv(os.path.join(data_dir, \"test.csv\"))\n\n# ✅ Step 2: Prepend Full Image Paths\ntrain_df[\"id_code\"] = train_df[\"id_code\"].apply(lambda x: os.path.join(data_dir, \"train_images\", f\"{x}.png\"))\ntest_df[\"id_code\"] = test_df[\"id_code\"].apply(lambda x: os.path.join(data_dir, \"test_images\", f\"{x}.png\"))\n\n# ✅ Step 3: Perform First 80/20 Train-Test Split\ntrain_full, test_set = train_test_split(train_df, test_size=0.2, random_state=42, stratify=train_df[\"diagnosis\"])\n\n# ✅ Step 4: Further Split Train Set into 80/20 Train-Validation\ntrain_set, val_set = train_test_split(train_full, test_size=0.2, random_state=42, stratify=train_full[\"diagnosis\"])\n\n# ✅ Step 5: Save the Splits as CSV Files\ntrain_set.to_csv(\"train_split.csv\", index=False)\nval_set.to_csv(\"val_split.csv\", index=False)\ntest_set.to_csv(\"test_split.csv\", index=False)\n\nprint(\"✅ Data has been split and saved as CSV files.\")\nprint(f\"Training Set: {len(train_set)} samples\")\nprint(f\"Validation Set: {len(val_set)} samples\")\nprint(f\"Test Set: {len(test_set)} samples\")","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-03-04T09:32:38.677235Z","iopub.execute_input":"2025-03-04T09:32:38.677521Z","iopub.status.idle":"2025-03-04T09:32:39.805376Z","shell.execute_reply.started":"2025-03-04T09:32:38.677496Z","shell.execute_reply":"2025-03-04T09:32:39.804436Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nimport numpy as np\nimport pandas as pd\nimport tensorflow as tf\nimport matplotlib.pyplot as plt\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator\nfrom tensorflow.keras.applications import ResNet152V2\nfrom tensorflow.keras.layers import Dense, GlobalAveragePooling2D, Dropout\nfrom tensorflow.keras.models import Model\nfrom tensorflow.keras.optimizers import Adam\nfrom tensorflow.keras.callbacks import EarlyStopping, ReduceLROnPlateau\nfrom sklearn.metrics import f1_score, roc_curve, auc\nfrom sklearn.preprocessing import label_binarize","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-04T09:32:39.806739Z","iopub.execute_input":"2025-03-04T09:32:39.807055Z","iopub.status.idle":"2025-03-04T09:32:55.988460Z","shell.execute_reply.started":"2025-03-04T09:32:39.807028Z","shell.execute_reply":"2025-03-04T09:32:55.987773Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ✅ Step 1: Load Split Data\ntrain_df = pd.read_csv(\"train_split.csv\")\nval_df = pd.read_csv(\"val_split.csv\")\n\n# Convert labels to string (for categorical classification)\ntrain_df[\"diagnosis\"] = train_df[\"diagnosis\"].astype(str)\nval_df[\"diagnosis\"] = val_df[\"diagnosis\"].astype(str)\n\n# ✅ Step 2: Data Generators with Augmentation\ntrain_datagen = ImageDataGenerator(\n    rescale=1.0 / 255,\n    rotation_range=20,\n    width_shift_range=0.2,\n    height_shift_range=0.2,\n    shear_range=0.2,\n    zoom_range=0.2,\n    horizontal_flip=True\n)\n\nval_datagen = ImageDataGenerator(rescale=1.0 / 255)\n\ntrain_generator = train_datagen.flow_from_dataframe(\n    dataframe=train_df,\n    x_col=\"id_code\",\n    y_col=\"diagnosis\",\n    target_size=(224, 224),\n    batch_size=32,\n    class_mode=\"categorical\"\n)\n\nval_generator = val_datagen.flow_from_dataframe(\n    dataframe=val_df,\n    x_col=\"id_code\",\n    y_col=\"diagnosis\",\n    target_size=(224, 224),\n    batch_size=32,\n    class_mode=\"categorical\"\n)\n\nnum_classes = len(train_generator.class_indices)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-04T09:32:55.990238Z","iopub.execute_input":"2025-03-04T09:32:55.990766Z","iopub.status.idle":"2025-03-04T09:32:58.502428Z","shell.execute_reply.started":"2025-03-04T09:32:55.990742Z","shell.execute_reply":"2025-03-04T09:32:58.501727Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ✅ Step 3: Define Model with ResNet152V2\nbase_model = ResNet152V2(weights=\"imagenet\", include_top=False, input_shape=(224, 224, 3))\nx = base_model.output\nx = GlobalAveragePooling2D()(x)\nx = Dense(512, activation=\"relu\")(x)\nx = Dropout(0.3)(x)\nx = Dense(256, activation=\"relu\")(x)\npredictions = Dense(num_classes, activation=\"softmax\")(x)\n\nmodel = Model(inputs=base_model.input, outputs=predictions)\n\n# Freeze base model layers\nfor layer in base_model.layers:\n    layer.trainable = False\n\n# ✅ Step 4: Compile the Model\nmodel.compile(optimizer=Adam(learning_rate=0.001), loss=\"categorical_crossentropy\", metrics=[\"accuracy\"])\n\n# ✅ Step 5: Training with Early Stopping & Learning Rate Reduction\ncallbacks = [\n    EarlyStopping(monitor=\"val_loss\", patience=5, restore_best_weights=True),\n    ReduceLROnPlateau(monitor=\"val_loss\", factor=0.5, patience=3, min_lr=1e-6)\n]\n\nhistory = model.fit(\n    train_generator,\n    validation_data=val_generator,\n    epochs=20,\n    callbacks=callbacks\n)","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ✅ Step 6: Save the Model\nmodel.save(\"blindness_detection_model.h5\")\n\n# ✅ Step 7: Evaluate the Model\nval_loss, val_accuracy = model.evaluate(val_generator)\nprint(f\"Validation Loss: {val_loss}\")\nprint(f\"Validation Accuracy: {val_accuracy}\")\n\n# ✅ Step 8: Compute F1-Score & ROC-AUC\ny_true = val_generator.classes\ny_pred_proba = model.predict(val_generator)\ny_pred = np.argmax(y_pred_proba, axis=1)\n\n# Compute F1-score\nf1 = f1_score(y_true, y_pred, average=\"weighted\")\nprint(f\"F1 Score: {f1}\")\n\n# Compute ROC-AUC for each class\ny_true_bin = label_binarize(y_true, classes=range(num_classes))\n\nroc_auc_values = []\nplt.figure(figsize=(8, 6))\n\nfor i in range(num_classes):\n    fpr, tpr, _ = roc_curve(y_true_bin[:, i], y_pred_proba[:, i])\n    roc_auc = auc(fpr, tpr)\n    roc_auc_values.append(roc_auc)\n    plt.plot(fpr, tpr, label=f\"Class {i} (AUC = {roc_auc:.2f})\")\n\n# Diagonal reference line\nplt.plot([0, 1], [0, 1], 'k--')\nplt.xlabel(\"False Positive Rate\")\nplt.ylabel(\"True Positive Rate\")\nplt.title(\"ROC-AUC Curve\")\nplt.legend()\nplt.show()\n\n# Print ROC-AUC scores\nfor i, auc_value in enumerate(roc_auc_values):\n    print(f\"Class {i} - ROC AUC Score: {auc_value}\")","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}