{"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"codemirror_mode":{"name":"ipython","version":3},"file_extension":".py","mimetype":"text/x-python","name":"python","nbconvert_exporter":"python","pygments_lexer":"ipython3","version":"3.11.11"},"kaggle":{"accelerator":"none","dataSources":[{"databundleVersionId":2420395,"sourceId":29653,"sourceType":"competition"}],"dockerImageVersionId":31040,"isGpuEnabled":false,"isInternetEnabled":true,"language":"python","sourceType":"notebook"},"papermill":{"default_parameters":{},"duration":424.62585,"end_time":"2026-07-10T21:04:20.668060","environment_variables":{},"exception":null,"input_path":"__notebook__.ipynb","output_path":"__notebook__.ipynb","parameters":{},"start_time":"2026-07-10T20:57:16.042210","version":"2.6.0"}},"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":{"execution":{"iopub.status.busy":"2026-07-11T02:39:52.733814Z","iopub.execute_input":"2026-07-11T02:39:52.734065Z","iopub.status.idle":"2026-07-11T02:39:52.738857Z","shell.execute_reply.started":"2026-07-11T02:39:52.734048Z","shell.execute_reply":"2026-07-11T02:39:52.737981Z"},"papermill":{"duration":6.941781,"end_time":"2026-07-10T20:57:27.582097","exception":false,"start_time":"2026-07-10T20:57:20.640316","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"path = '/kaggle/input/rsna-miccai-brain-tumor-radiogenomic-classification/'\nos.listdir(path)","metadata":{"execution":{"iopub.status.busy":"2026-07-11T02:39:52.746564Z","iopub.execute_input":"2026-07-11T02:39:52.746818Z","iopub.status.idle":"2026-07-11T02:39:52.758702Z","shell.execute_reply.started":"2026-07-11T02:39:52.746801Z","shell.execute_reply":"2026-07-11T02:39:52.757819Z"},"papermill":{"duration":0.011652,"end_time":"2026-07-10T20:57:27.598193","exception":false,"start_time":"2026-07-10T20:57:27.586541","status":"completed"},"tags":[],"trusted":true},"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":{"execution":{"iopub.status.busy":"2026-07-11T02:39:52.760156Z","iopub.execute_input":"2026-07-11T02:39:52.760392Z","iopub.status.idle":"2026-07-11T02:39:52.773663Z","shell.execute_reply.started":"2026-07-11T02:39:52.760375Z","shell.execute_reply":"2026-07-11T02:39:52.772842Z"},"papermill":{"duration":0.032336,"end_time":"2026-07-10T20:57:27.634951","exception":false,"start_time":"2026-07-10T20:57:27.602615","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print('Samples train:', len(train_data))\nprint('Samples test:', len(samp_subm))","metadata":{"execution":{"iopub.status.busy":"2026-07-11T02:39:52.774480Z","iopub.execute_input":"2026-07-11T02:39:52.774644Z","iopub.status.idle":"2026-07-11T02:39:52.783052Z","shell.execute_reply.started":"2026-07-11T02:39:52.774631Z","shell.execute_reply":"2026-07-11T02:39:52.781994Z"},"papermill":{"duration":0.011222,"end_time":"2026-07-10T20:57:27.652014","exception":false,"start_time":"2026-07-10T20:57:27.640792","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_data.head()","metadata":{"execution":{"iopub.status.busy":"2026-07-11T02:39:52.785111Z","iopub.execute_input":"2026-07-11T02:39:52.785444Z","iopub.status.idle":"2026-07-11T02:39:52.797236Z","shell.execute_reply.started":"2026-07-11T02:39:52.785389Z","shell.execute_reply":"2026-07-11T02:39:52.796615Z"},"papermill":{"duration":0.023123,"end_time":"2026-07-10T20:57:27.679188","exception":false,"start_time":"2026-07-10T20:57:27.656065","status":"completed"},"tags":[],"trusted":true},"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":{"execution":{"iopub.status.busy":"2026-07-11T02:39:52.798252Z","iopub.execute_input":"2026-07-11T02:39:52.798560Z","iopub.status.idle":"2026-07-11T02:39:52.921993Z","shell.execute_reply.started":"2026-07-11T02:39:52.798536Z","shell.execute_reply":"2026-07-11T02:39:52.921095Z"},"papermill":{"duration":0.364456,"end_time":"2026-07-10T20:57:28.048085","exception":false,"start_time":"2026-07-10T20:57:27.683629","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_data[\"MGMT_value\"].value_counts()","metadata":{"execution":{"iopub.status.busy":"2026-07-11T02:39:52.923083Z","iopub.execute_input":"2026-07-11T02:39:52.923384Z","iopub.status.idle":"2026-07-11T02:39:52.931538Z","shell.execute_reply.started":"2026-07-11T02:39:52.923353Z","shell.execute_reply":"2026-07-11T02:39:52.930766Z"},"papermill":{"duration":0.012097,"end_time":"2026-07-10T20:57:28.065251","exception":false,"start_time":"2026-07-10T20:57:28.053154","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"samp_subm.head()","metadata":{"execution":{"iopub.status.busy":"2026-07-11T02:39:52.932393Z","iopub.execute_input":"2026-07-11T02:39:52.932717Z","iopub.status.idle":"2026-07-11T02:39:52.946684Z","shell.execute_reply.started":"2026-07-11T02:39:52.932692Z","shell.execute_reply":"2026-07-11T02:39:52.945764Z"},"papermill":{"duration":0.013251,"end_time":"2026-07-10T20:57:28.083340","exception":false,"start_time":"2026-07-10T20:57:28.070089","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"folder = str(train_data.loc[0, 'BraTS21ID']).zfill(5)\nfolder","metadata":{"execution":{"iopub.status.busy":"2026-07-11T02:39:52.947534Z","iopub.execute_input":"2026-07-11T02:39:52.947755Z","iopub.status.idle":"2026-07-11T02:39:52.959515Z","shell.execute_reply.started":"2026-07-11T02:39:52.947718Z","shell.execute_reply":"2026-07-11T02:39:52.958589Z"},"papermill":{"duration":0.011,"end_time":"2026-07-10T20:57:28.099138","exception":false,"start_time":"2026-07-10T20:57:28.088138","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"os.listdir(path+'train/'+folder)","metadata":{"execution":{"iopub.status.busy":"2026-07-11T02:39:52.960399Z","iopub.execute_input":"2026-07-11T02:39:52.960981Z","iopub.status.idle":"2026-07-11T02:39:52.976973Z","shell.execute_reply.started":"2026-07-11T02:39:52.960964Z","shell.execute_reply":"2026-07-11T02:39:52.976427Z"},"papermill":{"duration":0.016451,"end_time":"2026-07-10T20:57:28.120749","exception":false,"start_time":"2026-07-10T20:57:28.104298","status":"completed"},"tags":[],"trusted":true},"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":{"execution":{"iopub.status.busy":"2026-07-11T02:39:52.978593Z","iopub.execute_input":"2026-07-11T02:39:52.979153Z","iopub.status.idle":"2026-07-11T02:39:52.992788Z","shell.execute_reply.started":"2026-07-11T02:39:52.979136Z","shell.execute_reply":"2026-07-11T02:39:52.991815Z"},"papermill":{"duration":0.057575,"end_time":"2026-07-10T20:57:28.183101","exception":false,"start_time":"2026-07-10T20:57:28.125526","status":"completed"},"tags":[],"trusted":true},"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":{"execution":{"iopub.status.busy":"2026-07-11T02:39:52.993382Z","iopub.execute_input":"2026-07-11T02:39:52.993666Z","iopub.status.idle":"2026-07-11T02:39:53.004357Z","shell.execute_reply.started":"2026-07-11T02:39:52.993622Z","shell.execute_reply":"2026-07-11T02:39:53.003570Z"},"papermill":{"duration":0.019914,"end_time":"2026-07-10T20:57:28.207992","exception":false,"start_time":"2026-07-10T20:57:28.188078","status":"completed"},"tags":[],"trusted":true},"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":{"execution":{"iopub.status.busy":"2026-07-11T02:39:53.005129Z","iopub.execute_input":"2026-07-11T02:39:53.005324Z","iopub.status.idle":"2026-07-11T02:39:53.697838Z","shell.execute_reply.started":"2026-07-11T02:39:53.005310Z","shell.execute_reply":"2026-07-11T02:39:53.697102Z"},"papermill":{"duration":0.733953,"end_time":"2026-07-10T20:57:28.947023","exception":false,"start_time":"2026-07-10T20:57:28.213070","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#T1w Images\nplot_examples(row = row, cat = 'T1w')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2026-07-11T02:39:53.698702Z","iopub.execute_input":"2026-07-11T02:39:53.699016Z","iopub.status.idle":"2026-07-11T02:39:54.333285Z","shell.execute_reply.started":"2026-07-11T02:39:53.698992Z","shell.execute_reply":"2026-07-11T02:39:54.332439Z"},"papermill":{"duration":0.773456,"end_time":"2026-07-10T20:57:29.728280","exception":false,"start_time":"2026-07-10T20:57:28.954824","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#T1wCE Images\nplot_examples(row = row, cat = 'T1wCE')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2026-07-11T02:39:54.335051Z","iopub.execute_input":"2026-07-11T02:39:54.335338Z","iopub.status.idle":"2026-07-11T02:39:54.968964Z","shell.execute_reply.started":"2026-07-11T02:39:54.335321Z","shell.execute_reply":"2026-07-11T02:39:54.968309Z"},"papermill":{"duration":0.752034,"end_time":"2026-07-10T20:57:30.490029","exception":false,"start_time":"2026-07-10T20:57:29.737995","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#T2w Images\nplot_examples(row = row, cat = 'T2w')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2026-07-11T02:39:54.969932Z","iopub.execute_input":"2026-07-11T02:39:54.970233Z","iopub.status.idle":"2026-07-11T02:39:55.617197Z","shell.execute_reply.started":"2026-07-11T02:39:54.970204Z","shell.execute_reply":"2026-07-11T02:39:55.616380Z"},"papermill":{"duration":0.742825,"end_time":"2026-07-10T20:57:31.245153","exception":false,"start_time":"2026-07-10T20:57:30.502328","status":"completed"},"tags":[],"trusted":true},"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\n# Konfigurasi\nIMG_SIZE = 128\nBATCH_SIZE = 16\nEPOCHS = 50\nMODALITIES = ['FLAIR', 'T1w', 'T1wCE', 'T2w']\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    # Stack ke 3 channel\n    img = np.stack([img]*3, axis=-1)\n    return img\n\n# Fungsi untuk memuat data pasien\ndef load_patient_data(patient_id, num_slices=12):\n    all_modality_slices = []\n    for mod in MODALITIES:\n        patient_path = os.path.join(path, 'train', str(patient_id).zfill(5), mod)\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        # on garde 1 seul canal par modalité (pas 3), pour ne pas exploser la taille\n        slices = [s[:,:,0] for s in slices]\n        all_modality_slices.append(np.stack(slices, axis=0))  # (num_slices, H, W)\n    # empile les modalités comme dernier axe -> (num_slices, H, W, 4)\n    volume = np.stack(all_modality_slices, axis=-1)\n    return volume","metadata":{"execution":{"iopub.status.busy":"2026-07-11T02:39:55.618011Z","iopub.execute_input":"2026-07-11T02:39:55.618306Z","iopub.status.idle":"2026-07-11T02:39:55.630367Z","shell.execute_reply.started":"2026-07-11T02:39:55.618289Z","shell.execute_reply":"2026-07-11T02:39:55.629791Z"},"papermill":{"duration":15.133594,"end_time":"2026-07-10T20:57:46.391590","exception":false,"start_time":"2026-07-10T20:57:31.257996","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Membuat dataset\nX = []\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    if patient_data is not None:\n        X.append(patient_data)\n        y.append(label)\n\n# Konversi ke numpy array\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":{"execution":{"iopub.status.busy":"2026-07-11T02:39:55.631144Z","iopub.execute_input":"2026-07-11T02:39:55.631473Z","iopub.status.idle":"2026-07-11T02:41:27.872658Z","shell.execute_reply.started":"2026-07-11T02:39:55.631443Z","shell.execute_reply":"2026-07-11T02:41:27.871886Z"},"papermill":{"duration":304.16131,"end_time":"2026-07-10T21:02:50.567392","exception":false,"start_time":"2026-07-10T20:57:46.406082","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Split data: training (60%), validation (20%), test (20%)\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":{"execution":{"iopub.status.busy":"2026-07-11T02:41:27.873462Z","iopub.execute_input":"2026-07-11T02:41:27.873647Z","iopub.status.idle":"2026-07-11T02:41:28.644307Z","shell.execute_reply.started":"2026-07-11T02:41:27.873633Z","shell.execute_reply":"2026-07-11T02:41:28.643389Z"},"papermill":{"duration":0.733763,"end_time":"2026-07-10T21:02:51.313646","exception":false,"start_time":"2026-07-10T21:02:50.579883","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Arsitektur model CNN 3D\ndef build_3d_cnn(input_shape, num_classes):\n    model = models.Sequential([\n        # Blok konvolusi 1\n        layers.Conv3D(32, (3, 3, 3), activation='relu', padding='same', input_shape=input_shape),\n        layers.BatchNormalization(),\n        layers.MaxPooling3D((2, 2, 2)),\n        layers.Dropout(0.2),\n        \n        # Blok konvolusi 2\n        layers.Conv3D(64, (3, 3, 3), activation='relu', padding='same'),\n        layers.BatchNormalization(),\n        layers.MaxPooling3D((2, 2, 2)),\n        layers.Dropout(0.3),\n        \n        # Blok konvolusi 3\n        layers.Conv3D(128, (3, 3, 3), activation='relu', padding='same'),\n        layers.BatchNormalization(),\n        layers.MaxPooling3D((2, 2, 2)),\n        layers.Dropout(0.3),\n        \n        layers.GlobalAveragePooling3D(),\n        layers.Dense(64, activation='relu'),\n        layers.Dropout(0.5),\n        layers.Dense(num_classes, activation='sigmoid')\n    ])\n    \n    return model","metadata":{"execution":{"iopub.status.busy":"2026-07-11T02:41:28.645195Z","iopub.execute_input":"2026-07-11T02:41:28.646299Z","iopub.status.idle":"2026-07-11T02:41:28.652217Z","shell.execute_reply.started":"2026-07-11T02:41:28.646280Z","shell.execute_reply":"2026-07-11T02:41:28.651233Z"},"papermill":{"duration":0.019781,"end_time":"2026-07-10T21:02:51.346089","exception":false,"start_time":"2026-07-10T21:02:51.326308","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Bangun model\ninput_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, num_classes=1)\n\n# Ringkasan model\nmodel.summary()","metadata":{"execution":{"iopub.status.busy":"2026-07-11T02:41:28.653035Z","iopub.execute_input":"2026-07-11T02:41:28.653315Z","iopub.status.idle":"2026-07-11T02:41:28.763237Z","shell.execute_reply.started":"2026-07-11T02:41:28.653280Z","shell.execute_reply":"2026-07-11T02:41:28.762465Z"},"papermill":{"duration":2.443186,"end_time":"2026-07-10T21:02:53.801412","exception":false,"start_time":"2026-07-10T21:02:51.358226","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Kompilasi model\nmodel.compile(\n    optimizer=tf.keras.optimizers.Adam(learning_rate=0.0005),\n    loss='binary_crossentropy',\n    metrics=['accuracy', tf.keras.metrics.AUC(name='auc')]\n)\n\n# Callback\ncallbacks = [\n    tf.keras.callbacks.EarlyStopping(\n        patience=8, \n        monitor='val_auc', \n        mode='max', \n        restore_best_weights=True,\n        verbose=1\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    tf.keras.callbacks.ModelCheckpoint(\n        filepath='best_model.h5',\n        save_best_only=True,\n        monitor='val_auc',\n        mode='max',\n        verbose=1\n    )\n]","metadata":{"execution":{"iopub.status.busy":"2026-07-11T02:41:28.764501Z","iopub.execute_input":"2026-07-11T02:41:28.764781Z","iopub.status.idle":"2026-07-11T02:41:28.778262Z","shell.execute_reply.started":"2026-07-11T02:41:28.764748Z","shell.execute_reply":"2026-07-11T02:41:28.777709Z"},"papermill":{"duration":0.037517,"end_time":"2026-07-10T21:02:53.853383","exception":false,"start_time":"2026-07-10T21:02:53.815866","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#Training\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)\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":{"execution":{"iopub.status.busy":"2026-07-11T02:41:28.778975Z","iopub.execute_input":"2026-07-11T02:41:28.779232Z","iopub.status.idle":"2026-07-11T02:43:59.003837Z","shell.execute_reply.started":"2026-07-11T02:41:28.779215Z","shell.execute_reply":"2026-07-11T02:43:59.003067Z"},"papermill":{"duration":71.124311,"end_time":"2026-07-10T21:04:04.991255","exception":false,"start_time":"2026-07-10T21:02:53.866944","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Evaluasi pada validation set\nprint(\"\\nEvaluasi pada validation set:\")\nval_loss, val_acc, val_auc = model.evaluate(X_val, y_val)\nprint(f\"Validation Loss: {val_loss:.4f}\")\nprint(f\"Validation Accuracy: {val_acc:.4f}\")\nprint(f\"Validation AUC: {val_auc:.4f}\")\n\n# Evaluasi pada test set\nprint(\"\\nEvaluasi pada test set:\")\ntest_loss, test_acc, test_auc = model.evaluate(X_test, y_test)\nprint(f\"Test Loss: {test_loss:.4f}\")\nprint(f\"Test Accuracy: {test_acc:.4f}\")\nprint(f\"Test AUC: {test_auc:.4f}\")","metadata":{"execution":{"iopub.status.busy":"2026-07-11T02:43:59.006166Z","iopub.execute_input":"2026-07-11T02:43:59.006525Z","iopub.status.idle":"2026-07-11T02:44:03.169505Z","shell.execute_reply.started":"2026-07-11T02:43:59.006505Z","shell.execute_reply":"2026-07-11T02:44:03.168865Z"},"papermill":{"duration":8.613609,"end_time":"2026-07-10T21:04:13.631221","exception":false,"start_time":"2026-07-10T21:04:05.017612","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Prediksi pada test set\ny_pred_prob = model.predict(X_test).flatten()\ny_pred = (y_pred_prob > 0.5).astype(int)","metadata":{"execution":{"iopub.status.busy":"2026-07-11T02:44:03.171510Z","iopub.execute_input":"2026-07-11T02:44:03.171704Z","iopub.status.idle":"2026-07-11T02:44:05.617575Z","shell.execute_reply.started":"2026-07-11T02:44:03.171689Z","shell.execute_reply":"2026-07-11T02:44:05.616637Z"},"papermill":{"duration":2.572533,"end_time":"2026-07-10T21:04:16.229259","exception":false,"start_time":"2026-07-10T21:04:13.656726","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Classification report\nprint(\"\\nClassification Report:\")\nprint(classification_report(y_test, y_pred))","metadata":{"execution":{"iopub.status.busy":"2026-07-11T02:44:05.618486Z","iopub.execute_input":"2026-07-11T02:44:05.618795Z","iopub.status.idle":"2026-07-11T02:44:05.634719Z","shell.execute_reply.started":"2026-07-11T02:44:05.618758Z","shell.execute_reply":"2026-07-11T02:44:05.633705Z"},"papermill":{"duration":0.041129,"end_time":"2026-07-10T21:04:16.296615","exception":false,"start_time":"2026-07-10T21:04:16.255486","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Confusion matrix\nconf_matrix = confusion_matrix(y_test, y_pred)\nprint(\"\\nConfusion Matrix:\")\nprint(conf_matrix)","metadata":{"execution":{"iopub.status.busy":"2026-07-11T02:44:05.635862Z","iopub.execute_input":"2026-07-11T02:44:05.636339Z","iopub.status.idle":"2026-07-11T02:44:05.644777Z","shell.execute_reply.started":"2026-07-11T02:44:05.636319Z","shell.execute_reply":"2026-07-11T02:44:05.643784Z"},"papermill":{"duration":0.037002,"end_time":"2026-07-10T21:04:16.358589","exception":false,"start_time":"2026-07-10T21:04:16.321587","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Plot ROC curve\nfpr, 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()","metadata":{"execution":{"iopub.status.busy":"2026-07-11T02:44:05.645728Z","iopub.execute_input":"2026-07-11T02:44:05.646108Z","iopub.status.idle":"2026-07-11T02:44:05.925787Z","shell.execute_reply.started":"2026-07-11T02:44:05.646086Z","shell.execute_reply":"2026-07-11T02:44:05.925099Z"},"papermill":{"duration":0.266944,"end_time":"2026-07-10T21:04:16.652557","exception":false,"start_time":"2026-07-10T21:04:16.385613","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Simpan model akhir\nmodel.save('final_model.h5')\nprint(\"\\nModel akhir disimpan sebagai 'final_model.h5'\")","metadata":{"execution":{"iopub.status.busy":"2026-07-11T02:44:05.926652Z","iopub.execute_input":"2026-07-11T02:44:05.926889Z","iopub.status.idle":"2026-07-11T02:44:05.994791Z","shell.execute_reply.started":"2026-07-11T02:44:05.926873Z","shell.execute_reply":"2026-07-11T02:44:05.993847Z"},"papermill":{"duration":0.084503,"end_time":"2026-07-10T21:04:16.763753","exception":false,"start_time":"2026-07-10T21:04:16.679250","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null}]}