{"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":39272,"databundleVersionId":4629629,"sourceType":"competition"}],"dockerImageVersionId":31040,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# Import library yang diperlukan\nimport numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nimport os\nimport pydicom\nfrom tqdm import tqdm\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.metrics import classification_report, confusion_matrix, roc_auc_score, roc_curve\n\nimport tensorflow as tf\nfrom tensorflow.keras.models import Sequential\nfrom tensorflow.keras.layers import Conv2D, MaxPooling2D, Flatten, Dense, Dropout, BatchNormalization\nfrom tensorflow.keras.optimizers import Adam\nfrom tensorflow.keras.callbacks import EarlyStopping, ReduceLROnPlateau\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator\n\n# Set random seed untuk reproducibility\ntf.random.set_seed(42)\nnp.random.seed(42)","metadata":{"trusted":true,"execution":{"execution_failed":"2025-05-20T05:14:33.915Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Load metadata\ntrain_df = pd.read_csv('/kaggle/input/rsna-breast-cancer-detection/train.csv')\ntest_df = pd.read_csv('/kaggle/input/rsna-breast-cancer-detection/test.csv')\n\n# Tampilkan info dataset\nprint(\"Train Data Shape:\", train_df.shape)\nprint(\"Test Data Shape:\", test_df.shape)\nprint(\"\\nTrain Data Columns:\", train_df.columns.tolist())\nprint(\"\\nMissing Values in Train Data:\")\nprint(train_df.isnull().sum())\n\n# Distribusi target\nplt.figure(figsize=(8, 6))\nsns.countplot(x='cancer', data=train_df)\nplt.title('Distribution of Cancer Cases')\nplt.show()\n\nprint(\"\\nCancer Distribution:\")\nprint(train_df['cancer'].value_counts(normalize=True))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-20T03:49:39.431984Z","iopub.execute_input":"2025-05-20T03:49:39.432775Z","iopub.status.idle":"2025-05-20T03:49:39.851382Z","shell.execute_reply.started":"2025-05-20T03:49:39.43274Z","shell.execute_reply":"2025-05-20T03:49:39.850082Z"}},"outputs":[{"name":"stdout","text":"Train Data Shape: (54706, 14)\nTest Data Shape: (4, 9)\n\nTrain Data Columns: ['site_id', 'patient_id', 'image_id', 'laterality', 'view', 'age', 'cancer', 'biopsy', 'invasive', 'BIRADS', 'implant', 'density', 'machine_id', 'difficult_negative_case']\n\nMissing Values in Train Data:\nsite_id                        0\npatient_id                     0\nimage_id                       0\nlaterality                     0\nview                           0\nage                           37\ncancer                         0\nbiopsy                         0\ninvasive                       0\nBIRADS                     28420\nimplant                        0\ndensity                    25236\nmachine_id                     0\ndifficult_negative_case        0\ndtype: int64\n","output_type":"stream"},{"output_type":"display_data","data":{"text/plain":"<Figure size 800x600 with 1 Axes>","image/png":"iVBORw0KGgoAAAANSUhEUgAAAskAAAIjCAYAAADx6oYJAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8pXeV/AAAACXBIWXMAAA9hAAAPYQGoP6dpAAA9IUlEQVR4nO3de1RVdcL/8Q8XuSge8IIggZfSUsrLIxrSxbIYT4ZNjlpqTiFqPTloCaXEVGg+lj05jlpqzuSaKKvx0qSVJurgbUoaFaXUCTNHwzIuVnC8gsD+/dHD+Xm+kCIhB533a62zVmfv7/nu7znDYt7tNvt4WJZlCQAAAICTp7sXAAAAADQ2RDIAAABgIJIBAAAAA5EMAAAAGIhkAAAAwEAkAwAAAAYiGQAAADAQyQAAAICBSAYAAAAMRDIAt5o2bZo8PDwa5Fi33367br/9dufzzZs3y8PDQ++++26DHH/06NHq0KFDgxyrrk6cOKFx48YpNDRUHh4emjRpkruXBABuQSQDqDfp6eny8PBwPvz8/BQWFia73a6XX35Zx48fr5fjHD16VNOmTVNOTk69zFefGvPaauOFF15Qenq6xo8fryVLlujBBx887/iKigq9/vrruv3229WyZUv5+vqqQ4cOSkhI0M6dOxto1e5TUFCgJ598Ul26dFHTpk3VrFkzRUVFacaMGSouLnb38gD8Ah6WZVnuXgSAK0N6eroSEhI0ffp0dezYUWfPnlV+fr42b96sDRs2qF27dvrggw/UvXt352vKy8tVXl4uPz+/Wh9n586d6tOnj15//XWNHj261q8rKyuTJPn4+Ej66Uxy//79tWLFCg0bNqzW89R1bWfPnlVlZaV8fX3r5ViXQt++feXt7a2PP/74gmNPnz6tIUOGKCMjQ/369dM999yjli1b6vDhw1q+fLm+/PJL5eXlKTw8vAFW3vB27Nihu+++WydOnNBvf/tbRUVFSfrpZ2Dp0qW66aabtH79ejevEkBdebt7AQCuPAMHDlTv3r2dz1NTU7Vx40YNGjRIv/71r/XFF1/I399fkuTt7S1v70v7q+jUqVNq2rSpM47dpUmTJm49fm0UFhYqMjKyVmMnT56sjIwMzZkzp9plGVOnTtWcOXMuwQobzsmTJ9WsWbMa9xUXF+s3v/mNvLy8tHv3bnXp0sVl//PPP6/XXnutIZYJ4FKxAKCevP7665Yka8eOHTXuf+GFFyxJ1p///GfntqlTp1rmr6L169dbN998sxUYGGg1a9bMuvbaa63U1FTLsixr06ZNlqRqj9dff92yLMu67bbbrOuvv97auXOndeutt1r+/v7W448/7tx32223OY9TNdfSpUut1NRUKyQkxGratKl1zz33WHl5eS5rat++vRUfH1/tPZ0754XWFh8fb7Vv397l9SdOnLCSk5Ot8PBwy8fHx7r22mutWbNmWZWVlS7jJFmJiYnWypUrreuvv97y8fGxIiMjrbVr19b4WZsKCgqsMWPGWG3atLF8fX2t7t27W+np6dU+C/Nx6NChGuc7cuSI5e3tbf3qV7+q1fEPHz5sjR8/3rr22mstPz8/q2XLltawYcOqzV/1M/Txxx9bSUlJVuvWra2mTZtagwcPtgoLC6vN+9FHH1n9+vWzAgICrObNm1u9e/e23n77bZcxn376qWW32y2bzWb5+/tb/fr1sz7++GOXMVU/h/v27bNGjhxpBQUFWT179vzZ9/Piiy9akqod6+esWrXKuvvuu622bdtaPj4+1tVXX21Nnz7dKi8vdxn35ZdfWkOGDLFCQkIsX19f66qrrrKGDx9uFRcXu4xbsmSJ1atXL8vPz89q0aKFNXz48Go/s7WdC0DNOJMMoME8+OCD+v3vf6/169fr4YcfrnHMvn37NGjQIHXv3l3Tp0+Xr6+vvvrqK33yySeSpK5du2r69OlKS0vTI488oltvvVWSdNNNNznn+P777zVw4ECNGDFCv/3tbxUSEnLedT3//PPy8PBQSkqKCgsLNXfuXMXGxionJ8d5xrs2arO2c1mWpV//+tfatGmTxo4dq549e2rdunWaPHmyvv3222pnYj/++GO99957+t3vfqfmzZvr5Zdf1tChQ5WXl6dWrVr97LpOnz6t22+/XV999ZUmTJigjh07asWKFRo9erSKi4v1+OOPq2vXrlqyZImSkpIUHh6uJ554QpIUHBxc45xr165VeXn5Ba9ZrrJjxw5t27ZNI0aMUHh4uA4fPqxXX31Vt99+u/71r3+padOmLuMnTpyoFi1aaOrUqTp8+LDmzp2rCRMmaNmyZc4x6enpGjNmjK6//nqlpqYqKChIu3fvVkZGhh544AFJ0saNGzVw4EBFRUVp6tSp8vT01Ouvv6477rhD//jHP3TjjTe6HPe+++5T586d9cILL8g6z9WIH3zwgfz9/Wt9mU56eroCAgKUnJysgIAAbdy4UWlpaXI4HJo1a5akny4HstvtKi0t1cSJExUaGqpvv/1Wq1evVnFxsQIDAyX99PP67LPP6v7779e4ceNUVFSkV155Rf369dPu3bsVFBRU67kAnIe7Kx3AleNCZ5Ity7ICAwOt//qv/3I+N88kz5kzx5JkFRUV/ewcO3bscDlDe67bbrvNkmQtWrSoxn01nUm+6qqrLIfD4dy+fPlyS5I1b94857banEm+0NrMM8mrVq2yJFkzZsxwGTds2DDLw8PD+uqrr5zbJFk+Pj4u2z777DNLkvXKK69UO9a55s6da0my3nrrLee2srIyKyYmxgoICHB57+3bt7fi4uLOO59lWVZSUpIlydq9e/cFx1qWZZ06daratqysLEuS9eabbzq3Vf0MxcbGupxNT0pKsry8vJxnQYuLi63mzZtb0dHR1unTp13mrXpdZWWl1blzZ8tut7vMderUKatjx44uZ8Grfg5HjhxZq/fTokULq0ePHrUaW3VM03//939bTZs2tc6cOWNZlmXt3r3bkmStWLHiZ+c5fPiw5eXlZT3//PMu2/fs2WN5e3s7t9dmLgDnx90tADSogICA897lIigoSJL0/vvvq7Kysk7H8PX1VUJCQq3HP/TQQ2revLnz+bBhw9S2bVt99NFHdTp+bX300Ufy8vLSY4895rL9iSeekGVZWrt2rcv22NhYXXPNNc7n3bt3l81m07///e8LHic0NFQjR450bmvSpIkee+wxnThxQlu2bLnotTscDkly+dzO59wz8mfPntX333+vTp06KSgoSLt27ao2/pFHHnG5NeCtt96qiooKff3115KkDRs26Pjx43rqqaeq/dFn1etycnJ04MABPfDAA/r+++917NgxHTt2TCdPntSdd96prVu3VvsZe/TRR2v1fhwOR63fu+T6/o8fP65jx47p1ltv1alTp5SbmytJzrO769at06lTp2qc57333lNlZaXuv/9+5/s5duyYQkND1blzZ23atKnWcwE4PyIZQIM6ceLEeeNi+PDhuvnmmzVu3DiFhIRoxIgRWr58+UUF81VXXXVRf6TXuXNnl+ceHh7q1KmTDh8+XOs56uLrr79WWFhYtc+ja9euzv3nateuXbU5WrRooR9//PGCx+ncubM8PV1/5f/ccWrDZrNJUq1v63f69GmlpaUpIiJCvr6+at26tYKDg1VcXKySkpJq48332qJFC0lyvteDBw9Kkm644YafPeaBAwckSfHx8QoODnZ5LF68WKWlpdWO3bFjx1q9H5vNdlG3NNy3b59+85vfKDAwUDabTcHBwfrtb38rSc41dOzYUcnJyVq8eLFat24tu92uBQsWuKzxwIEDsixLnTt3rvaevvjiCxUWFtZ6LgDnxzXJABrMN998o5KSEnXq1Olnx/j7+2vr1q3atGmT1qxZo4yMDC1btkx33HGH1q9fLy8vrwse52KuI66tn/vCk4qKilqtqT783HEsN9zJs+puDnv27FHPnj0vOH7ixIl6/fXXNWnSJMXExCgwMFAeHh4aMWJEjf8CVB/vtWreWbNm/ewaAwICXJ7X9menS5cuysnJUVlZ2QX/hay4uFi33XabbDabpk+frmuuuUZ+fn7atWuXUlJSXN7/7NmzNXr0aL3//vtav369HnvsMc2cOVOffvqpwsPDVVlZKQ8PD61du7bGz+jc93OhuQCcH5EMoMEsWbJEkmS32887ztPTU3feeafuvPNO/fGPf9QLL7ygp59+Wps2bVJsbGy9f0Nf1RnHKpZl6auvvnK5n3OLFi1q/HKIr7/+WldffbXz+cWsrX379vr73/+u48ePu5xNrvrP7+3bt6/1XBc6zueff67KykqXs8m/5DgDBw6Ul5eX3nrrrVr98d67776r+Ph4zZ4927ntzJkzdf7CjarLTvbu3fuz/9JVNcZmsyk2NrZOx/k599xzj7KysvS3v/3N5TKWmmzevFnff/+93nvvPfXr18+5/dChQzWO79atm7p166ZnnnlG27Zt080336xFixZpxowZuuaaa2RZljp27Khrr732gus831wAzo/LLQA0iI0bN+p//ud/1LFjR40aNepnx/3www/VtlWdBSwtLZUk571r6+sbzd58802X/3T+7rvv6rvvvtPAgQOd26655hp9+umnzi8kkaTVq1fryJEjLnNdzNruvvtuVVRUaP78+S7b58yZIw8PD5fj/xJ333238vPzXe4MUV5erldeeUUBAQG67bbbLnrOiIgIPfzww1q/fr1eeeWVavsrKys1e/ZsffPNN5J+OjNsngV+5ZVXVFFRcdHHlqQBAwaoefPmmjlzps6cOeOyr+o4UVFRuuaaa/SH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\n"},"metadata":{}},{"name":"stdout","text":"\nCancer Distribution:\ncancer\n0    0.978832\n1    0.021168\nName: proportion, dtype: float64\n","output_type":"stream"}],"execution_count":2},{"cell_type":"code","source":"# Fungsi untuk memuat dan memproses gambar DICOM\ndef load_dicom_image(path, img_size=256):\n    dicom = pydicom.dcmread(path)\n    img = dicom.pixel_array\n    \n    # Normalisasi\n    img = (img - img.min()) / (img.max() - img.min())\n    \n    # Jika gambar memiliki channel photometric interpretation 'MONOCHROME1', invert\n    if dicom.PhotometricInterpretation == \"MONOCHROME1\":\n        img = 1 - img\n    \n    # Ubah ke 3 channel (RGB) untuk kompatibilitas dengan model CNN\n    img = np.stack([img, img, img], axis=-1)\n    \n    # Resize gambar\n    img = tf.image.resize(img, [img_size, img_size])\n    \n    return img.numpy()\n\n# Fungsi untuk memuat gambar dari path\ndef load_images_from_df(df, folder_path, img_size=256, sample_size=None):\n    if sample_size is not None:\n        df = df.sample(sample_size, random_state=42)\n    \n    images = []\n    labels = []\n    \n    for _, row in tqdm(df.iterrows(), total=len(df)):\n        patient_id = row['patient_id']\n        image_id = row['image_id']\n        img_path = f\"{folder_path}/{patient_id}/{image_id}.dcm\"\n        \n        try:\n            img = load_dicom_image(img_path, img_size)\n            images.append(img)\n            labels.append(row['cancer'])\n        except:\n            continue\n    \n    return np.array(images), np.array(labels)\n\n# Karena dataset besar, kita akan mengambil sample untuk prototyping\nSAMPLE_SIZE = 5000  \nIMG_SIZE = 256\n\n# Memuat sample data\nfolder_path = '/kaggle/input/rsna-breast-cancer-detection/train_images'\nimages, labels = load_images_from_df(train_df, folder_path, IMG_SIZE, SAMPLE_SIZE)\n\n# Split data menjadi train dan validation set\nX_train, X_val, y_train, y_val = train_test_split(\n    images, labels, test_size=0.2, stratify=labels, random_state=42\n)\n\nprint(f\"Train Shape: {X_train.shape}, Val Shape: {X_val.shape}\")\nprint(f\"Positive Cases in Train: {y_train.sum()}, Val: {y_val.sum()}\")","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}