{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.11.11","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":29653,"databundleVersionId":2420395,"sourceType":"competition"}],"dockerImageVersionId":31040,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import os\nimport torch\nimport torch.nn as nn\nimport pandas as pd\nimport numpy as np\nimport matplotlib.pyplot as plt\nimport matplotlib\nimport pydicom as dicom\nimport cv2\nimport ast\nimport glob\n\nimport warnings\nwarnings.filterwarnings(\"ignore\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-10T22:49:05.356038Z","iopub.execute_input":"2026-07-10T22:49:05.356728Z","iopub.status.idle":"2026-07-10T22:49:10.701817Z","shell.execute_reply.started":"2026-07-10T22:49:05.356701Z","shell.execute_reply":"2026-07-10T22:49:10.701057Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"path = '/kaggle/input/rsna-miccai-brain-tumor-radiogenomic-classification/'\nos.listdir(path)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-10T22:49:10.703053Z","iopub.execute_input":"2026-07-10T22:49:10.703777Z","iopub.status.idle":"2026-07-10T22:49:10.710730Z","shell.execute_reply.started":"2026-07-10T22:49:10.703755Z","shell.execute_reply":"2026-07-10T22:49:10.709834Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"\n\npath = '/kaggle/input/rsna-miccai-brain-tumor-radiogenomic-classification/'\nos.listdir(path)\ntrain_data = pd.read_csv(path+'train_labels.csv')\nsamp_subm = pd.read_csv(path+'sample_submission.csv')\n\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-10T22:49:10.711655Z","iopub.execute_input":"2026-07-10T22:49:10.711980Z","iopub.status.idle":"2026-07-10T22:49:10.741130Z","shell.execute_reply.started":"2026-07-10T22:49:10.711956Z","shell.execute_reply":"2026-07-10T22:49:10.739988Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print('Samples train:', len(train_data))\nprint('Samples test:', len(samp_subm))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-10T22:49:10.743161Z","iopub.execute_input":"2026-07-10T22:49:10.743942Z","iopub.status.idle":"2026-07-10T22:49:10.748657Z","shell.execute_reply.started":"2026-07-10T22:49:10.743913Z","shell.execute_reply":"2026-07-10T22:49:10.747760Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_data.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-10T22:49:10.749502Z","iopub.execute_input":"2026-07-10T22:49:10.749821Z","iopub.status.idle":"2026-07-10T22:49:10.779676Z","shell.execute_reply.started":"2026-07-10T22:49:10.749798Z","shell.execute_reply":"2026-07-10T22:49:10.778978Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_data[\"MGMT_value\"].value_counts().head(2).plot(kind = 'pie', autopct='%1.1f%%', figsize=(8, 8)).legend()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-10T22:49:10.780498Z","iopub.execute_input":"2026-07-10T22:49:10.780813Z","iopub.status.idle":"2026-07-10T22:49:11.158059Z","shell.execute_reply.started":"2026-07-10T22:49:10.780788Z","shell.execute_reply":"2026-07-10T22:49:11.157116Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_data[\"MGMT_value\"].value_counts()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-10T22:49:11.159043Z","iopub.execute_input":"2026-07-10T22:49:11.159869Z","iopub.status.idle":"2026-07-10T22:49:11.166494Z","shell.execute_reply.started":"2026-07-10T22:49:11.159845Z","shell.execute_reply":"2026-07-10T22:49:11.165505Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"samp_subm.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-10T22:49:11.167660Z","iopub.execute_input":"2026-07-10T22:49:11.168070Z","iopub.status.idle":"2026-07-10T22:49:11.185244Z","shell.execute_reply.started":"2026-07-10T22:49:11.168028Z","shell.execute_reply":"2026-07-10T22:49:11.184348Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"folder = str(train_data.loc[0, 'BraTS21ID']).zfill(5)\nfolder","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-10T22:49:11.186258Z","iopub.execute_input":"2026-07-10T22:49:11.186595Z","iopub.status.idle":"2026-07-10T22:49:11.201920Z","shell.execute_reply.started":"2026-07-10T22:49:11.186565Z","shell.execute_reply":"2026-07-10T22:49:11.201134Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"os.listdir(path+'train/'+folder)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-10T22:49:11.205725Z","iopub.execute_input":"2026-07-10T22:49:11.205979Z","iopub.status.idle":"2026-07-10T22:49:11.219478Z","shell.execute_reply.started":"2026-07-10T22:49:11.205962Z","shell.execute_reply":"2026-07-10T22:49:11.218777Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print('Number of FLAIR images:', len(os.listdir(path+'train/'+folder+'/'+'FLAIR')))\nprint('Number of T1w images:', len(os.listdir(path+'train/'+folder+'/'+'T1w')))\nprint('Number of T1wCE images:', len(os.listdir(path+'train/'+folder+'/'+'T1wCE')))\nprint('Number of T2w images:', len(os.listdir(path+'train/'+folder+'/'+'T2w')))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-10T22:49:11.220263Z","iopub.execute_input":"2026-07-10T22:49:11.220501Z","iopub.status.idle":"2026-07-10T22:49:11.266092Z","shell.execute_reply.started":"2026-07-10T22:49:11.220485Z","shell.execute_reply":"2026-07-10T22:49:11.265286Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"\n\npath_file = ''.join([path, 'train/', folder, '/', 'FLAIR/'])\nimage = os.listdir(path_file)[0]\ndata_file = dicom.dcmread(path_file+image)\nimg = data_file.pixel_array\nprint('Image shape:', img.shape)\n\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-10T22:49:11.266917Z","iopub.execute_input":"2026-07-10T22:49:11.267198Z","iopub.status.idle":"2026-07-10T22:49:11.281018Z","shell.execute_reply.started":"2026-07-10T22:49:11.267174Z","shell.execute_reply":"2026-07-10T22:49:11.280057Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#Flair Image\ndef plot_examples(row = 0, cat = 'FLAIR'): \n    folder = str(train_data.loc[row, 'BraTS21ID']).zfill(5)\n    path_file = ''.join([path, 'train/', folder, '/', cat, '/'])\n    images = os.listdir(path_file)\n    \n    fig, axs = plt.subplots(1, 5, figsize=(30, 30))\n    fig.subplots_adjust(hspace = .2, wspace=.2)\n    axs = axs.ravel()\n    \n    for num in range(5):\n        data_file = dicom.dcmread(path_file+images[num])\n        img = data_file.pixel_array\n        axs[num].imshow(img, cmap='gray')\n        axs[num].set_title(cat+' '+images[num])\n        axs[num].set_xticklabels([])\n        axs[num].set_yticklabels([])\n        \nrow = 0\nplot_examples(row = row, cat = 'FLAIR')\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-10T22:49:11.281961Z","iopub.execute_input":"2026-07-10T22:49:11.282233Z","iopub.status.idle":"2026-07-10T22:49:12.076355Z","shell.execute_reply.started":"2026-07-10T22:49:11.282206Z","shell.execute_reply":"2026-07-10T22:49:12.075373Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#T1w Images\nplot_examples(row = row, cat = 'T1w')\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-10T22:49:12.077141Z","iopub.execute_input":"2026-07-10T22:49:12.077464Z","iopub.status.idle":"2026-07-10T22:49:12.850671Z","shell.execute_reply.started":"2026-07-10T22:49:12.077443Z","shell.execute_reply":"2026-07-10T22:49:12.849823Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#T1wCE Images\nplot_examples(row = row, cat = 'T1wCE')\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-10T22:49:12.851651Z","iopub.execute_input":"2026-07-10T22:49:12.851932Z","iopub.status.idle":"2026-07-10T22:49:13.650481Z","shell.execute_reply.started":"2026-07-10T22:49:12.851908Z","shell.execute_reply":"2026-07-10T22:49:13.649578Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#T2w Images\nplot_examples(row = row, cat = 'T2w')\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-10T22:49:13.651438Z","iopub.execute_input":"2026-07-10T22:49:13.652291Z","iopub.status.idle":"2026-07-10T22:49:14.458927Z","shell.execute_reply.started":"2026-07-10T22:49:13.652264Z","shell.execute_reply":"2026-07-10T22:49:14.458006Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nimport numpy as np\nimport pandas as pd\nimport pydicom\nimport tensorflow as tf\nfrom tensorflow.keras import layers, models\nfrom sklearn.model_selection import train_test_split\nimport cv2\nimport matplotlib.pyplot as plt\nfrom sklearn.metrics import classification_report, confusion_matrix, roc_curve, auc\n\n# Path dataset\npath = '/kaggle/input/rsna-miccai-brain-tumor-radiogenomic-classification/'\ntrain_labels = pd.read_csv(path + 'train_labels.csv')\n\nIMG_SIZE = 128\nBATCH_SIZE = 8\nEPOCHS = 50\nMODALITIES = [\n    \"FLAIR\",\n    \"T1w\",\n    \"T1wCE\",\n    \"T2w\"\n]\n\ndef load_dicom_image(path):\n\n    dicom = pydicom.dcmread(path)\n\n    img = dicom.pixel_array.astype(np.float32)\n\n    img = cv2.normalize(img, None, 0, 1, cv2.NORM_MINMAX)\n\n    return img\n\n\n\n\nimport glob\n\ndef load_patient_data(patient_id, img_size=128, num_slices=32):\n\n    patient_id = str(patient_id).zfill(5)\n\n    patient_path = os.path.join(path, \"train\", patient_id)\n\n    modalities = [\"FLAIR\", \"T1w\", \"T1wCE\", \"T2w\"]\n\n    modality_volumes = []\n\n    for modality in modalities:\n\n        modality_folder = os.path.join(patient_path, modality)\n\n        if not os.path.exists(modality_folder):\n            return None\n\n        dicom_files = sorted(glob.glob(os.path.join(modality_folder, \"*.dcm\")))\n\n        if len(dicom_files) == 0:\n            return None\n\n        indices = np.linspace(\n            0,\n            len(dicom_files)-1,\n            num_slices\n        ).astype(int)\n\n        slices = []\n\n        for idx in indices:\n\n            img = load_dicom_image(dicom_files[idx])\n\n            img = cv2.resize(img, (img_size, img_size))\n\n            slices.append(img)\n\n        volume = np.stack(slices, axis=0)\n\n        modality_volumes.append(volume)\n\n    # (Slices, Height, Width, 4 modalités)\n    volume = np.stack(modality_volumes, axis=-1)\n    if np.random.rand() < 0.5:\n       volume = np.flip(volume, axis=1)\n\n    if np.random.rand() < 0.5:\n       volume = np.flip(volume, axis=2)\n\n    return volume.astype(np.float32)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-10T22:49:14.459935Z","iopub.execute_input":"2026-07-10T22:49:14.460484Z","iopub.status.idle":"2026-07-10T22:49:28.608252Z","shell.execute_reply.started":"2026-07-10T22:49:14.460464Z","shell.execute_reply":"2026-07-10T22:49:28.607497Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"X = []\ny = []\n\nprint(\"Memuat data training...\")\nfor idx, row in train_labels.iterrows():\n    patient_id = row['BraTS21ID']\n    label = row['MGMT_value']\n\n    patient_data = load_patient_data(patient_id)\n\n    if patient_data is not None:\n        X.append(patient_data)\n        y.append(label)\n\nX = np.array(X, dtype=np.float32)\ny = np.array(y, dtype=np.float32)\n\nprint(f\"Total data yang dimuat: {len(X)} sampel\")\nprint(f\"Distribusi kelas: {np.sum(y == 1)} positif, {np.sum(y == 0)} negatif\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-10T22:49:28.609110Z","iopub.execute_input":"2026-07-10T22:49:28.609465Z","iopub.status.idle":"2026-07-10T22:58:57.412461Z","shell.execute_reply.started":"2026-07-10T22:49:28.609445Z","shell.execute_reply":"2026-07-10T22:58:57.411407Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Split data: training (60%), validation (20%), test (20%)\nfrom sklearn.model_selection import train_test_split\nX_train, X_temp, y_train, y_temp = train_test_split(\n    X, y, test_size=0.4, random_state=42, stratify=y\n)\nX_val, X_test, y_val, y_test = train_test_split(\n    X_temp, y_temp, test_size=0.5, random_state=42, stratify=y_temp\n)\n\nprint(\"\\nDistribusi dataset:\")\nprint(f\"Training:   {len(X_train)} sampel\")\nprint(f\"Validation: {len(X_val)} sampel\")\nprint(f\"Test:       {len(X_test)} sampel\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-10T22:58:57.413570Z","iopub.execute_input":"2026-07-10T22:58:57.413913Z","iopub.status.idle":"2026-07-10T22:59:00.236436Z","shell.execute_reply.started":"2026-07-10T22:58:57.413892Z","shell.execute_reply":"2026-07-10T22:59:00.235600Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from tensorflow.keras import regularizers\ndef build_3d_cnn(input_shape):\n\n    model = tf.keras.Sequential([\n\n        layers.Conv3D(\n            32, 3,\n            padding='same',\n            activation='relu',\n            kernel_regularizer=regularizers.l2(1e-4),\n            input_shape=input_shape\n        ),\n        layers.BatchNormalization(),\n        layers.MaxPooling3D(2),\n\n        layers.Conv3D(\n            64, 3,\n            padding='same',\n            activation='relu',\n            kernel_regularizer=regularizers.l2(1e-4)\n        ),\n        layers.BatchNormalization(),\n        layers.MaxPooling3D(2),\n\n        layers.Conv3D(\n            128, 3,\n            padding='same',\n            activation='relu',\n            kernel_regularizer=regularizers.l2(1e-4)\n        ),\n        layers.BatchNormalization(),\n        layers.MaxPooling3D(2),\n\n        layers.Conv3D(\n            256, 3,\n            padding='same',\n            activation='relu',\n            kernel_regularizer=regularizers.l2(1e-4)\n        ),\n        layers.BatchNormalization(),\n\n        layers.GlobalAveragePooling3D(),\n\n        layers.Dense(\n            256,\n            activation='relu',\n            kernel_regularizer=regularizers.l2(1e-4)\n        ),\n        layers.Dropout(0.4),\n\n        layers.Dense(\n            128,\n            activation='relu',\n            kernel_regularizer=regularizers.l2(1e-4)\n        ),\n        layers.Dropout(0.3),\n\n        layers.Dense(1, activation='sigmoid')\n\n    ])\n\n    return model","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-10T22:59:00.237394Z","iopub.execute_input":"2026-07-10T22:59:00.238417Z","iopub.status.idle":"2026-07-10T22:59:00.245857Z","shell.execute_reply.started":"2026-07-10T22:59:00.238395Z","shell.execute_reply":"2026-07-10T22:59:00.244992Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"input_shape = (X_train.shape[1], X_train.shape[2], X_train.shape[3], X_train.shape[4])\nprint(f\"\\nInput shape: {input_shape}\")\nmodel = build_3d_cnn(input_shape)\n\nmodel.summary()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-10T22:59:00.246697Z","iopub.execute_input":"2026-07-10T22:59:00.247074Z","iopub.status.idle":"2026-07-10T22:59:02.404690Z","shell.execute_reply.started":"2026-07-10T22:59:00.247054Z","shell.execute_reply":"2026-07-10T22:59:02.403972Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model.compile(\n    optimizer=tf.keras.optimizers.AdamW(\n        learning_rate=5e-5,\n        weight_decay=1e-5\n    ),\n    loss='binary_crossentropy',\n    metrics=[\n        'accuracy',\n        tf.keras.metrics.AUC(name='auc')\n    ]\n)\n# Callback\n\ncallbacks = [\n    tf.keras.callbacks.EarlyStopping(\n        monitor='val_auc',\n        patience=10,\n        mode='max',\n        restore_best_weights=True,\n        verbose=1\n    ),\n\n    tf.keras.callbacks.ReduceLROnPlateau(\n        monitor='val_loss',\n        factor=0.2,\n        patience=3,\n        min_lr=1e-6,\n        verbose=1\n    ),\n\n    tf.keras.callbacks.ModelCheckpoint(\n        'best_model.h5',\n        monitor='val_auc',\n        mode='max',\n        save_best_only=True,\n        verbose=1\n    )\n]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-10T22:59:02.405455Z","iopub.execute_input":"2026-07-10T22:59:02.405824Z","iopub.status.idle":"2026-07-10T22:59:02.432704Z","shell.execute_reply.started":"2026-07-10T22:59:02.405783Z","shell.execute_reply":"2026-07-10T22:59:02.431942Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from sklearn.utils.class_weight import compute_class_weight\nimport numpy as np\n\nweights = compute_class_weight(\n    class_weight=\"balanced\",\n    classes=np.unique(y_train),\n    y=y_train\n)\n\nclass_weights = {\n    0: weights[0],\n    1: weights[1]\n}\nprint(\"\\nMemulai training...\")\nhistory = model.fit(\n    X_train, y_train,\n    validation_data=(X_val, y_val),\n    batch_size=BATCH_SIZE,\n    epochs=EPOCHS,\n    callbacks=callbacks,\n    class_weight=class_weights\n)\n\n# Plot history training\ndef plot_history(history):\n    plt.figure(figsize=(12, 5))\n    \n    # Plot loss\n    plt.subplot(1, 2, 1)\n    plt.plot(history.history['loss'], label='Training Loss')\n    plt.plot(history.history['val_loss'], label='Validation Loss')\n    plt.title('Training and Validation Loss')\n    plt.xlabel('Epoch')\n    plt.ylabel('Loss')\n    plt.legend()\n    \n    # Plot AUC\n    plt.subplot(1, 2, 2)\n    plt.plot(history.history['auc'], label='Training AUC')\n    plt.plot(history.history['val_auc'], label='Validation AUC')\n    plt.title('Training and Validation AUC')\n    plt.xlabel('Epoch')\n    plt.ylabel('AUC')\n    plt.legend()\n    \n    plt.tight_layout()\n    plt.savefig('training_history.png')\n    plt.show()\n\nplot_history(history)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-10T22:59:02.433608Z","iopub.execute_input":"2026-07-10T22:59:02.434082Z","iopub.status.idle":"2026-07-10T23:03:02.525841Z","shell.execute_reply.started":"2026-07-10T22:59:02.434036Z","shell.execute_reply":"2026-07-10T23:03:02.525051Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import tensorflow as tf\n\nprint(tf.executing_eagerly())","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-10T23:03:02.526825Z","iopub.execute_input":"2026-07-10T23:03:02.527115Z","iopub.status.idle":"2026-07-10T23:03:02.532000Z","shell.execute_reply.started":"2026-07-10T23:03:02.527090Z","shell.execute_reply":"2026-07-10T23:03:02.531280Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"y_pred_prob = model.predict(X_test).flatten()\ny_pred = (y_pred_prob > 0.53).astype(int)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-10T23:03:02.532754Z","iopub.execute_input":"2026-07-10T23:03:02.533101Z","iopub.status.idle":"2026-07-10T23:03:10.605776Z","shell.execute_reply.started":"2026-07-10T23:03:02.533074Z","shell.execute_reply":"2026-07-10T23:03:10.604817Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from sklearn.metrics import accuracy_score\ntest_loss, test_acc, test_auc = model.evaluate(X_test, y_test, verbose=0)\n\nprint(\"Accuracy sklearn :\", accuracy_score(y_test, y_pred))\nprint(\"Accuracy keras   :\", test_acc)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-10T23:03:10.606634Z","iopub.execute_input":"2026-07-10T23:03:10.606937Z","iopub.status.idle":"2026-07-10T23:03:15.831386Z","shell.execute_reply.started":"2026-07-10T23:03:10.606920Z","shell.execute_reply":"2026-07-10T23:03:15.830603Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from sklearn.metrics import accuracy_score, classification_report, confusion_matrix\nimport tensorflow as tf\n\n# Charger le meilleur modèle\nmodel = tf.keras.models.load_model(\"best_model.h5\")\n\n# ===========================\n# Evaluation sur le jeu de validation\n# ===========================\nval_loss, _, val_auc = model.evaluate(X_val, y_val, verbose=0)\n\nthreshold = 0.53  \n\nval_pred_prob = model.predict(X_val, batch_size=2).flatten()\nval_pred = (val_pred_prob >= threshold).astype(int)\n\nval_acc = accuracy_score(y_val, val_pred)\n\nprint(\"========== VALIDATION ==========\")\nprint(f\"Validation Loss     : {val_loss:.4f}\")\nprint(f\"Validation AUC      : {val_auc:.4f}\")\nprint(f\"Validation Accuracy : {val_acc:.4f}\")\nprint(classification_report(y_val, val_pred))\nprint(confusion_matrix(y_val, val_pred))\n\n\n# ===========================\n# Evaluation sur le jeu de test\n# ===========================\ntest_loss, _, test_auc = model.evaluate(X_test, y_test, verbose=0)\n\ntest_pred_prob = model.predict(X_test, batch_size=2).flatten()\ntest_pred = (test_pred_prob >= threshold).astype(int)\n\ntest_acc = accuracy_score(y_test, test_pred)\n\nprint(\"\\n========== TEST ==========\")\nprint(f\"Test Loss     : {test_loss:.4f}\")\nprint(f\"Test AUC      : {test_auc:.4f}\")\nprint(f\"Test Accuracy : {test_acc:.4f}\")\nprint(classification_report(y_test, test_pred))\nprint(confusion_matrix(y_test, test_pred))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-10T23:03:15.832195Z","iopub.execute_input":"2026-07-10T23:03:15.832500Z","iopub.status.idle":"2026-07-10T23:03:34.930344Z","shell.execute_reply.started":"2026-07-10T23:03:15.832482Z","shell.execute_reply":"2026-07-10T23:03:34.929303Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"fpr, tpr, thresholds = roc_curve(y_test, y_pred_prob)\nroc_auc = auc(fpr, tpr)\n\nplt.figure()\nplt.plot(fpr, tpr, color='darkorange', lw=2, label=f'ROC curve (area = {roc_auc:.2f})')\nplt.plot([0, 1], [0, 1], color='navy', lw=2, linestyle='--')\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')\nplt.legend(loc=\"lower right\")\nplt.savefig('roc_curve.png')\nplt.show()\n\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-10T23:03:34.933973Z","iopub.execute_input":"2026-07-10T23:03:34.934661Z","iopub.status.idle":"2026-07-10T23:03:35.200064Z","shell.execute_reply.started":"2026-07-10T23:03:34.934620Z","shell.execute_reply":"2026-07-10T23:03:35.199106Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model.save('final_model.h5')\nprint(\"\\nModel 'final_model.h5'\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-10T23:03:35.201226Z","iopub.execute_input":"2026-07-10T23:03:35.201610Z","iopub.status.idle":"2026-07-10T23:03:35.258016Z","shell.execute_reply.started":"2026-07-10T23:03:35.201565Z","shell.execute_reply":"2026-07-10T23:03:35.257324Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\n\nprint(os.path.exists(\"best_model.h5\"))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-10T23:03:35.259012Z","iopub.execute_input":"2026-07-10T23:03:35.259251Z","iopub.status.idle":"2026-07-10T23:03:35.264074Z","shell.execute_reply.started":"2026-07-10T23:03:35.259235Z","shell.execute_reply":"2026-07-10T23:03:35.263241Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from sklearn.metrics import accuracy_score\n\nbest_acc = 0\nbest_t = 0\n\nfor t in np.arange(0.30, 0.71, 0.01):\n    pred = (y_pred_prob > t).astype(int)\n    acc = accuracy_score(y_test, pred)\n\n    if acc > best_acc:\n        best_acc = acc\n        best_t = t\n\nprint(\"Best threshold =\", best_t)\nprint(\"Best accuracy =\", best_acc)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-10T23:03:35.264884Z","iopub.execute_input":"2026-07-10T23:03:35.265940Z","iopub.status.idle":"2026-07-10T23:03:35.299221Z","shell.execute_reply.started":"2026-07-10T23:03:35.265118Z","shell.execute_reply":"2026-07-10T23:03:35.298585Z"}},"outputs":[],"execution_count":null}]}