{"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\n\nimport warnings\nwarnings.filterwarnings(\"ignore\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-11T01:40:42.660967Z","iopub.execute_input":"2026-07-11T01:40:42.661387Z","iopub.status.idle":"2026-07-11T01:40:44.833976Z","shell.execute_reply.started":"2026-07-11T01:40:42.661364Z","shell.execute_reply":"2026-07-11T01:40:44.833317Z"}},"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-11T01:40:44.835097Z","iopub.execute_input":"2026-07-11T01:40:44.835496Z","iopub.status.idle":"2026-07-11T01:40:44.841628Z","shell.execute_reply.started":"2026-07-11T01:40:44.835476Z","shell.execute_reply":"2026-07-11T01:40:44.840560Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"path = '/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')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-11T01:40:44.842412Z","iopub.execute_input":"2026-07-11T01:40:44.842680Z","iopub.status.idle":"2026-07-11T01:40:44.859120Z","shell.execute_reply.started":"2026-07-11T01:40:44.842658Z","shell.execute_reply":"2026-07-11T01:40:44.858465Z"}},"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-11T01:40:44.860980Z","iopub.execute_input":"2026-07-11T01:40:44.861574Z","iopub.status.idle":"2026-07-11T01:40:44.865569Z","shell.execute_reply.started":"2026-07-11T01:40:44.861550Z","shell.execute_reply":"2026-07-11T01:40:44.864891Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_data.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-11T01:40:44.866178Z","iopub.execute_input":"2026-07-11T01:40:44.866420Z","iopub.status.idle":"2026-07-11T01:40:44.880663Z","shell.execute_reply.started":"2026-07-11T01:40:44.866397Z","shell.execute_reply":"2026-07-11T01:40:44.879869Z"}},"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-11T01:40:44.881423Z","iopub.execute_input":"2026-07-11T01:40:44.881694Z","iopub.status.idle":"2026-07-11T01:40:45.014339Z","shell.execute_reply.started":"2026-07-11T01:40:44.881678Z","shell.execute_reply":"2026-07-11T01:40:45.013754Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_data[\"MGMT_value\"].value_counts()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-11T01:40:45.015021Z","iopub.execute_input":"2026-07-11T01:40:45.015619Z","iopub.status.idle":"2026-07-11T01:40:45.020977Z","shell.execute_reply.started":"2026-07-11T01:40:45.015593Z","shell.execute_reply":"2026-07-11T01:40:45.020294Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"samp_subm.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-11T01:40:45.021826Z","iopub.execute_input":"2026-07-11T01:40:45.022390Z","iopub.status.idle":"2026-07-11T01:40:45.036784Z","shell.execute_reply.started":"2026-07-11T01:40:45.022370Z","shell.execute_reply":"2026-07-11T01:40:45.036096Z"}},"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-11T01:40:45.037635Z","iopub.execute_input":"2026-07-11T01:40:45.037890Z","iopub.status.idle":"2026-07-11T01:40:45.049482Z","shell.execute_reply.started":"2026-07-11T01:40:45.037866Z","shell.execute_reply":"2026-07-11T01:40:45.048662Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"os.listdir(path+'train/'+folder)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-11T01:40:45.052285Z","iopub.execute_input":"2026-07-11T01:40:45.053053Z","iopub.status.idle":"2026-07-11T01:40:45.065956Z","shell.execute_reply.started":"2026-07-11T01:40:45.053022Z","shell.execute_reply":"2026-07-11T01:40:45.065298Z"}},"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-11T01:40:45.066762Z","iopub.execute_input":"2026-07-11T01:40:45.066984Z","iopub.status.idle":"2026-07-11T01:40:45.080002Z","shell.execute_reply.started":"2026-07-11T01:40:45.066968Z","shell.execute_reply":"2026-07-11T01:40:45.079154Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"path_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)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-11T01:40:45.080686Z","iopub.execute_input":"2026-07-11T01:40:45.081411Z","iopub.status.idle":"2026-07-11T01:40:45.092938Z","shell.execute_reply.started":"2026-07-11T01:40:45.081394Z","shell.execute_reply":"2026-07-11T01:40:45.092276Z"}},"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-11T01:40:45.093619Z","iopub.execute_input":"2026-07-11T01:40:45.093924Z","iopub.status.idle":"2026-07-11T01:40:45.741771Z","shell.execute_reply.started":"2026-07-11T01:40:45.093899Z","shell.execute_reply":"2026-07-11T01:40:45.740939Z"}},"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-11T01:40:45.742622Z","iopub.execute_input":"2026-07-11T01:40:45.742859Z","iopub.status.idle":"2026-07-11T01:40:46.468298Z","shell.execute_reply.started":"2026-07-11T01:40:45.742842Z","shell.execute_reply":"2026-07-11T01:40:46.467407Z"}},"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-11T01:40:46.469045Z","iopub.execute_input":"2026-07-11T01:40:46.469253Z","iopub.status.idle":"2026-07-11T01:40:47.217176Z","shell.execute_reply.started":"2026-07-11T01:40:46.469237Z","shell.execute_reply":"2026-07-11T01:40:47.216492Z"}},"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-11T01:40:47.218377Z","iopub.execute_input":"2026-07-11T01:40:47.218673Z","iopub.status.idle":"2026-07-11T01:40:47.835101Z","shell.execute_reply.started":"2026-07-11T01:40:47.218647Z","shell.execute_reply":"2026-07-11T01:40:47.834463Z"}},"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 tensorflow.keras.applications import EfficientNetB0\nfrom tensorflow.keras.applications.efficientnet import preprocess_input\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\n# Konfigurasi\nIMG_SIZE = 128\nBATCH_SIZE = 32\nEPOCHS = 15\nMODALITY = 'FLAIR' \n\ndef crop_center(img, crop_size=80):\n    h, w = img.shape[:2]\n    start_h, start_w = (h - crop_size)//2, (w - crop_size)//2\n    cropped = img[start_h:start_h+crop_size, start_w:start_w+crop_size]\n    return cv2.resize(cropped, (h, w))  # remet à la taille d'origine 128x128\n\n# Fungsi untuk membaca dan memproses gambar DICOM\ndef load_dicom_image(filepath, img_size=IMG_SIZE):\n    dicom = pydicom.dcmread(filepath)\n    img = dicom.pixel_array.astype(float)\n    \n    # Normalisasi\n    img = (img - img.min()) / (img.max() - img.min())\n    \n    # Konversi ke uint8\n    img = (img * 255).astype(np.uint8)\n    \n    # Resize\n    img = cv2.resize(img, (img_size, img_size))\n    \n    # Recadrage centré sur la zone tumorale probable  <-- LIGNE AJOUTÉE\n    img = crop_center(img, crop_size=80)\n    \n    # Stack ke 3 channel\n    img = np.stack([img]*3, axis=-1)\n    return img\n\ndef load_patient_slices_2d(patient_id, num_slices=16, modality='FLAIR'):\n    patient_path = os.path.join(path, 'train', str(patient_id).zfill(5), modality)\n    if not os.path.exists(patient_path):\n        return None\n    dicom_files = sorted([f for f in os.listdir(patient_path) if f.endswith('.dcm')])\n    if not dicom_files:\n        return None\n    step = max(1, len(dicom_files) // num_slices)\n    selected_files = dicom_files[::step][:num_slices]\n    slices = [load_dicom_image(os.path.join(patient_path, f)) for f in selected_files]\n    while len(slices) < num_slices:\n        slices.append(slices[-1])\n    return np.array(slices)  # shape (num_slices, 128, 128, 3)\n    ","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-11T01:40:47.835998Z","iopub.execute_input":"2026-07-11T01:40:47.836768Z","iopub.status.idle":"2026-07-11T01:40:51.088924Z","shell.execute_reply.started":"2026-07-11T01:40:47.836742Z","shell.execute_reply":"2026-07-11T01:40:51.088093Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"X_slices, y_slices, patient_ids_per_slice = [], [], []\n\nfor _, row in train_labels.iterrows():\n    pid = row['BraTS21ID']\n    label = row['MGMT_value']\n    slices = load_patient_slices_2d(pid)\n    if slices is not None:\n        for s in slices:\n            X_slices.append(s)\n            y_slices.append(label)\n            patient_ids_per_slice.append(pid)\n\nX_slices = np.array(X_slices)\ny_slices = np.array(y_slices)\npatient_ids_per_slice = np.array(patient_ids_per_slice) \nprint(f\"Total slices: {len(X_slices)}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-11T01:40:51.089934Z","iopub.execute_input":"2026-07-11T01:40:51.090238Z","iopub.status.idle":"2026-07-11T01:41:17.650555Z","shell.execute_reply.started":"2026-07-11T01:40:51.090207Z","shell.execute_reply":"2026-07-11T01:41:17.649428Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"unique_patients = train_labels['BraTS21ID'].values\ntrain_p, temp_p = train_test_split(unique_patients, test_size=0.4, random_state=42,\n                                     stratify=train_labels.set_index('BraTS21ID').loc[unique_patients]['MGMT_value'])\nval_p, test_p = train_test_split(temp_p, test_size=0.5, random_state=42,\n                                   stratify=train_labels.set_index('BraTS21ID').loc[temp_p]['MGMT_value'])\n\ndef filter_by_patients(patient_list):\n    mask = np.isin(patient_ids_per_slice, patient_list)\n    return X_slices[mask], y_slices[mask]\n\nX_train_2d, y_train_2d = filter_by_patients(train_p)\nX_val_2d, y_val_2d = filter_by_patients(val_p)\nX_test_2d, y_test_2d = filter_by_patients(test_p)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-11T01:41:17.651484Z","iopub.execute_input":"2026-07-11T01:41:17.651855Z","iopub.status.idle":"2026-07-11T01:41:17.781466Z","shell.execute_reply.started":"2026-07-11T01:41:17.651837Z","shell.execute_reply":"2026-07-11T01:41:17.780853Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def build_transfer_model(input_shape=(128,128,3)):\n    base_model = EfficientNetB0(weights='imagenet', include_top=False, input_shape=input_shape)\n    base_model.trainable = False  # on gèle le backbone au début\n\n    model = models.Sequential([\n        base_model,\n        layers.GlobalAveragePooling2D(),\n        layers.Dense(64, activation='relu'),\n        layers.Dropout(0.3),\n        layers.Dense(1, activation='sigmoid')\n    ])\n    return model\n\nmodel_2d = build_transfer_model()\nmodel_2d.compile(\n    optimizer=tf.keras.optimizers.Adam(learning_rate=0.0001),\n    loss='binary_crossentropy',\n    metrics=['accuracy', tf.keras.metrics.AUC(name='auc')]\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-11T01:41:17.782281Z","iopub.execute_input":"2026-07-11T01:41:17.782788Z","iopub.status.idle":"2026-07-11T01:41:20.465219Z","shell.execute_reply.started":"2026-07-11T01:41:17.782760Z","shell.execute_reply":"2026-07-11T01:41:20.464291Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model_2d.compile(\n    optimizer=tf.keras.optimizers.Adam(learning_rate=0.0001),  # 0.0001, pas 0.001 (transfer learning = LR plus faible)\n    loss='binary_crossentropy',\n    metrics=['accuracy', tf.keras.metrics.AUC(name='auc')]\n)\n\ncallbacks = [\n    tf.keras.callbacks.EarlyStopping(patience=8, monitor='val_auc', mode='max', restore_best_weights=True, verbose=1),\n    tf.keras.callbacks.ReduceLROnPlateau(monitor='val_loss', factor=0.5, patience=3, min_lr=1e-6, verbose=1),\n    tf.keras.callbacks.ModelCheckpoint(filepath='best_model_2d.h5', save_best_only=True, monitor='val_auc', mode='max', verbose=1)\n]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-11T01:41:20.466178Z","iopub.execute_input":"2026-07-11T01:41:20.466461Z","iopub.status.idle":"2026-07-11T01:41:20.479685Z","shell.execute_reply.started":"2026-07-11T01:41:20.466438Z","shell.execute_reply":"2026-07-11T01:41:20.478824Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#Training\nhistory_2d = model_2d.fit(\n    preprocess_input(X_train_2d), y_train_2d,\n    validation_data=(preprocess_input(X_val_2d), y_val_2d),\n    batch_size=32,\n    epochs=15,\n    callbacks=callbacks  # réutilise tes callbacks existants\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_2d)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-11T01:41:20.480562Z","iopub.execute_input":"2026-07-11T01:41:20.480918Z","iopub.status.idle":"2026-07-11T01:42:33.829271Z","shell.execute_reply.started":"2026-07-11T01:41:20.480894Z","shell.execute_reply":"2026-07-11T01:42:33.828570Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"y_pred_prob_slices = model_2d.predict(preprocess_input(X_test_2d)).flatten()\ntest_patient_ids = patient_ids_per_slice[np.isin(patient_ids_per_slice, test_p)]\n\ndf_pred = pd.DataFrame({'patient': test_patient_ids, 'prob': y_pred_prob_slices})\npatient_probs = df_pred.groupby('patient')['prob'].mean()  # moyenne des slices par patient\npatient_true = train_labels.set_index('BraTS21ID').loc[patient_probs.index]['MGMT_value']\n\ny_pred_patient = (patient_probs > 0.5).astype(int)\nprint(confusion_matrix(patient_true, y_pred_patient))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-11T01:42:33.830253Z","iopub.execute_input":"2026-07-11T01:42:33.830571Z","iopub.status.idle":"2026-07-11T01:42:47.221717Z","shell.execute_reply.started":"2026-07-11T01:42:33.830537Z","shell.execute_reply":"2026-07-11T01:42:47.220675Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Plot ROC curve\nfpr, tpr, thresholds = roc_curve(patient_true, patient_probs)\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()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-11T01:42:47.222961Z","iopub.execute_input":"2026-07-11T01:42:47.223740Z","iopub.status.idle":"2026-07-11T01:42:47.443359Z","shell.execute_reply.started":"2026-07-11T01:42:47.223720Z","shell.execute_reply":"2026-07-11T01:42:47.442557Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Rapport de classification\nprint(\"Classification Report:\")\nprint(classification_report(patient_true, y_pred_patient))\n\n# Matrice de confusion\nprint(\"\\nConfusion Matrix:\")\nprint(confusion_matrix(patient_true, y_pred_patient))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-11T01:46:13.862179Z","iopub.execute_input":"2026-07-11T01:46:13.862870Z","iopub.status.idle":"2026-07-11T01:46:13.875540Z","shell.execute_reply.started":"2026-07-11T01:46:13.862845Z","shell.execute_reply":"2026-07-11T01:46:13.874684Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"fpr, tpr, thresholds = roc_curve(patient_true, patient_probs)\nroc_auc = auc(fpr, tpr)\nprint(f\"AUC (patient-level): {roc_auc:.3f}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-11T01:47:30.627005Z","iopub.execute_input":"2026-07-11T01:47:30.627309Z","iopub.status.idle":"2026-07-11T01:47:30.635274Z","shell.execute_reply.started":"2026-07-11T01:47:30.627289Z","shell.execute_reply":"2026-07-11T01:47:30.634281Z"}},"outputs":[],"execution_count":null}]}