{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "69865783",
   "metadata": {},
   "source": [
    "# 第 05 章　簡單貝氏分類（Naive Bayesian Classification）\n",
    "\n",
    "本 notebook 搭配網站「醫學生的機器學習入門」第 05 章使用。可以直接在 Google Colab 執行（選單「執行階段 → 全部執行」），不需安裝額外套件。\n",
    "\n",
    "內容分三段：\n",
    "\n",
    "1. 用程式算一次貝氏定理：盛行率、敏感度、特異度 → 陽性預測值（PPV）\n",
    "2. `GaussianNB` 分類乳癌細胞核特徵（WDBC，sklearn 內建）\n",
    "3. `MultinomialNB` 把醫學論文摘要分成 5 個疾病大類（Medical Abstracts TC Corpus，需網路下載）\n",
    "\n",
    "> 圖上的文字一律用英文，因為 Colab 預設沒有中文字型。本例僅供學習，不構成臨床建議。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "297d03a3",
   "metadata": {},
   "source": [
    "先印出套件版本。本教材以 Colab 的 scikit-learn 1.6 為相容底線，新版也能執行。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "cb614f00",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-09-29T20:02:48.099378Z",
     "iopub.status.busy": "2026-09-29T20:02:48.099226Z",
     "iopub.status.idle": "2026-09-29T20:02:48.775031Z",
     "shell.execute_reply": "2026-09-29T20:02:48.774648Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "numpy 2.1.3 | pandas 2.2.3 | scikit-learn 1.6.1\n"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "import pandas as pd\n",
    "import matplotlib.pyplot as plt\n",
    "import sklearn\n",
    "\n",
    "print(\"numpy\", np.__version__, \"| pandas\", pd.__version__, \"| scikit-learn\", sklearn.__version__)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d206bfca",
   "metadata": {},
   "source": [
    "## 1. 貝氏定理＝檢驗前後機率\n",
    "\n",
    "先寫一個小函式：給盛行率、敏感度、特異度，回傳 PPV 與 NPV。用「每 10,000 人」的自然頻率來算，和你在流病課畫 2×2 表完全一樣。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "90243111",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-09-29T20:02:48.776312Z",
     "iopub.status.busy": "2026-09-29T20:02:48.776212Z",
     "iopub.status.idle": "2026-09-29T20:02:48.778596Z",
     "shell.execute_reply": "2026-09-29T20:02:48.778161Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "prevalence   0.1%  ->  PPV   1.8%   NPV  99.99%\n",
      "prevalence   1.0%  ->  PPV  15.4%   NPV  99.89%\n",
      "prevalence  10.0%  ->  PPV  66.7%   NPV  98.84%\n",
      "prevalence  30.0%  ->  PPV  88.5%   NPV  95.68%\n"
     ]
    }
   ],
   "source": [
    "def ppv_npv(prevalence, sensitivity, specificity, n=10_000):\n",
    "    diseased = prevalence * n\n",
    "    healthy = n - diseased\n",
    "    tp = sensitivity * diseased          # true positive\n",
    "    fn = diseased - tp                   # false negative\n",
    "    tn = specificity * healthy           # true negative\n",
    "    fp = healthy - tn                    # false positive\n",
    "    return tp / (tp + fp), tn / (tn + fn)\n",
    "\n",
    "for prev in [0.001, 0.01, 0.1, 0.3]:\n",
    "    ppv, npv = ppv_npv(prev, sensitivity=0.90, specificity=0.95)\n",
    "    print(f\"prevalence {prev:>6.1%}  ->  PPV {ppv:6.1%}   NPV {npv:7.2%}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7e1f72a0",
   "metadata": {},
   "source": [
    "同一支敏感度 90%、特異度 95% 的檢驗，盛行率 1% 時 PPV 只有約 15%，盛行率 30% 時卻接近 89%。檢驗本身沒變，變的是檢驗前機率。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9e67a773",
   "metadata": {},
   "source": [
    "換成勝算（odds）與概似比（likelihood ratio）的寫法：檢驗後勝算＝檢驗前勝算 × LR。連續做兩個檢驗時，**如果兩者在已知有無疾病下彼此獨立**，就可以一路乘下去——這正是 naive Bayes 的核心假設。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "6356db96",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-09-29T20:02:48.779653Z",
     "iopub.status.busy": "2026-09-29T20:02:48.779599Z",
     "iopub.status.idle": "2026-09-29T20:02:48.781565Z",
     "shell.execute_reply": "2026-09-29T20:02:48.781293Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "LR+ = 18.0\n",
      "after 1 positive test : 15.4%\n",
      "after 2 positive tests: 76.6%  (only valid if the tests are conditionally independent)\n"
     ]
    }
   ],
   "source": [
    "def to_odds(p):\n",
    "    return p / (1 - p)\n",
    "\n",
    "def to_prob(odds):\n",
    "    return odds / (1 + odds)\n",
    "\n",
    "sens, spec = 0.90, 0.95\n",
    "lr_pos = sens / (1 - spec)               # LR+ = 18\n",
    "pretest = 0.01\n",
    "\n",
    "post1 = to_prob(to_odds(pretest) * lr_pos)\n",
    "post2 = to_prob(to_odds(pretest) * lr_pos * lr_pos)   # a second, independent positive test\n",
    "print(f\"LR+ = {lr_pos:.1f}\")\n",
    "print(f\"after 1 positive test : {post1:.1%}\")\n",
    "print(f\"after 2 positive tests: {post2:.1%}  (only valid if the tests are conditionally independent)\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "55880b4c",
   "metadata": {},
   "source": [
    "第一次陽性之後機率從 1% 升到約 15.4%（和上面 PPV 相同），再一次獨立的陽性升到約 76.6%。若第二個檢驗其實和第一個高度相關（例如同一種原理的兩支試劑），這樣相乘就會高估。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d4cc35c1",
   "metadata": {},
   "source": [
    "## 2. GaussianNB：乳癌細胞核特徵\n",
    "\n",
    "WDBC 資料集的標籤 `0 = 惡性、1 = 良性`，和直覺相反。我們先把它翻成 `1 = 惡性`，再切出 25% 當測試集。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "e2abc8a3",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-09-29T20:02:48.782625Z",
     "iopub.status.busy": "2026-09-29T20:02:48.782557Z",
     "iopub.status.idle": "2026-09-29T20:02:48.867611Z",
     "shell.execute_reply": "2026-09-29T20:02:48.867205Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(426, 30) (143, 30) malignant rate: 0.373\n"
     ]
    }
   ],
   "source": [
    "from sklearn.datasets import load_breast_cancer\n",
    "from sklearn.model_selection import train_test_split\n",
    "\n",
    "X, y = load_breast_cancer(return_X_y=True, as_frame=True)\n",
    "y = (y == 0).astype(int)                 # flip: 1 = malignant, 0 = benign\n",
    "X_train, X_test, y_train, y_test = train_test_split(\n",
    "    X, y, test_size=0.25, stratify=y, random_state=42)\n",
    "print(X_train.shape, X_test.shape, \"malignant rate:\", round(y.mean(), 3))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "57a78185",
   "metadata": {},
   "source": [
    "訓練 `GaussianNB` 只要兩行，不需要標準化（每個特徵各自估平均與變異數，尺度不影響）。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "30c77cfb",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-09-29T20:02:48.868904Z",
     "iopub.status.busy": "2026-09-29T20:02:48.868818Z",
     "iopub.status.idle": "2026-09-29T20:02:48.877267Z",
     "shell.execute_reply": "2026-09-29T20:02:48.876809Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "accuracy: 0.944\n",
      "[[90  0]\n",
      " [ 8 45]]\n",
      "              precision    recall  f1-score   support\n",
      "\n",
      "      benign      0.918     1.000     0.957        90\n",
      "   malignant      1.000     0.849     0.918        53\n",
      "\n",
      "    accuracy                          0.944       143\n",
      "   macro avg      0.959     0.925     0.938       143\n",
      "weighted avg      0.949     0.944     0.943       143\n",
      "\n"
     ]
    }
   ],
   "source": [
    "from sklearn.naive_bayes import GaussianNB\n",
    "from sklearn.metrics import accuracy_score, confusion_matrix, classification_report\n",
    "\n",
    "nb = GaussianNB()\n",
    "nb.fit(X_train, y_train)\n",
    "y_pred = nb.predict(X_test)\n",
    "\n",
    "print(\"accuracy:\", round(accuracy_score(y_test, y_pred), 3))\n",
    "print(confusion_matrix(y_test, y_pred))          # rows: true 0/1, cols: predicted 0/1\n",
    "print(classification_report(y_test, y_pred, target_names=[\"benign\", \"malignant\"], digits=3))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "834704eb",
   "metadata": {},
   "source": [
    "混淆矩陣的第二列是真正惡性的 53 例：抓到 45 例、漏掉 8 例（敏感度約 0.85），良性則全部判對。對醫學應用來說，偽陰性比偽陽性更值得注意。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b3376db1",
   "metadata": {},
   "source": [
    "模型「學到」的東西其實就是每個類別、每個特徵的平均與變異數，可以直接印出來看。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "23c3e194",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-09-29T20:02:48.878326Z",
     "iopub.status.busy": "2026-09-29T20:02:48.878260Z",
     "iopub.status.idle": "2026-09-29T20:02:48.882525Z",
     "shell.execute_reply": "2026-09-29T20:02:48.882131Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "class prior: [0.627 0.373]\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>benign_mean</th>\n",
       "      <th>malignant_mean</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>mean radius</th>\n",
       "      <td>12.166</td>\n",
       "      <td>17.530</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>mean concave points</th>\n",
       "      <td>0.026</td>\n",
       "      <td>0.088</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>worst area</th>\n",
       "      <td>563.221</td>\n",
       "      <td>1446.654</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                     benign_mean  malignant_mean\n",
       "mean radius               12.166          17.530\n",
       "mean concave points        0.026           0.088\n",
       "worst area               563.221        1446.654"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "params = pd.DataFrame({\"benign_mean\": nb.theta_[0], \"malignant_mean\": nb.theta_[1]},\n",
    "                      index=X.columns)\n",
    "print(\"class prior:\", nb.class_prior_.round(3))\n",
    "params.loc[[\"mean radius\", \"mean concave points\", \"worst area\"]].round(3)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "761e7e4b",
   "metadata": {},
   "source": [
    "`class_prior_` 就是訓練集中良性與惡性的比例（先驗機率）；表格是兩類各自的特徵平均（`theta_`），搭配變異數（`var_`）就決定了每一條常態曲線。預測時，模型把 30 個特徵的常態機率密度相乘，再乘上先驗。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b333edd2",
   "metadata": {},
   "source": [
    "用 5 折交叉驗證和邏輯迴歸比一比，看看這個「天真」的模型差多少。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "b000d854",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-09-29T20:02:48.883490Z",
     "iopub.status.busy": "2026-09-29T20:02:48.883439Z",
     "iopub.status.idle": "2026-09-29T20:02:48.942410Z",
     "shell.execute_reply": "2026-09-29T20:02:48.942067Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "GaussianNB           accuracy 0.939 (+/- 0.023)\n",
      "LogisticRegression   accuracy 0.974 (+/- 0.017)\n"
     ]
    }
   ],
   "source": [
    "from sklearn.model_selection import cross_val_score, StratifiedKFold\n",
    "from sklearn.pipeline import make_pipeline\n",
    "from sklearn.preprocessing import StandardScaler\n",
    "from sklearn.linear_model import LogisticRegression\n",
    "\n",
    "cv = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)\n",
    "models = {\n",
    "    \"GaussianNB\": GaussianNB(),\n",
    "    \"LogisticRegression\": make_pipeline(StandardScaler(), LogisticRegression(max_iter=1000)),\n",
    "}\n",
    "for name, model in models.items():\n",
    "    scores = cross_val_score(model, X, y, cv=cv)\n",
    "    print(f\"{name:20s} accuracy {scores.mean():.3f} (+/- {scores.std():.3f})\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5cba8a01",
   "metadata": {},
   "source": [
    "GaussianNB 大約 0.94，邏輯迴歸約 0.97～0.98。NB 不是最強，但幾乎不用調參數、訓練一瞬間，很適合當基準線（baseline）。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "21441388",
   "metadata": {},
   "source": [
    "### 機率輸出不要當真\n",
    "\n",
    "WDBC 有很多高度相關的特徵（半徑、周長、面積幾乎是同一件事），違反條件獨立假設，於是同一份證據被重複相乘，機率被推到極端。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "7757424e",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-09-29T20:02:48.943576Z",
     "iopub.status.busy": "2026-09-29T20:02:48.943491Z",
     "iopub.status.idle": "2026-09-29T20:02:48.985395Z",
     "shell.execute_reply": "2026-09-29T20:02:48.985026Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "corr(mean radius, mean perimeter) = 0.998\n",
      "share of predictions < 1% or > 99%: 0.958\n",
      "misclassified cases: 8\n",
      "their predicted P(malignant): [0.     0.     0.0022 0.0026 0.0032 0.0156 0.1963 0.2041]\n"
     ]
    },
    {
     "data": {
      "image/png": "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Yueee677zgjIQ560Y8cO3SZ5HTt2POS1P//80/vf//4XeuzatSv0Wvj/fdOmTXPb+uyzz0LLunXr5tWsWfOQdYcOHerW9Y0ZM8Y91+ek59JLL/VOPPHEDL/P5MmT3XbWrVuXYVpvvvlmr3jx4t6ePXtCy9q2beve+9JLL4WW7d2716tcubJ3+eWXh5Zp21rv3//+t3fgwAGvbt26XuPGjb2DBw9GfLfw76J80LLoR7Vq1byvv/46w+8U/pnFihXzfvvtt9DyRYsWueV9+/Y95LMGDhwYsY23337bLR8xYkTE8iuuuMLLly+ft3r16tAyP31fffVVaNkvv/ziFS1a1OvUqVOGebtw4cJD8tHfL82aNfP27dsXWj5q1Ci3/J133onYD3pEf3dtI73jR0qUKOG+++GOib/++ssrW7as16NHj4j1Nm7c6JUpUya0XMe/v5/j5e+DPn36hJbp+Ljwwgu9woULRxwbWk/fJ2h60xMrr2J9jui3qmVvvPFGxDmiSpUqXtOmTQ/7vaOPB+3rk046yWvXrl2m9lUsvXv39goUKBDztaOPPtrr3LlzXGk63DHavn370G9Z9NvS52/fvt0937x5s9uH2pfh6917773u/Zn9Xj6d08KP91RHeU0epbtz0R17NEXuKurzH+PGjQu9puJCn+6QdcetOzBRlB4v3a36VRKqC01vnd9++83dacQjPK26q1daVVysu7sffvghYl3lQ/hdjurvdQelUoRY/NKJZcuWHbZBmYqMdVerh0oE1KhMn6c7mx9//DFT36Vjx46u6sWntKlESY1ko916660Rz7WO0quShnCq9tA1TcXo4dTITXd/vho1argifqXdryIKz9v9+/e74miVcmlfxToOdCdaqFChiDSqiidW+rOL8n/79u12zTXXuGPBfyhvlJcqufG/m/a/Sk2iq2IyK7x7rd/dVnevs2bNSnh6E0XVMSra9/nVUSoBULVPRsKPB+XZjh073G8tK+eE8DYT6bWj0W8quiFuRmnK7DEaXkqm9Ot49xuga99pH6oEI3y9O++8M0vfD5EIJvIo1b3K33//fchrutjpRPbf//73kNe2bdvmqhpUtK4fq4KN2rVru9d0AomXilVbt27tij+1TRVJvvrqqxGBhaoEdPHVBVRdqlTUH14Nkh4VU+vkWKZMGXdiVFr9gCE6rSoGjS5uV5FnRhcTFenq5HS4thM6+aunjB4qEtVJSycmpWHQoEGWGfre0dRuI7r+VxdofZdwOhnqQuHvc5+62/mvZ+azFIT5dcg6kavI12+DcdRRR7n81cUv1nEQvU3tT7VDOJJjKqgYX1Q9FB4s66G2AqrKEH0fVSkoyNIx2aZNG1ddcbgLqk9F8GpTFJ1/Es/3zWx6E0XHcvRvILPpVnWGbip0kS9fvrxLo6oUsnJO8On8kl71gW5kwoOFWOI9RhU0h/Mbd/rnAP93En0sa5t5rSFobkSbiTxKF1idzKMb8YnfhiLWCUTtCVQPqfp21b3roqALv+qIwwOA9OrBoxs/6oSgxn26y1KDKtXPqo5SJ1CdMHUh1kVP9ew6Yel1jfGgenydKIYNGxbzc3TCUCNFBRG62KtuVic63ZEoOIkuBUmv1f/hggSVTqgRmUpW4qELvhqGRTdsDEonzSPRwEt3Z6pT112ZSjJ0PGmfKxhMr4Qpp/npUt293wA2XHhjWH2viy++2JU6qUTm/vvvt4cffti1u2natGmuS28smf0NBvX555+79hIKuvS71HlFpVA6PsIbScdL21FaFTRVrFgxtFwBhkoZFCAn8hjNyjkAiUMwkYepYZTGPVDDOt31H44idHUh1QVcF/LoO6hwitR1QY8Wa8wKXfzOPvts9xg9erTri64uYQowdDcval2tUgw9dDJRo8eHHnrI3dnH6mKnImqdcNQaXSe58AG6EkklHWqQpTzRCTUeapAXq2Qollh5rCqSzDTAUw8QlYSoqie8dMKv6okehyG9z1KDNd2FiRqoqpHe448/HnG3GGuf+9tUy3efvveGDRtcVU9QmW3A6Tf204XJP64Ot76qgvRQ+hU86/vGKrELpwuVqsf8u3rxq7PiaTAZb3qj+XfL2id+daKkN26MGj7rwhmen5lJt4J7/QYVdCmY9elCHi2exrbKb9HoqeHHiZ4rj/3X0xPvMXo4/u9Ex0J4yZNK67JaHYb/QzVHHnbPPfe4C4S6dm7atOmwEbkfuUcvV6vnWCdCFSWGj6Cpi4d6P0RXm0TzTxJ79+51f6O7naoeVd3WlA7VhcYSK60KQnTnlEh+6YTGnXj33Xcz/T6dpFXa0rhx40ytrztk9bzwKQBUb5boniax6ESsO7ynn346Yrl6cejkHr2NhQsXRtQpr1+/3pW8qIrGz1f9jT4O1H03vbte9fgJ31cqAlcwlZn0H44CzcxcINQjQiVVClZjHTd+FY6qc3TRiT6eFYj5x+ThhOe18knPdbeugDmzMpvewwUj4aVfftfMWDSAWvjvU+2q1ItIv8dYJSM+HQs6jsL3vUo1Y7Ulyuy+EpVOqspEx0o4Pdd5y+8lklG64jlGD0cBnfahthG+3VjnP8SPkok8THV/KoZUAy8VuasNgC5u+qHoDl6vqdTAr4PXic2vP9bJTQ0CVRUR625fRYmqTlCbBTX887u06W4t/EKlKgid7HRiUOSvIk1d8PWZ6v4muojpZKa2FarDXrlypTs56z3R7QB86vOuOzPdmejzdbJTcXF2FFkq3zR+hQKKWHTR9O9mdUelE+2ECRPc/9UNLbP12coPNVzUBU0nMHUtVUB4OCquV6mASnv02drH2m8KEFQEHN09T90/dSEL7xoq4VVK6tKq/FTRsQI7BSAq/VCaYlEgpwupqskURGmb+j7xlubEosai+myVaqnoW214YnV31vGrY1AjY5588snuGFVJi7p7qopNx5eOKwV6flr13VSdoIusAm6953B0l67qOB17SofaXmj7GjvFL9nJjMymNz363agdgLoDq1pSF9cXXnghtI1o+m1qXTV01u9M6+o7xyphCKffofJeVZ3qqq3fsBpt65iNHo4/s/vKrwLV70ptpNTNVMekqlT0W1KppAKNjMR7jB6O8u3uu+921V3atoJ0NU7V/lV7jMzQuc4P7hQMKrhTyabo3Bpeippycro7CYJT18Bbb73VO+6441wXQHVDrF+/vnfLLbd433zzTcS66p6oLoLqsqbuaVdeeaX3xx9/HNLNTT766CPXPUzdqY4//njvv//97yHd1WbPnu26flatWtWtp7/XXHON9+OPP4bWefbZZ702bdp4FSpU8IoUKeLVqVPH69+/v+u6llF3t/nz53unnXaa+z7a7j333ON9+OGHbr05c+aE1lP3rFhdT6O7t4Z3DY3mf35muoaWLl3aO/vss71Zs2Yddt+Ef+bjjz/uVa9e3eXBGWec4S1btuyQ9KrrXSzqZqiubsqHQoUKuW6t2mZ4FzfRZ6lLnvaV1tFnqWtgeH753SdvuOEG76ijjvJKlizpdejQwfvhhx9cfoV3kfPzZe7cuV7Pnj29cuXKufW7dOnibd26NWKbWe0aqs/V8aH9HN5FL9YxIfouSq+OXx3vOp6uv/76UHfYLVu2uDzQb0D5qfVatGjhvfrqq4fZW/+3D9asWeOde+65rhtypUqVXLrT0tIOyeuMuoZmNr0ZUfdjpV2/rRo1anijR49Ot2uoujzq99GoUSO33/X9X3vtNS8zJk2aFDpe9D59Rjz7KiMTJ0505w99B313dSePPm5jifcY/fLLLw/J9+hzhfbhsGHDXJdZfYczzzzTW7FixSHbTI+fJ7EeQ6POn6kmn/7J6YAGSFYqSdDdmwbZ0l0Rcjc1xlVdfWbbwuQWahOhEik1cgZyAm0mAABAIAQTAAAgEIIJAAAQCG0mAABAIJRMAACAQAgmAABAIEk/aJUGFtLIcBocKZ6hYAEASHWe57mh/DVIWUbzBiV9MKFAQrPOAQCArNGw/NEzGqdUMOEP16yM0PC2AAAgczTHi27I05v6IGWCCb9qQ4EEwQQAAPE7XDMBGmACAIBACCYAAEAgBBMAACAQggkAABAIwQQAAAiEYAIAAARCMAEAAAIhmAAAAIEQTAAAgEAIJgAAQCAEE1mUdvBgntgmAADZLenn5sguBfLnty4zXrOVWzcnZHsNKlS0qRddmZBtAQBwJBFMBKBAYummDYnbGwAA5EFUcwAAgEAIJgAAQCAEEwAAIBCCCQAAEAjBBAAACIRgAgAABEIwAQAAAiGYAAAAgRBMAACAQAgmAABAIAQTAAAgEIIJAAAQCMEEAAAIhGACAAAEQjABAAACIZgAAACBEEwAAIBACCYAAEAgBBMAACAQggkAABAIwQQAAAiEYAIAAARCMAEAAAIhmAAAAIEQTAAAgEAIJgAAQCAEEwAAIBCCCQAAEAjBBAAACIRgAgAABEIwAQAAAiGYAAAAgRBMAACAvBtMpKWl2f3332+1a9e2YsWKWZ06dezBBx80z/NC6+j/Q4YMsSpVqrh12rdvbz/99FNOJhsAAOSWYOLRRx+18ePH29NPP20rV650z0eNGmVPPfVUaB09f/LJJ23ChAm2aNEiK1GihHXo0MH27NmTk0kHAAD/v4KWgxYsWGCXXnqpXXjhhe55rVq1bNq0abZ48eJQqcTYsWNt8ODBbj156aWXrFKlSvb2229b586dczL5AAAgp0smWrVqZbNnz7Yff/zRPV+2bJnNmzfPzj//fPd83bp1tnHjRle14StTpoy1aNHCFi5cmGPpBgAAuaRkYuDAgbZz506rX7++FShQwLWheOihh6xLly7udQUSopKIcHruvxZt79697uHT9gEAQJKWTLz66qs2depUe/nll23JkiU2ZcoUe+yxx9zfrHr44Ydd6YX/qF69ekLTDAAAclEw0b9/f1c6obYPDRs2tK5du1rfvn1dQCCVK1d2fzdt2hTxPj33X4s2aNAg27FjR+ixfv36I/BNAABIXTkaTOzatcvy549Mgqo7Dh486P6vLqMKGtSuIrzaQr06WrZsGXObRYoUsdKlS0c8AABAkraZuPjii10biRo1atiJJ55oS5cutdGjR9uNN97oXs+XL5/deeedNmLECKtbt64LLjQuRdWqVa1jx445mXQAAJDVYOKDDz6wkiVL2umnn+6ejxs3zp577jk74YQT3P/LlSuX6W1pPAkFB7169bLNmze7IOHmm292g1T57rnnHvvnn3+sZ8+etn37dve5SkPRokXjTToAAMgG+bzw4SYzQW0bNLjUBRdcYMuXL7dTTjnF+vXrZ3PmzHG9MiZPnmy5iapF1BBT7ScSXeVx8pRxtnTThoRsq2mlKrakW++EbAsAgCN5DY27ZEJjP6gUQt544w276KKLbOTIka43hgIMAACQWuJugFm4cGHXcFJmzZpl5557rvt/+fLlGdMBAIAUFHfJROvWrV21hv5q2OtXXnnFLdcolsccc0x2pBEAACRTyYQaWRYqVMhef/11N0lXtWrV3PL333/fzjvvvOxIIwAASJaSiQMHDtinn37qem9EDxo1ZsyYRKcNAAAkW8lEwYIF7ZZbbomY+wIAAKS2uKs5Tj31VDe4FAAAQJYaYGqAqbvuust+++03a9asmZUoUSLi9UaNGpGzAACkkLiDCU3KJbfffntomYa91thX+qtpxAEAQOrI0qBVAAAAWQ4matasGe9bAABAEsvSrKFr1qyxsWPH2sqVK91zDa99xx13WJ06dRKdPgAAkGy9OT788EMXPGj0SzW21GPRokVuCvGPP/44e1IJAACSp2Ri4MCB1rdvX3vkkUcOWT5gwAA755xzEpk+AACQbCUTqtro3r37IctvvPFG+/777xOVLgAAkKzBxNFHH23ffPPNIcu1rGLFiolKFwAASNZqjh49eljPnj1t7dq11qpVK7ds/vz59uijj7rZRAEAQGqJO5i4//77rVSpUvb444/boEGD3LKqVava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AAIhmEjHuHHjrFatWla0aFFr0aKFLV68OMOMfO2116x+/fpu/YYNG9rMmTOD7ZkUz9PnnnvOzjjjDCtXrpx7aHK3w+2DVBPvMeqbPn26Gw3WHwgOWc/T7du3W+/eva1KlSquBX29evX47QfIT40jdPzxx1uxYsXcSI59+/a1PXv2cIia2WeffWYXX3yxG4lSv9+33377sPny6aef2sknn+yOzeOOO85efPHF7MvLRM6lkSymT5/uFS5c2HvhhRe87777zuvRo4dXtmxZb9OmTTHXnz9/vlegQAFv1KhR3vfff+8NHjzYK1SokLd8+fIjnvZkydNrr73WGzdunLd06VJv5cqV3vXXX++VKVPG++2334542pMhP33r1q3zqlWr5p1xxhnepZdeesTSm4x5unfvXq958+beBRdc4M2bN8/l7aeffup98803RzztyZCfU6dO9YoUKeL+Ki8//PBDr0qVKl7fvn2PeNpzo5kzZ3r33Xef9+abb7q5Mt56660M11+7dq1XvHhxr1+/fu669NRTT7nr1AcffJAt6SOYiEGTiPXu3Tv0PC0tzatatar38MMPx8zEq666yrvwwgsjlrVo0cK7+eabE72/UiZPox04cMArVaqUN2XKlGxMZXLnp/KwVatW3vPPP+9169aNYCJgno4fP9479thjvX379gXfoUko3vzUuu3atYtYpgth69atsz2teY1lIpi45557vBNPPDFi2dVXX+116NAhW9JENUeUffv22ddff+2K1X358+d3zxcuXBizdEfLw9eXDh06pLt+qslKnkbbtWuX7d+/38qXL2+pLqv5OXz4cKtYsaJ17979CKU0ufP03XfftZYtW7pqDo3Ie9JJJ9nIkSMtLS3NUl1W8rNVq1buPX5VyNq1a12V0QUXXHDE0p1MFh7h61KeGAHzSNqyZYs7GUQP163nP/zwQ8z3aJjvWOtrObKWp9EGDBjg6gqjfxypKCv5OW/ePJs0aZJ98803RyiVyZ+nuth98skn1qVLF3fRW716tfXq1csFvRqFMJVlJT+vvfZa977TTz/dzVR54MABu+WWW+zee+89QqlOLhvTuS5pZtHdu3e7dimJRMkEcr1HHnnENRp86623XEMuxEfTB3ft2tU1aj3qqKPIvgTRDMYq6Zk4caKb3VjzCN133302YcIE8jgL1FhQJTvPPPOMLVmy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",
      "text/plain": [
       "<Figure size 600x350 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "proba = nb.predict_proba(X_test)[:, 1]          # predicted probability of malignant\n",
    "print(\"corr(mean radius, mean perimeter) =\", round(X[\"mean radius\"].corr(X[\"mean perimeter\"]), 3))\n",
    "print(\"share of predictions < 1% or > 99%:\", round(np.mean((proba < 0.01) | (proba > 0.99)), 3))\n",
    "\n",
    "wrong = y_pred != y_test.to_numpy()\n",
    "print(\"misclassified cases:\", wrong.sum())\n",
    "print(\"their predicted P(malignant):\", np.sort(proba[wrong]).round(4))\n",
    "\n",
    "fig, ax = plt.subplots(figsize=(6, 3.5))\n",
    "ax.hist(proba, bins=20, range=(0, 1), color=\"#00897B\", edgecolor=\"white\")\n",
    "ax.set_xlabel(\"predicted P(malignant)\")\n",
    "ax.set_ylabel(\"number of test tumors\")\n",
    "ax.set_title(\"GaussianNB probabilities pile up at 0 and 1\")\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "97e78742",
   "metadata": {},
   "source": [
    "超過九成的預測落在 <1% 或 >99%；而被判錯的 8 例中，有 5 例模型給的惡性機率不到 1%。分類結果可以參考，但 `predict_proba` 的數字不能當成「這顆腫瘤的惡性風險」。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5f61a1b7",
   "metadata": {},
   "source": [
    "## 3. MultinomialNB：醫學摘要文字分類\n",
    "\n",
    "資料來自 Medical Abstracts TC Corpus（sebischair，GitHub），約 1.4 萬篇醫學摘要，標為 5 個疾病大類。需要網路下載（約 10 秒）。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "be16effe",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-09-29T20:02:48.986566Z",
     "iopub.status.busy": "2026-09-29T20:02:48.986500Z",
     "iopub.status.idle": "2026-09-29T20:02:58.398943Z",
     "shell.execute_reply": "2026-09-29T20:02:58.398313Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(11550, 2) (2888, 2)\n",
      "condition_label\n",
      "general           3844\n",
      "neoplasms         2530\n",
      "cardiovascular    2441\n",
      "nervous           1540\n",
      "digestive         1195\n",
      "Name: count, dtype: int64\n",
      "Tissue changes around loose prostheses. A canine model to investigate the effects of an antiinflammatory agent. The aseptically loosened prosthesis provided a means for investigating the in vivo and in vitro activity of the cells associated with the loosening process in seven dogs. The cells were is ...\n"
     ]
    }
   ],
   "source": [
    "base = \"https://raw.githubusercontent.com/sebischair/Medical-Abstracts-TC-Corpus/main/\"\n",
    "try:\n",
    "    train_df = pd.read_csv(base + \"medical_tc_train.csv\")\n",
    "    test_df = pd.read_csv(base + \"medical_tc_test.csv\")\n",
    "except Exception as e:\n",
    "    raise RuntimeError(\n",
    "        \"下載 Medical Abstracts 失敗，請確認網路連線，或稍後再執行此格。原始錯誤：\" + str(e))\n",
    "\n",
    "label_names = {1: \"neoplasms\", 2: \"digestive\", 3: \"nervous\", 4: \"cardiovascular\", 5: \"general\"}\n",
    "print(train_df.shape, test_df.shape)\n",
    "print(train_df[\"condition_label\"].map(label_names).value_counts())\n",
    "print(train_df[\"medical_abstract\"].iloc[0][:300], \"...\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "84f7b826",
   "metadata": {},
   "source": [
    "先用三句玩具句子看看詞袋模型（bag-of-words）在做什麼：每個字變成一欄，數它出現幾次，**字的順序被丟掉**。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "dba22c38",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-09-29T20:02:58.400744Z",
     "iopub.status.busy": "2026-09-29T20:02:58.400636Z",
     "iopub.status.idle": "2026-09-29T20:02:58.406180Z",
     "shell.execute_reply": "2026-09-29T20:02:58.405737Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>and</th>\n",
       "      <th>biopsy</th>\n",
       "      <th>carcinoma</th>\n",
       "      <th>chest</th>\n",
       "      <th>dyspnea</th>\n",
       "      <th>pain</th>\n",
       "      <th>shows</th>\n",
       "      <th>tumor</th>\n",
       "      <th>with</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>doc1</th>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>doc2</th>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>doc3</th>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "      and  biopsy  carcinoma  chest  dyspnea  pain  shows  tumor  with\n",
       "doc1    1       0          0      1        1     1      0      0     0\n",
       "doc2    0       1          1      0        0     0      1      1     0\n",
       "doc3    0       0          0      1        0     1      0      1     1"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from sklearn.feature_extraction.text import CountVectorizer\n",
    "\n",
    "toy = [\"chest pain and dyspnea\",\n",
    "       \"tumor biopsy shows carcinoma\",\n",
    "       \"chest tumor with pain\"]\n",
    "vec = CountVectorizer()\n",
    "counts = vec.fit_transform(toy)\n",
    "pd.DataFrame(counts.toarray(), columns=vec.get_feature_names_out(), index=[\"doc1\", \"doc2\", \"doc3\"])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "aea47590",
   "metadata": {},
   "source": [
    "接著把「詞袋 → MultinomialNB」串成 Pipeline，在真正的摘要上訓練。`stop_words=\"english\"` 移除 the、and 等虛詞，`min_df=2` 忽略只出現一次的字。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "7750ab0f",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-09-29T20:02:58.407855Z",
     "iopub.status.busy": "2026-09-29T20:02:58.407732Z",
     "iopub.status.idle": "2026-09-29T20:02:58.971727Z",
     "shell.execute_reply": "2026-09-29T20:02:58.971255Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "test accuracy: 0.587\n"
     ]
    },
    {
     "data": {
      "image/png": "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C1fizt37iB4tilnOYYyudQptPquN+b+uwffj5uLx4yeIFycmGtWtjGyZPbdv9F1Ys3szzl29iIZlawT1png09qV3nzwUF/6+bC52nIisZ8OvEDZM2KDeNI8UNkwYzOo5An2mfI96fdri/sMHJmD44cueZqI3TxbK4Y15xEBgOr5FixbmAs6LMUclLF269KUzKXKYY5MmTUzmIFWqVCYYqFSpkmnJs66ALl++bIYhLlu2zAQRHGrIIsjBgwfj4cOHaN68uclaXL9+3dQeMODo0aOHCUxYJ8CLOy/mt27dMt0RrFkIaCbF5cuXo2LFiihatKgZieGKgQhHT0ybNg0XLlxAnDhxTIaChYhWV8SrsAaBIyhOXz2JaNHc6ynE3YKT7hMXScDqpnuR5ZKX06k6cO4/u6uP0WvcvXMXqeKnM4Xxr8poK0B4RzZt2mTmRWBhojUqISRQgBB4ChACRwFC4ChACBwFCG8vQFAXw1vCVjy7JjiXAIOCNm3amImOQlJwICIi3kMBwlvCLgN2H3COAabtOUzR/+yLIiIiwYUChLeEhX+uIwZERESCM92LQURERGwUIIiIiIiNAgQRERGxUYAgIiIiNgoQRERExEYBgoiIiNgoQBAREREbBQgiIiJiowBBREREbBQgiIiIiI0CBBEREbFRgCAiIiI2ChBERETERgGCiIiI2ChAEBERERsFCCIiImKjAEFERERsFCCIiIiIjQIEERERsVGAICIiIjYKEERERMRGAYKIiIjYKEAQERERGwUIIiIiYqMAQURERGwUIIiIiIiNAgQRERGxCWNfJPJ6oUOFQuhQii9fpU7a+vooBUKHjd20nwKhX8Gu2k+B8MzxTPvpLe0jneFFRETERgGCiIiI2ChAEBERERsFCCIiImKjAEFERET+2SiGxYsXI7AqV64c6HVFREQkGAcIVatWDdSbhQoVCr6+vv92m0RERCQ4BAh+fn7vfktEREQkZNQgPHr06O1tiYiIiATfAIFdCH369EHixIkRJUoUnDx50izv1q0bJk6c+C62UURERDw9QOjXrx+mTJmCgQMHIly4cM7lWbJkwYQJE9729omIiEhwCBCmTZuGcePGoW7duvDx8XEuz549Ow4fPvy2t09ERESCQ4Bw4cIFpEmTJsBCxqdPn76t7RIREZHgFCBkypQJGzZssC2fN28ecubM+ba2S0RERILT7Z67d++Ohg0bmkwCswYLFizAkSNHTNfDkiVL3s1WioiIiGdnEKpUqYJff/0Vq1atQuTIkU3AcOjQIbOsTJky72YrRURExLMzCPTee+9h5cqVb39rREREJPgGCLRjxw6TObDqEnLnzv02t0tERESCU4Bw/vx51K5dG5s2bUKMGDHMslu3bqFQoUKYPXs2kiRJ8i62U0RERDy5BqFJkyZmOCOzBzdu3DBf/JkFi3xOREREvDCD8Mcff2Dz5s1Inz69cxl//v77701tgoiIiHhhBiFp0qQBTojEezQkSpTobW2XiIiIBKcAYdCgQfjiiy9MkaKFP7dp0waDBw9+29snIiIintrFEDNmTIQKFcr5+P79+8ifPz/ChHn+8mfPnpmfGzVqhKpVq767rRURERHPCRCGDx/+7rdEREREgleAwKmVRURExHv844mS6NGjR3jy5InbsmjRov3bbRIREZHgVqTI+oNWrVohXrx45l4MrE9w/RIREREvDBA6duyINWvWYPTo0QgfPjwmTJiAXr16mSGOvKOjiIiIeGEXA+/ayECgePHi+PTTT83kSGnSpEHy5MkxY8YM1K1b991sqYiIiHhuBoFTK6dKlcpZb8DHVKRIEaxfv/7tb6GIiIh4fgaBwcGpU6eQLFkyZMiQAXPnzkW+fPlMZsG6eZPI2zZ07gT8unk1jp0/hQjhwiNfxhzo9emXSJskpXOdU5fOoevEIdh6YDeePH2CUrkLY2DzzogXM7ZX/4fcfXAPvaeNwOItq3Dt1nVkT50Jgz77BnnSZ4M3KJGkKLLGzoi4EePimd9TnL57DstO/45rD/92Wy951KQon7w0kkVNAj+HHy7ev4zxB6bimd8z83zJJMWQMVY6JIqcAL4OX3Tf+i1CuiHmuFv1/+MuAvJnzI5en37lPO7OXLmAbI3KB/jaKZ0Go9p75eANBs8cjyGzJ7otS504OTaOnmN+Pn3pPHpN/h7bD+4156YSuQqiX7O2iOvh56Y3DhDYrbB3714UK1YMnTp1QqVKlfDDDz+Y6ZeHDh36brZSvN6m/TvQ5P1ayJUuM575+qLP1JGo1rU5to1ZiMgRIuH+oweo1vUzZEmZHov7jzf7q9/0H1Gr9xdYNeQnhA79xsmyEKPliK44ePoYJrYfiISx42HWmsX44JtPsXPsMiSOEx8hXeroKbD50nacu3cBoUOFRoXkpdE0c0MM2jUST/2eOoODxpkbYO359Vh0cqkJEBJGTgCHw+F8nzChfbDv779w5u455IufC95y3DU1x10Wc9z1njrCHGfbxiwyx12SOAlwdPpat9dMWfEzRi6YgjJ5vOvePOmTpcLcPt87H/v4+JjvDx49RK0ebZApRRrM6/uDWfbdjHFo0LcDlg6a4NHnpjcOEL766ivnz6VLl8bhw4exc+dOU4eQLZt3tEjeNg4VDRcuXFBvhkeb32eM2+NRbfsgTZ3i2HP8IApnyYNtB/fg7NWLWP/9XESLFMWsM7ptX6T4uAjW792O4jkLwBs9fPwIizb+jrk9RqFI1rxmWdd6X2DZtrUYv3QmejZ8cTyHVBMOuBdPzzm6AD0LdEaSKIlw6s4Zs6xSygrYdHEr1p7f4FzPf4bh97NrzPc88XLCWyzwd9zxmEpdp5jzuONFMH6sOG7r/LplDaoWKYcoESPBm4Tx8QkwW7n90D6cu3oJK4dPQ9RIkc2ykV92R4Y6ZbBx3w4UzZEPnupfhy4sTqxevbpXBQcs0GzdurUZ0RErViwkSJAAPXv2dD5/69Ytc+vruHHjmjqNkiVLmqyLhevmyJHDjABJmTIlIkSIgHHjxpmRILxttqsqVaqYKawtHD2SOnVqE1DwLprTp093Pnf69GkzJfaePXvctoXL1q1bZx7fvHnTFJJy2yJGjIi0adNi8uTJCG7u3L9nvseMEt18f/z0CUIhFMKHfRFosSuCLcYtB3fBWz3zfQZfP19ECBvebXnEcOGx5YB37pcIYSKY7w+ePTTfI4eNjOTRkuLe03v4PFtTdM/3NZpnbYQU0ZIF8ZZ6ntv+jjv/dh87gP0nD6NB2erwNicvnkOOTz5A/qbV0XJId5y/dtksf/L/c1O4sGGd64YPF86cm9jl4MkClUEYOXJkoN+QF05vMHXqVLRt2xbbtm3Dli1b8Mknn6Bw4cIoU6YMatasaS6+y5cvR/To0TF27FiUKlUKR48eNQEFHT9+HPPnz8eCBQtMFM67ZPImWGvXrjXrEgtAV6xYgWXLlpnHCxcuNDfF4tTXzN4sWbLEdPkkSZIEJUqUCNR2d+vWDQcPHjTbFidOHLMdDx8+P1EG5PHjx+bLcufOHQQ1BlGdxw1EgUw5kSlFWrMsb4ZsiBwhInpMHobuDVrDAQd6Th5hLo5Xbri3BL1J1EhRkD9jTgyYNcqkQOPHiIO5fyzBtsN7kDqh910AeaKunKoiTt0+gysPrpplsSM8n7+lTLKSWHJqhak9yB0vBz7L8imG7Poefz96Xojt7Z4fd9+5HXf+Tf99IdInTYX8mXLAm+RMnxkj2nRD6sTJcOXmdQydPRFVOzXHuu9nIFf6LIgUIQL6TvkRnRu0ABwO9Jv64/Nz083rCPYBwrBhwwL1ZmypekuAwIxJjx49zM9shbMOY/Xq1SYw2L59O65evWrmiSDe5XLRokWYN28emjVr5uxW4HBRtuQtFSpUwMyZM50BAtfnRdy6+PN9GIi0bNnSPGaAsnXrVrM8sAHC2bNnkTNnTuTJk8c8TpEixSvX79+/v5nnwpO0H90PB88cx4pBU5zL4kSPhSmdB6Ptj30xdvFME51/WKwCsqfOiNChX9xozBux9qD5sG+Qpl5R+IT2QY40mfBRsfex+/gBeJtqqT9AgkjxMGrfBLeggbZe/hM7ru42P188dQlpY6RC3vi5sfzMyiDbXk/SbnQ/HDLH3dSXdmfN+2MZOtT6DN6mVO5Czp8zpUxraqXyNqmKxRtXo07Zyhj39bfoNHogJi6Za85NVYuWQdbU6RHa5SaIwTZA4KgFcee/SyVhwoQmKGBXwr179xA7tntfFFvpJ06ccOuacQ0OiKn/pk2bYtSoUSa44LwStWrVchaxHDp0yBlgWJi1GDFiRKD/e1q0aIEPP/wQu3btQtmyZc3dNwsVevHh9q9z584mEHHNIDDbEVQ6jP4Wv21fj6XfTUbiOAncniuZqxD2TFyG67dvmqxMjCjRkK5uCaRIkATeLFWiZPh90E+mkPPOg3tIGCse6vf/EikSBN3/Y1Comup9ZIyV3gQHt5+8yITdeXLXfL/64Jrb+lceXEOM8AGn0r0Ng/Lftv+BZd9NsR13ll82rcSDxw9Ru1QleLvoUaKa4+7UpfPmcfGc+bF13Hxcv3PLFLvy+WwNKiL5e4kRYu/F4M3CuvQnWdkTpuAYHDBYsPr8XbkOA+U01f5xRAirppcuXYq8efNiw4YNgc7ekBVIuFZec3SJK2Ypzpw5Y7otVq5cabIVn3/+uclCBISBipUJCUr8mzqO6Y8lW9ZgSf+Jr7zox47+PGX8x95tuHb7BirkL/4fbqnnYtU5v27evY1VOzeib6MO8KbgIEvsTBizfyJuPr7l9hwf3358B3Ejuhfb8fHhm0fhzXjcdRjzrTnulvaf9MrjbvrvC1AhfwmTzfN29x8+wJnLF1CjhPsQ0NjRnl8DNu7dgb9v30TZfJ490kMBwluWK1cuXL58GWHChHlt+t4/Fiuy4JOZA9YGsAiR72fJmDEjNm3a5HZ3TT7OlCmT+dnKSFy6dMl0I5BrwaKF6/E9+MWZMDt06PDSAMFTtB/VDz//sRwzu41AlIiRnXUF0SJHQcTwz4vOflq5COmTpjQnqO2H9qLTuO/Qsmp9t7kSvNHKnRvMiT5dkpQ4cfEsvpk4EOmSpPKaQjJ2K+SMmw1TDs7EY98niBr2+SiXh76PnHMcrLuwEWWTlTT1BxfvXzIjFeJFjIPph2c534fZhEhhIprvoRDazIdAfz+8gSd+7jetCynajepnug1eddwRP1eb/tqJeT1HwRv1mjQSZfIVQdK4CXD5xt9mXgQ22KoWLWuen71qCdImSYHY0WNgx+H96D5hGJpVroU0SZLDkylAeMtYPFiwYEGTuh84cCDSpUuHixcvmqxAtWrVnH3/L8Nuhg8++AAHDhxAvXr13J7jhfyjjz4yF3/+Hk5OxSLHVatWmedZ/1CgQAEMGDDAjI5gl0fXrl3d3qN79+7InTs3MmfObIoPWejIwMPTTVw213z/oNOLER3045d9ULdMFfPz8fOn0XvKCNy8dxvJ4iVGu4+b4vOq9eHt7ty/i+6Th+LC35cRM2oMVC1S1gxvDBvGPQsWUhVKmN98b5GtsW24o1VzsPHiFoQNHQaVU1UwQQADhXEHpuD6o5vO9cslK4k8LvMffJXzc/N99P6JOHn7NEKiicueT/Tzvr/jbpQ57qo6H/+0cqGZU4PdfN7o0vWraDm4O27euW2CgHyZsps5DuL8P5t54sIZfDttFG7du4Ok8RKidc1P8FmV2vB0oRyu+WgJ9DBHDlPkaAILAwJ2IUyZMgV3795Fly5dzCiFa9eumWGQRYsWNQV/7L/nMEcWLQbUumc3BUclMAvAmgVrWmvXYY5s7Z87d84EAQwA6td/cRFknULjxo3NezMDwSCFtQYcHcHt7tu3rymE5JBIBhTMILAbg+8VGKxB4MiMs9dO6dberxEudNB3zQQHHTd1D+pNCBb6FXQP9iVgD3zva9e8xt07d5EuQSbcvn37ledxBQjyRhQgBJ4ChMBRgBA4ChACRwHC2wsQ/tFESSyeY/qbqfQLFy6YZZywZ+PGjf/k7URERMTDvHGAwLR5uXLlTHp69+7dzkl0GIl8+23Iv3mJiIiIN3jjAIF92GPGjMH48ePdhvpxPD7H1ouIiIgXBghHjhwxBXf+sXCN8/6LiIiIFwYIrMjnGH3/WH/gv+JeREREvCRA4FTAvGEQb1LE2QM5xp8T+7Rv395M4ysiIiLB3xtPlNSpUyczVp9T9D548MB0N3AqXgYIvBuhiIiIeGGAwKwBJwHirH7sauC9BzjVb5Qoz6cvFRERkeDvH0+1HC5cOOc9AERERMTLA4QSJUqYLMLLrFmz5t9uk4iIiAS3AIH3IHDF2wlz3v+//vrL7S6DIiIi4kUBAm/sExDegIj1CCIiIhL8/aN7MQSE92aYNGnS23o7ERERCQkBwpYtWxAhQoS39XYiIiISnLoYqlev7vbY4XDg0qVL2LFjB7p16/Y2t01ERESCS4DAey64Ch06NNKnT4/evXujbNmyb3PbREREJDgECL6+vvj000+RNWtWxIwZ891tlYiIiASfGgQfHx+TJdBdG0VEREK2Ny5SzJIlC06ePPlutkZERESCZ4DQt29fc2OmJUuWmOLEO3fuuH2JiIiIF9UgsAixXbt2qFixonlcuXJltymXOZqBj1mnICIiIl4SIPTq1QvNmzfH2rVr3+0WiYiISPAJEJghoGLFir3L7REREZHgVoPwqrs4ioiIiJfOg5AuXbrXBgk3btz4t9skIiIiwSlAYB2C/5kURURExMsDhFq1aiFevHjvbmtEREQkeNUgqP5ARETEe4R+01EMIiIiEvIFuovBz8/v3W6JiIiIBN/bPYtQ2NDhzJe8nAPKugVGrwKd9DEKhOgN82o/BcLp8cu1n17jse8jvJN7MYiIiEjIpwBBREREbBQgiIiIiI0CBBEREbFRgCAiIiI2ChBERETERgGCiIiI2ChAEBERERsFCCIiImKjAEFERERsFCCIiIiIjQIEERERsVGAICIiIjYKEERERMRGAYKIiIjYKEAQERERGwUIIiIiYqMAQURERGwUIIiIiIiNAgQRERGxUYAgIiIiNgoQRERExEYBgoiIiNgoQBAREREbBQgiIiJiowBBREREbBQgiIiIiI0CBBEREbFRgCAiIiI2ChBERETERgGCiIiIeGeAECpUKCxatMj8fPr0afN4z549CCmmTJmCGDFiIKTbuP9P1OjRHKnrvofIFTLg182rXrpu6+97mHV+WDgV3kb76fUmLZuL91p9hOQ1i5ivcu0aYNWOjc7nT106h/p92yJdnRLm+UYDOuLqzevwJu0rNcLDn/ZhUL2Obsvzp8mG5Z0n4O8J23Bl/Gas7DoZEcKGt70+XJiw2NpvrnmPbMnSIyQr3KwWUlQrYfvqNna4ef7MpQtoNqAbcjWsiix13sfng3ri2q0b8HReESC4Spo0KS5duoQsWbIE9abIG7r/6CGypsqAYS27v3K9xZtWYvvhvUgYO55X7mPtp9dLFDs+ujf8AmuGz8Dq4TPwXvZ8qNf3Kxw+c8LsvxrdWj5vWHw7DssHTcaTZ09Rp3cb+Pn5wRvkTpUZjUvUxL4zR2zBwS8dR2P1X5vxXo86KNK9DsasnAU/h32/fFu7LS7dvAZvsHjQGGyfNN/59VPPwWZ5xcLF8eDRQ9Tv1RGhEAozew/FvP7f48mzZ2jSr4vHf57CIIR48uQJwoUL99r1fHx8kCBBgv9km0Li/gtK5fIWNV+vcvHvK2g3ui9+6TcBH3b/DN5I++n1yucv5va4a4NWmLzsZ+w4sg+Xrl/F2asXsXbkLESLFMU8P+qr3khVqxjW79uO4jkKICSLHD4iJrfoj5YTe6JT1WZuzw2s1xGjfp+Jwb9Oci47dum07T3KZiuCUlkKovaItiif4z2EdLGju2dwRy+YieQJEqFA5uzYsHcHzl+7jKVDxyFqpMjm+SGtOyF7/crYvH83imTPDU8VpBkERk8DBw5EmjRpED58eCRLlgz9+vUzz3399ddIly4dIkWKhFSpUqFbt254+vSp87U9e/ZEjhw5MGHCBKRMmRIRIkQwy48dO4aiRYuax5kyZcLKlSvdfmdAXQx//PEH8uXLZ7YhYcKE6NSpE549e2aeGzduHBIlSmSL9KpUqYJGjRqZn0+cOGEex48fH1GiREHevHmxapV7+nvUqFFImzat2S6uV6NGjUDth3Xr1pntvXXrlnN9bjuX8W8JSGC2J0WKFOjTpw8aNGiAaNGioVkz9xNBcMT92HhwR3xZozEyJU8b1JvjsbSf3Pn6+mLBHytMSy9Phmx4/PSJae2FD/siYA4fLjxChwqNbQdCTtfkywz/pAtW7NmAtQe2uS2PGy0W8qXJhmu3b2Bt92k4/eNa/N5lEgqly+m2XrxosTCqSQ80HvMNHjx5BG/z5OlTLPpjJT4qVcGcp/k4FLtcwoZ1rhM+XDiEDhUKfx7aD08WpAFC586dMWDAAHPxP3jwIGbOnGkuahQ1alTTt87lI0aMwPjx4zFs2DC31x8/fhzz58/HggULzEWTJ77q1aublvC2bdswZswYE2i8yoULF1CxYkVzEd27dy9Gjx6NiRMnom/fvub5mjVr4vr161i7dq3zNTdu3MCKFStQt25d8/jevXvmPVavXo3du3ejfPnyqFSpEs6ePWue37FjB1q3bo3evXvjyJEj5rUMYgKzH/6J122PZfDgwciePbtZh787II8fP8adO3fcvjzVkJ/HI0xoH7SsUj+oN8WjaT89d/D0MSSrUQgJq+VHu1H9MK3LEGRIlhp5MmRFpAgR0WvyCBM0sMuh+8Sh8PXzxZWbfyMkq1mgPHKkyIhuc0fYnksZN4n53qV6C0xaNx9VBrbAntOHsKzzeKSOn8y53rjP+mL86rnYdeogvNHv2zfizv17qFGyvHmcM10m83kaMG0cHj5+ZD5T304ZA18/P4+vawmyLoa7d++aC/8PP/yAhg0bmmWpU6dGkSJFzM9du3Z1a+22b98es2fPRseOHd3S4tOmTUPcuHHN499//x2HDx/Gb7/9Zlr99O2336JChQov3Q627FmXwO1gtJchQwZcvHjRBBbdu3dHzJgxzet50S5VqpR5zbx58xAnThyUKFHCPOZFll8WtswXLlyIxYsXo1WrVubCHDlyZHzwwQcm8EmePDly5swZqP3wT7xueywlS5ZEu3btXvle/fv3R69eveDpdh/7C6N+mY7N3883/4+i/fQ6aRKnwLqRs3HnwT0s3rgKnw/rjsUDJpggYXKngWg/6luM+3WWyRxUL1Ye2VNnDNGfrSSx4mNQ/a/xwYBmJoviX+jQz//2iWvnYfr6X8zPe88cRvHM+dGwWFV0nzsSLcvWQdQIkTBo8UR4qzmrlqF4rvyIHyuOs/vhxw490HXMcExZusBkDiq/VwpZUqU1ny1PFmQBwqFDh0zr1Lro+jdnzhyMHDnSpMvZImbKn6lwV7zQWsGB9Z682FvBARUsWPC128F1XA/8woULm995/vx5k+5npqBp06YmmGAXwIwZM1CrVi2EDv38P5frsstj6dKlpgCS2/rw4UNni71MmTJmW9lVwtY8v6pVq2a6T163H/6J122PJU+ePK99L2Y32rZt63zMDAL3safZ9NdOXLt1HekblHQuY4uv84Tv8OOiqTg0dU2Qbp+n0H56gSnfVImet3xzpMmE3ccOYNziWRjaqitK5CqInRN+xfXbNxHGJwyiR4mKjPVKo1qCcgipcqbMhPjRY2NL3znOZfzbi6TPjeZlaiFbh8pm2aELJ9xed+TiSSSNndD8XDxTPuRPmx23p+xwW2dTn1mYvXkZmo590fALic5fvYxN+3ZhTEf3RlXRHHmxfswM3Lhz29TBRY8cBXk+rY5K8Z/vN08VZAFCxIgRX/rcli1bzEWZLddy5cohevToJnswZMgQt/XYKv8vMD3vcDjMBZddERs2bHDr7mB2g7UOTNmzjoB/G2sMmOEgZg127dpl6gmY5WBmghfwP//885X7gawghL/f4lqLEZDXbc+b7D8GRPzydLVLVUaJnO7BYJWuTVC7ZBXUL1styLbL02g/vZyfw2FrOceOHtN8X793u+l791/cGJKw5iB3p+puy8Y1640jF09hyJLJOHX1PC7euIJ0CVO4rZMmQXL8vm+T+bnd9AHoOe8H53MJY8TFkk5jUf+HjvjzhGf3t78NP69ZYTIGJfME3DCNFS26+b553y5cv30LpfMVgicLsgCBBXu8cLGfvEmTJm7Pbd682bS4u3Tp4lx25syZ175nxowZce7cOdNqZrEhbd269bWvYR0DL8BWFmHTpk3mop4kyfM+NxYWsraBmQPWPaRPnx65cuVyvgfX/+STT0xWwGrB+y8gDBMmDEqXLm2+evToYeYtWLNmjakVeNl+ICtDwr+J3R30ujkcArM9wdG9h/dx4uKLLMjpK+ex98QhxIoaHUnjJULsaM/3jyWsTxjEjxkH6ZKkgjfRfnq93lNGonSewkgSN6HZX/PWLcem/Tvwc+9R5vkZK39BuqQpESd6TPx5eB++GTcILarURdok7hfHkOTeowc4eP6427L7jx/ixr3bzuXDlk5F1w9bYP+Zo9h79jDqvVcZ6ROlRJ2Rz7sqz12/bHtPOnnlHC7cuIKQzM/PD/PWrMCHxcshjI+P23NzVy9HmiTJETtadOw6chC9Jv6AxpVqIHXiF7UbnijIAgRedNnPz5oCFhUyrX/t2jUcOHDABA9MhzNrwBY7W+7sQ38dXnw58oF9+YMGDTLpcNcgIyAtW7bE8OHD8cUXX5j+eRYR8gLOtLrVeidmNFhDwO2rV6+e23twe1koyUwDgwwW/LmOeliyZAlOnjxpChN5kV+2bJl5noHGq/ZD48aNTQaAKX1mHDiy4ejRo7ZMin+v257gatexv1Dh6+d1GtRp3ADzvW7pqhjX7vnPov0UGH/fvoGWQ7vhyo2/ES1yFGRKkdYEByVyPh/CePzCafSd+j1u3ruNZPESoe1HjdGiqvtx741++O0nRAgXDgPrdUDMyNGx/+wRfDDgM5Nd8HYb9+3EhWtXzOgF/05eOIeBP43H7Xt3kSRuArSqUReNK9eEpwvSeRB44WLLmil3Fgay1d+8eXNzYfzqq6/MBZv98++//75ZlxfJV+EFnYEEX89hiyxuZB0D+/xfJnHixOaC3aFDB1PYFytWLPN61yJJq6CPzzGAqFOnjttzQ4cONUMeCxUqZIoXecF3rfZntoAXbG7/o0ePzAV81qxZyJw58yv3A4UNG9as26JFC2TLls0ETBxhwdEVL/O67QmuimbLj/vLDwd6fW+tO9B+er2RbV59LunxSRvz5e3K9WtsW8Y5EFznQXiVs39fRMR62eANiubIi9MLX4x2c9WpQTPzFdyEcrh2bou8BgMN1oRcun7BVjQq8k888n2oHRcIsT95dcG1PHd6/HLtite4e+cesibOhdu3b7/yPO7ZYyxEREQkSChAEBERERsFCCIiImKjAEFERERsFCCIiIiIjQIEERERsVGAICIiIjYKEERERMRGAYKIiIjYKEAQERERGwUIIiIiYqMAQURERGwUIIiIiIiNAgQRERGxUYAgIiIiNgoQRERExEYBgoiIiNgoQBAREREbBQgiIiJiowBBREREbBQgiIiIiI0CBBEREbFRgCAiIiI2ChBERETERgGCiIiI2ChAEBERERsFCCIiImKjAEFERERsFCCIiIiIjQIEERERsQljXyTyemsv/I5IdyJpV71C6FCKvwMjvE94fY4C4ccurbWfAqHnlpHaT6/x5P4TBIbOYCIiImKjAEFERERsFCCIiIiIjQIEERERsVGAICIiIjYKEERERMRGAYKIiIjYKEAQERERGwUIIiIiYqMAQURERGwUIIiIiIiNAgQRERGxUYAgIiIiNgoQRERExEYBgoiIiNgoQBAREREbBQgiIiJiowBBREREbBQgiIiIiI0CBBER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",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "from sklearn.naive_bayes import MultinomialNB\n",
    "from sklearn.metrics import ConfusionMatrixDisplay\n",
    "\n",
    "text_clf = make_pipeline(CountVectorizer(stop_words=\"english\", min_df=2), MultinomialNB())\n",
    "text_clf.fit(train_df[\"medical_abstract\"], train_df[\"condition_label\"])\n",
    "pred = text_clf.predict(test_df[\"medical_abstract\"])\n",
    "print(\"test accuracy:\", round(accuracy_score(test_df[\"condition_label\"], pred), 3))\n",
    "\n",
    "ConfusionMatrixDisplay.from_predictions(\n",
    "    test_df[\"condition_label\"], pred,\n",
    "    display_labels=list(label_names.values()), cmap=\"Greens\", colorbar=False,\n",
    "    xticks_rotation=30)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c5e3b55a",
   "metadata": {},
   "source": [
    "整體準確度約 0.59。看混淆矩陣就知道問題在哪：「general pathological conditions」是雜項類別，大量被分到其他四類，其他四類彼此的界線反而清楚得多。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f8051602",
   "metadata": {},
   "source": [
    "每個類別的 `feature_log_prob_` 是「在這一類裡，每個字出現的機率（取對數）」。印出各類最具代表性的字，模型就不再是黑盒子。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "a3c5eb4c",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-09-29T20:02:58.972962Z",
     "iopub.status.busy": "2026-09-29T20:02:58.972880Z",
     "iopub.status.idle": "2026-09-29T20:02:58.980423Z",
     "shell.execute_reply": "2026-09-29T20:02:58.980053Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "neoplasms       patients, cancer, cell, tumor, cells, carcinoma, tumors, disease\n",
      "digestive       patients, disease, liver, treatment, group, study, patient, gastric\n",
      "nervous         patients, disease, treatment, group, pain, study, patient, brain\n",
      "cardiovascular  patients, coronary, pressure, blood, ventricular, group, disease, artery\n",
      "general         patients, group, disease, treatment, study, patient, cases, acute\n"
     ]
    }
   ],
   "source": [
    "vec = text_clf.named_steps[\"countvectorizer\"]\n",
    "mnb = text_clf.named_steps[\"multinomialnb\"]\n",
    "words = vec.get_feature_names_out()\n",
    "for i, label in enumerate(mnb.classes_):\n",
    "    top = np.argsort(mnb.feature_log_prob_[i])[::-1][:8]\n",
    "    print(f\"{label_names[label]:15s}\", \", \".join(words[top]))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "90da0596",
   "metadata": {},
   "source": [
    "腫瘤類出現 cancer、tumor，心血管類出現 coronary、blood、artery，大致符合醫學直覺；但也有 patients、study 這種每一類都常見的字，這是只數次數的詞袋模型的限制。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fd5006c0",
   "metadata": {},
   "source": [
    "比較三種 NB 變體：Multinomial（數次數）、Bernoulli（只看有沒有出現）、Complement（為類別不平衡設計的 Multinomial 變形）。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "00916051",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-09-29T20:02:58.981511Z",
     "iopub.status.busy": "2026-09-29T20:02:58.981455Z",
     "iopub.status.idle": "2026-09-29T20:03:00.633446Z",
     "shell.execute_reply": "2026-09-29T20:03:00.633106Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "MultinomialNB  test accuracy 0.587\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "BernoulliNB    test accuracy 0.559\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "ComplementNB   test accuracy 0.595\n"
     ]
    }
   ],
   "source": [
    "from sklearn.naive_bayes import BernoulliNB, ComplementNB\n",
    "\n",
    "variants = {\n",
    "    \"MultinomialNB\": make_pipeline(CountVectorizer(stop_words=\"english\", min_df=2), MultinomialNB()),\n",
    "    \"BernoulliNB\": make_pipeline(CountVectorizer(stop_words=\"english\", min_df=2, binary=True), BernoulliNB()),\n",
    "    \"ComplementNB\": make_pipeline(CountVectorizer(stop_words=\"english\", min_df=2), ComplementNB()),\n",
    "}\n",
    "for name, model in variants.items():\n",
    "    model.fit(train_df[\"medical_abstract\"], train_df[\"condition_label\"])\n",
    "    acc = accuracy_score(test_df[\"condition_label\"], model.predict(test_df[\"medical_abstract\"]))\n",
    "    print(f\"{name:14s} test accuracy {acc:.3f}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "afcfb22a",
   "metadata": {},
   "source": [
    "三者差距只有幾個百分點，都在 0.56～0.60 之間；這份資料的瓶頸是類別本身模糊，不是選哪個變體。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "46218b7f",
   "metadata": {},
   "source": [
    "最後丟一句自己寫的句子進去試試。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "84572701",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-09-29T20:03:00.634794Z",
     "iopub.status.busy": "2026-09-29T20:03:00.634721Z",
     "iopub.status.idle": "2026-09-29T20:03:00.637023Z",
     "shell.execute_reply": "2026-09-29T20:03:00.636620Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "cardiovascular  <- Patients with acute myocardial infarction underwent coronary angiography.\n",
      "neoplasms       <- Resection of hepatocellular carcinoma improved survival.\n"
     ]
    }
   ],
   "source": [
    "new_docs = [\"Patients with acute myocardial infarction underwent coronary angiography.\",\n",
    "            \"Resection of hepatocellular carcinoma improved survival.\"]\n",
    "for doc, label in zip(new_docs, text_clf.predict(new_docs)):\n",
    "    print(f\"{label_names[label]:15s} <- {doc}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ef95db8e",
   "metadata": {},
   "source": [
    "## 動手試試\n",
    "\n",
    "1. 在第 1 段把 `specificity` 從 0.95 改成 0.99，盛行率 1% 時 PPV 變成多少？（提示：偽陽性人數會剩原本的五分之一）\n",
    "2. 在 GaussianNB 那段只用 `[\"mean radius\", \"mean texture\", \"mean smoothness\"]` 三個相關性較低的特徵訓練，比較準確度與 `predict_proba` 落在極端值的比例。\n",
    "3. 把 `CountVectorizer` 換成 `TfidfVectorizer`，或在 `MultinomialNB(alpha=...)` 試 0.1 與 5，觀察測試準確度如何變化。"
   ]
  }
 ],
 "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.12.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
