{"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":4104,"databundleVersionId":46661,"sourceType":"competition"},{"sourceId":7251,"sourceType":"datasetVersion","datasetId":2798},{"sourceId":7866129,"sourceType":"datasetVersion","datasetId":4614938},{"sourceId":7869237,"sourceType":"datasetVersion","datasetId":4617269}],"dockerImageVersionId":30673,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"**Pre traitement et l'importation des bibliothèques nécessaires**","metadata":{}},{"cell_type":"code","source":"# copy the weights and configurations for the pre-trained models \n!mkdir ~/.keras\n!mkdir ~/.keras/models7\n!cp ../input/keras-pretrained-models/*notop* ~/.keras/models/\n!cp ../input/keras-pretrained-models/imagenet_class_index.json ~/.keras/models/","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Imports","metadata":{}},{"cell_type":"code","source":"import os\nimport numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nfrom glob import glob\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.utils import resample, compute_class_weight\nfrom sklearn.metrics import confusion_matrix, classification_report\nfrom tensorflow.keras.utils import to_categorical\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator, load_img, img_to_array\nfrom tensorflow.keras.applications import EfficientNetB0\nfrom tensorflow.keras.models import Model\nfrom tensorflow.keras.layers import GlobalAveragePooling2D, Dense, Dropout\nfrom tensorflow.keras.optimizers import Adam\nfrom tensorflow.keras.callbacks import ReduceLROnPlateau, EarlyStopping\nimport tensorflow as tf\nimport math\n","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Data loading and cleaning ","metadata":{}},{"cell_type":"code","source":"labels_path = \"/kaggle/input/diabetic-retinopathy-detection/trainLabels.csv.zip\"\ntrain_images_path = \"/kaggle/input/diabetic-retinopathy-train-unzipped/train/\"\ntest_images_path = \"/kaggle/input/diabetic-retinopathy-test-unzipped/test/\"\n\nlabels_df = pd.read_csv(labels_path)\nlabels_df['image_path'] = labels_df['image'].apply(lambda name: os.path.join(train_images_path, f\"{name}.jpeg\"))\nlabels_df['is_present'] = labels_df['image_path'].apply(os.path.exists)\nlabels_df = labels_df[labels_df['is_present']]\nlabels_df.dropna(inplace=True)\n","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Stratified split + Balanced sampling","metadata":{}},{"cell_type":"code","source":"unique_patients_df = labels_df[['image', 'level']].drop_duplicates()\ntrain_patients, val_patients = train_test_split(\n    unique_patients_df['image'],\n    test_size=0.25,\n    stratify=unique_patients_df['level'],\n    random_state=42\n)\n\ntrain_df = labels_df[labels_df['image'].isin(train_patients)]\nval_df = labels_df[labels_df['image'].isin(val_patients)]\n\n# Avoid over-sampling class 0\ntarget_size = train_df['level'].value_counts().median()\n\nbalanced_parts = []\nfor level in train_df['level'].unique():\n    class_subset = train_df[train_df['level'] == level]\n    if level == 0:\n        balanced = class_subset.sample(int(target_size), random_state=42)\n    else:\n        balanced = resample(class_subset, replace=True, n_samples=int(target_size), random_state=42)\n    balanced_parts.append(balanced)\n\nbalanced_train_df = pd.concat(balanced_parts)\n","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Data generators","metadata":{}},{"cell_type":"code","source":"train_datagen = ImageDataGenerator(rescale=1./255,\n                                   rotation_range=20,\n                                   width_shift_range=0.1,\n                                   height_shift_range=0.1,\n                                   zoom_range=0.1,\n                                   horizontal_flip=True)\nvalid_datagen = ImageDataGenerator(rescale=1./255)\ntest_datagen = ImageDataGenerator(rescale=1./255)\n\ndef generate_from_dataframe(df, datagen, batch_size=32, target_size=(224, 224), num_classes=5, shuffle=True):\n    while True:\n        if shuffle:\n            df = df.sample(frac=1).reset_index(drop=True)\n        for start in range(0, len(df), batch_size):\n            end = start + batch_size\n            batch = df.iloc[start:end]\n            imgs, labels = [], []\n            for _, row in batch.iterrows():\n                img = load_img(row['image_path'], target_size=target_size)\n                imgs.append(img_to_array(img))\n                labels.append(row['level'])\n            X = np.array(imgs, dtype=np.float32)\n            y = to_categorical(np.array(labels), num_classes=num_classes)\n            for aug_X, aug_y in datagen.flow(X, y, batch_size=batch_size, shuffle=False):\n                yield aug_X, aug_y\n                break\n\nnum_classes = labels_df['level'].nunique()\ntrain_generator = generate_from_dataframe(balanced_train_df, train_datagen, num_classes=num_classes)\nvalid_generator = generate_from_dataframe(val_df, valid_datagen, num_classes=num_classes, shuffle=False)\n","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Model Architecture EfficientNETB0","metadata":{}},{"cell_type":"code","source":"base_model = EfficientNetB0(include_top=False, weights=\"imagenet\", input_shape=(224,224,3))\nx = base_model.output\nx = GlobalAveragePooling2D()(x)\nx = Dropout(0.4)(x)\npreds = Dense(num_classes, activation='softmax')(x)\n\nmodel = Model(inputs=base_model.input, outputs=preds)\nmodel.compile(optimizer=Adam(1e-4), loss=\"categorical_crossentropy\", metrics=[\"accuracy\"])\n","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Training","metadata":{}},{"cell_type":"code","source":"callbacks = [\n    ReduceLROnPlateau(monitor='val_loss', factor=0.5, patience=2),\n    EarlyStopping(monitor='val_loss', patience=5, restore_best_weights=True)\n]\n\nsteps_per_epoch = len(balanced_train_df) // 32\nvalidation_steps = len(val_df) // 32\n\nhistory = model.fit(\n    train_generator,\n    steps_per_epoch=steps_per_epoch,\n    validation_data=valid_generator,\n    validation_steps=validation_steps,\n    epochs=20,\n    callbacks=callbacks\n)\n","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Evaluation on validation set ","metadata":{}},{"cell_type":"code","source":"all_predictions = []\nall_true_labels = []\nsteps = math.ceil(len(val_df) / 32)\n\nfor _ in range(steps):\n    x_batch, y_batch = next(valid_generator)\n    preds = model.predict(x_batch, verbose=0)\n    all_predictions.extend(np.argmax(preds, axis=1))\n    all_true_labels.extend(np.argmax(y_batch, axis=1))\n\ncm = confusion_matrix(all_true_labels, all_predictions)\nsns.heatmap(cm, annot=True, fmt='d', cmap='Blues')\nplt.xlabel(\"Predicted\")\nplt.ylabel(\"True\")\nplt.title(\"Confusion Matrix\")\nplt.show()\n\nprint(classification_report(all_true_labels, all_predictions, digits=4))\n","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Test set pred + submission","metadata":{}},{"cell_type":"code","source":"# === Load and Predict on Test Set ===\ntest_paths = glob(\"/kaggle/input/diabetic-retinopathy-test-unzipped/test/*.jpeg\")\ntest_df = pd.DataFrame({\"image\": [os.path.basename(p) for p in test_paths], \"image_path\": test_paths})\n\ndef generate_test_batches(df, datagen, batch_size=32, target_size=(224, 224)):\n    for start in range(0, len(df), batch_size):\n        end = start + batch_size\n        batch = df.iloc[start:end]\n        imgs = []\n        for path in batch['image_path']:\n            img = load_img(path, target_size=target_size)\n            imgs.append(img_to_array(img))\n        X = np.array(imgs, dtype=np.float32)\n        X /= 255.\n        yield X\n        \nbatch_size = 32\ntest_preds = []\ntest_steps = math.ceil(len(test_df) / batch_size)\ntest_gen = generate_test_batches(test_df, test_datagen, batch_size=batch_size)\n\nfor _ in range(test_steps):\n    x_batch = next(test_gen)\n    preds = model.predict(x_batch, verbose=0)\n    test_preds.extend(np.argmax(preds, axis=1))\n\nsubmission_df = pd.DataFrame({\"image\": test_df['image'], \"level\": test_preds})\nsubmission_df.to_csv(\"submission.csv\", index=False)\n","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}