《從零開始的資料科學筆記》Day#16: 疾病診斷

更新 發佈閱讀 23 分鐘
raw-image

疾病診斷在醫學領域中是一項非常重要的任務,正確的診斷能夠有效幫助患者及早接受治療,改善預後,並避免不必要的風險。然而,疾病診斷通常需要依賴大量且複雜的數據分析,例如病患的檢測數值、影像和臨床數據等。面對如此大量的資料,人工診斷可能會因主觀判斷或疲勞而存在不確定性,這便為機器學習和人工智慧提供了一個巨大的應用場景。

機器學習技術能夠透過算法與數據,學習疾病的複雜特徵,從而快速且精確地做出診斷判斷。在疾病分類任務中,我們的目標通常是「二元分類」(如惡性腫瘤 vs 良性腫瘤),或是「多類分類」(如不同疾病的類型)。機器學習不僅能協助醫療從業人員進行輔助診斷,還可提升診斷效率,降低潛在的誤診風險。

我將以乳腺癌診斷作為樣本資料,應用機器學習解決二元分類問題,幫助判別乳腺腫瘤是否為惡性。

📂 什麼是分類?

分類任務(Classification Task)是機器學習中的一種核心問題類型,其目的是根據現有數據的特徵,為其分配到特定的類別或標籤。簡單來說,分類任務就是要解答某種「這是什麼?」的問題。例如,根據醫學數據判斷腫瘤是「惡性」還是「良性」;或是根據手寫影像來識別數字是「0~9」中的哪一個。

分類任務廣泛應用於許多特定領域,例如醫療診斷、金融詐欺檢測、垃圾郵件過濾、人臉識別等,為解決多樣化實際問題提供了重要框架。

📦 常見應用

醫療領域:

  • 癌症診斷(良性 vs 惡性)
  • 健康指標分析預測疾病風險

金融風控:

  • 判斷信用卡交易是否為詐欺行為
  • 信用風險評估

電子商務:

  • 客戶分群(VIP/普通客戶)
  • 預測產品是否屬於熱門類型

自然語言處理:

  • 垃圾郵件過濾
  • 文本情感分類(正面、負面)

電腦視覺:

  • 圖像分類(辨識貓、狗)
  • 人臉識別與身份驗證

🧾 0. 環境建議與可重現性

在開發環境安裝所需套件:

pip install numpy pandas scikit-learn matplotlib seaborn joblib

設定亂數種子:

RANDOM_STATE = 42

📦 1. 資料集說明(Dataset Card)

  • 名稱:Breast Cancer Wisconsin (Diagnostic)
  • 來源:sklearn.datasets.load_breast_cancer()
  • 任務:二元分類(預測腫瘤為 malignant / benign)
  • 樣本數:569
  • 特徵數:30 個連續特徵
  • 類別比例:malignant 212,benign 357

🔎 2. 載入與初探(Loading & Quick EDA)

  • 檢查Y欄位的類別比例,如果相差懸殊就會是不平衡資料,需多做額外處理
  • 沒有缺失值
  • 還可以多做”異常值檢查”,利用盒鬚圖或是Z分數可以判斷哪些資料是異常值,再進行後續處理
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.datasets import load_breast_cancer

raw = load_breast_cancer()X = pd.DataFrame(raw.data, columns=raw.feature_names)y = pd.Series(raw.target, name="target")

print(X.shape)
print(X.head(3))
print(y.value_counts(normalize=True))
print("Missing:", X.isna().sum().sum())
(569, 30)

mean radius mean texture mean perimeter mean area mean smoothness \
0 17.99 10.38 122.8 1001.0 0.11840
1 20.57 17.77 132.9 1326.0 0.08474
2 19.69 21.25 130.0 1203.0 0.10960

mean compactness mean concavity mean concave points mean symmetry \
0 0.27760 0.3001 0.14710 0.2419
1 0.07864 0.0869 0.07017 0.1812
2 0.15990 0.1974 0.12790 0.2069

mean fractal dimension ... worst radius worst texture worst perimeter \
0 0.07871 ... 25.38 17.33 184.6
1 0.05667 ... 24.99 23.41 158.8
2 0.05999 ... 23.57 25.53 152.5

worst area worst smoothness worst compactness worst concavity \
0 2019.0 0.1622 0.6656 0.7119
1 1956.0 0.1238 0.1866 0.2416
2 1709.0 0.1444 0.4245 0.4504

worst concave points worst symmetry worst fractal dimension
0 0.2654 0.4601 0.11890
1 0.1860 0.2750 0.08902
2 0.2430 0.3613 0.08758

[3 rows x 30 columns]

target
1 0.627417
0 0.372583
Name: proportion, dtype: float64

Missing: 0

🧼 3. 資料前處理(Preprocessing)

透過前面的統計分析和視覺化分析,前處理通常會包含以下步驟:

  • 缺失值補值
  • 異常值處理
  • 去除重複資料
  • 檢查資料格式
  • ...
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler

X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, stratify=y, random_state=RANDOM_STATE
)
scaler = StandardScaler()

🧩 4. 特徵工程(Feature Engineering)

  • 標準化轉換
  • 特徵篩選
from sklearn.feature_selection import SelectKBest, mutual_info_classif
from sklearn.compose import ColumnTransformer

preprocessor = ColumnTransformer([
("scale", StandardScaler(), X.columns)
])
selector = SelectKBest(score_func=mutual_info_classif, k=20)

🧪 5. 基準模型(Baseline)

分類任務使用的評估指標除了Accuracy之外,常用的為Confusion matrix、F1 Score、ROC、AUC。

from sklearn.dummy import DummyClassifier
from sklearn.metrics import accuracy_score

baseline = DummyClassifier(strategy="most_frequent", random_state=RANDOM_STATE)
baseline.fit(X_train, y_train)
print("Baseline accuracy:", accuracy_score(y_test, baseline.predict(X_test)))
Baseline accuracy: 0.631578947368421

🧠 6. 模型選擇與 GridSearchCV

使用GridSearchCV將設置的參數範圍一個一個掃過,就可以一次性的從這些實驗參數中找出最佳的模型。 除了GridSearch之外,也可以使用RandomSearch和BayesSearch等方法。

from sklearn.linear_model import LogisticRegression
from sklearn.svm import SVC
from sklearn.ensemble import RandomForestClassifier
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import GridSearchCV, StratifiedKFold

# 設定隨機種子
RANDOM_STATE = 42

# 建立流水線 (Pipeline)
pipe = Pipeline([
("scale", StandardScaler()),
("model", LogisticRegression(max_iter=2000, random_state=RANDOM_STATE))
])

# 定義參數網格
param_grid = [
{"model": [LogisticRegression(max_iter=2000, class_weight="balanced")],
"model__C": [0.01, 0.1, 1, 10]},
{"model": [SVC(probability=True, class_weight="balanced")],
"model__C": [0.1, 1, 10], "model__gamma": ["scale", "auto"]},
{"model": [RandomForestClassifier(class_weight="balanced", random_state=RANDOM_STATE)],
"model__n_estimators": [200, 500], "model__max_depth": [None, 5, 10]}
]

# 定義Stratified K-Fold交叉驗證
cv = StratifiedKFold(5, shuffle=True, random_state=RANDOM_STATE)

# 使用GridSearchCV進行超參數調整
grid = GridSearchCV(pipe, param_grid, scoring="roc_auc", cv=cv, n_jobs=-1)
grid.fit(X_train, y_train)

# 印出最佳模型 ROC-AUC 分數
print(f"Best CV ROC-AUC: {grid.best_score_:.4f}")

# 添加印出最佳模型名稱與參數
print("\n===== 最佳模型資訊 =====")
# 顯示最佳模型名稱
best_model_name = grid.best_estimator_.named_steps['model'].__class__.__name__
print(f"最佳模型名稱: {best_model_name}")

# 顯示最佳模型參數
best_model_params = grid.best_params_
print(f"最佳模型參數: {best_model_params}")
Best CV ROC-AUC: 0.9963

===== 最佳模型資訊 =====
最佳模型名稱: SVC
最佳模型參數: {'model': SVC(class_weight='balanced', probability=True), 'model__C': 1, 'model__gamma': 'scale'}

📏 7. 模型評估

挑選完最佳模型後,再進一步評估其各方面的效能,其中Confusion Matrix和ROC-AUC曲線是分類任務中很重要的指標,建議熟悉其原理。

  • ROC-AUC曲線越接近1代表模型整體效能越好
from sklearn.metrics import (accuracy_score, precision_score, recall_score, f1_score,
roc_auc_score, average_precision_score, confusion_matrix, RocCurveDisplay)

best_model = grid.best_estimator_
y_pred = best_model.predict(X_test)
y_proba = best_model.predict_proba(X_test)[:, 1]

print("Accuracy:", accuracy_score(y_test, y_pred))
print("Precision:", precision_score(y_test, y_pred))
print("Recall:", recall_score(y_test, y_pred))
print("F1:", f1_score(y_test, y_pred))
print("ROC-AUC:", roc_auc_score(y_test, y_proba))
RocCurveDisplay.from_estimator(best_model, X_test, y_test)
Accuracy: 0.9649122807017544
Precision: 0.9857142857142858
Recall: 0.9583333333333334
F1: 0.971830985915493
ROC-AUC: 0.9940476190476191
raw-image

🎚️ 8. 閾值調整

分類模型的輸出其實只是一個0~1的數值,需要透過threshold的設定來判斷類別是什麼。

  • 通常預設threshold=0.5,預測值超過0.5則分類成"1"類(惡性),其餘則是"0"類(良性),類別名稱可以依照自己任務定義
  • 調整threshold可以算出不同的指標分數,依照在意的指標嘗試調整到符合標準
from sklearn.metrics import precision_recall_curve, accuracy_score, precision_score, recall_score, f1_score

# 計算 Precision, Recall 和 Threshold
prec, rec, thr = precision_recall_curve(y_test, y_proba)

# 定義一個調整 threshold 並計算新指標的函數
def evaluate_at_threshold(y_true, y_probas, custom_threshold):
"""
根據給定的 threshold 分類,並計算分類指標
"""
# 使用指定門檻值進行分類
y_pred = (y_probas >= custom_threshold).astype(int)

# 計算指標
acc = accuracy_score(y_true, y_pred)
precision = precision_score(y_true, y_pred)
recall = recall_score(y_true, y_pred)
f1 = f1_score(y_true, y_pred)

# 打印輸出
print(f"Threshold: {custom_threshold:.2f}")
print(f"Accuracy: {acc:.4f}")
print(f"Precision: {precision:.4f}")
print(f"Recall: {recall:.4f}")
print(f"F1 Score: {f1:.4f}")

return y_pred, acc, precision, recall, f1

# 任意自定義的 threshold (例如,讓 recall >= 0.95 時,找出對應 threshold 和指標)
custom_thr = thr[np.argmax(rec >= 0.95)]
print("\n=== 評估以 Recall >= 0.95 為目標的門檻值 ===")
y_pred_custom, acc, precision, recall, f1 = evaluate_at_threshold(y_test, y_proba, custom_thr)

# 對不同的 threshold 進行多次測試
thresholds_to_test = [0.3, 0.5, 0.7] # 或者您可自定義其他門檻值
print("\n=== 在不同的 Threshold 下評估 ===")
for t in thresholds_to_test:
print("\nThreshold =", t)
evaluate_at_threshold(y_test, y_proba, t)
=== 評估以 Recall >= 0.95 為目標的門檻值 ===
Threshold: 0.00
Accuracy: 0.6316
Precision: 0.6316
Recall: 1.0000
F1 Score: 0.7742

=== 在不同的 Threshold 下評估 ===

Threshold = 0.3
Threshold: 0.30
Accuracy: 0.9737
Precision: 0.9726
Recall: 0.9861
F1 Score: 0.9793

Threshold = 0.5
Threshold: 0.50
Accuracy: 0.9737
Precision: 0.9859
Recall: 0.9722
F1 Score: 0.9790

Threshold = 0.7
...
Accuracy: 0.9474
Precision: 0.9853
Recall: 0.9306
F1 Score: 0.9571

💾 9. 模型保存與載入

模型評估完成確定可以用之後,將模型儲存以待後續預測使用。 要特別注意在預測之前,要將同樣的資料前處理跟特徵轉換使用在新資料上,才可以丟入模型預測。

import joblib

joblib.dump(best_model, "bc_best_model.joblib")
model = joblib.load("bc_best_model.joblib")

y_pred = model.predict(X_test)
留言
avatar-img
留言分享你的想法!
avatar-img
Ethan的AI學習筆記
4會員
29內容數
我是一個不務正業的資料科學家,從零開始學習的路途上跌跌撞撞,跌過許多坑,也撞過許多牆... 當有人迷失方向時,希望這些筆記可以成為你的指南針。
Ethan的AI學習筆記的其他內容
2025/09/20
在學習完機器學習的各種基礎知識後,我們終於可以開始進入實際應用的階段。機器學習的常見應用大致可分為四大類:迴歸(Regression)、分類(Classification)、分群(Clustering)、以及時間序列分析(Time Series Analysis)。身為資料科學家,理解並掌握這些方法
Thumbnail
2025/09/20
在學習完機器學習的各種基礎知識後,我們終於可以開始進入實際應用的階段。機器學習的常見應用大致可分為四大類:迴歸(Regression)、分類(Classification)、分群(Clustering)、以及時間序列分析(Time Series Analysis)。身為資料科學家,理解並掌握這些方法
Thumbnail
2025/07/25
帶著大家簡單地看過整個機器學習流程之後,相信每個人對於機器學習在幹嘛還是很模糊,因此這章節來個實際範例,讓大家更了解在每一個流程中資料科學家究竟都在做什麼。 這裡我使用機器學習中很有名的”鳶尾花”資料集,這部分內容會比較多,希望大家可以跟著我的步驟慢慢地操作,細細地去體驗如何完成一個基本的機器學習
Thumbnail
2025/07/25
帶著大家簡單地看過整個機器學習流程之後,相信每個人對於機器學習在幹嘛還是很模糊,因此這章節來個實際範例,讓大家更了解在每一個流程中資料科學家究竟都在做什麼。 這裡我使用機器學習中很有名的”鳶尾花”資料集,這部分內容會比較多,希望大家可以跟著我的步驟慢慢地操作,細細地去體驗如何完成一個基本的機器學習
Thumbnail
2025/07/19
在這個章節會繼續介紹機器學習後半部的流程,主要也是概念式的說明,每一個小細節在後續的文章中會再單獨拿出來說明。請大家盡量記得文章中每個流程所提到的專有名詞,大概了解每一個步驟在做什麼對於後續的學習很有幫助!
Thumbnail
2025/07/19
在這個章節會繼續介紹機器學習後半部的流程,主要也是概念式的說明,每一個小細節在後續的文章中會再單獨拿出來說明。請大家盡量記得文章中每個流程所提到的專有名詞,大概了解每一個步驟在做什麼對於後續的學習很有幫助!
Thumbnail
看更多
你可能也想看
Thumbnail
還在煩惱平凡日常該如何增添一點小驚喜嗎?全家便利商店這次聯手超萌的馬來貘,推出黑白配色的馬來貘雪糕,不僅外觀吸睛,層次豐富的雙層口味更是讓人一口接一口!本文將帶你探索馬來貘雪糕的多種創意吃法,從簡單的豆漿燕麥碗、藍莓果昔,到大人系的奇亞籽布丁下午茶,讓可愛的馬來貘陪你度過每一餐,增添生活中的小確幸!
Thumbnail
還在煩惱平凡日常該如何增添一點小驚喜嗎?全家便利商店這次聯手超萌的馬來貘,推出黑白配色的馬來貘雪糕,不僅外觀吸睛,層次豐富的雙層口味更是讓人一口接一口!本文將帶你探索馬來貘雪糕的多種創意吃法,從簡單的豆漿燕麥碗、藍莓果昔,到大人系的奇亞籽布丁下午茶,讓可愛的馬來貘陪你度過每一餐,增添生活中的小確幸!
Thumbnail
在於google的知識時代,我覺得很多人會把很多相關的醫療資訊放在網路上(包含我自己),但是我的文章都有提到說,我也是以經驗分享我的臨床故事及衛教
Thumbnail
在於google的知識時代,我覺得很多人會把很多相關的醫療資訊放在網路上(包含我自己),但是我的文章都有提到說,我也是以經驗分享我的臨床故事及衛教
Thumbnail
帶動病人和家屬說出內心話的解釋模式,有助於醫師正視病人的觀點,以此組織臨床醫療的對策。而醫師將自己的解釋模式清楚地傳達給病人了解,相對也有助於病人、家屬對於什麼時候要開始治療,要找哪些醫師治療,進行怎樣的治療,成本效益大概如何,作出比較實用的判斷。
Thumbnail
帶動病人和家屬說出內心話的解釋模式,有助於醫師正視病人的觀點,以此組織臨床醫療的對策。而醫師將自己的解釋模式清楚地傳達給病人了解,相對也有助於病人、家屬對於什麼時候要開始治療,要找哪些醫師治療,進行怎樣的治療,成本效益大概如何,作出比較實用的判斷。
Thumbnail
隨著醫檢師分科化,除了病理醫檢師,有細胞醫檢師的證照求職時可以加分喔!
Thumbnail
隨著醫檢師分科化,除了病理醫檢師,有細胞醫檢師的證照求職時可以加分喔!
Thumbnail
如果沒有人記錯...醫院還有遺傳鑑定的項目可以做喔,啾咪 (但通常來做這項的,整團都很低氣壓...)
Thumbnail
如果沒有人記錯...醫院還有遺傳鑑定的項目可以做喔,啾咪 (但通常來做這項的,整團都很低氣壓...)
Thumbnail
現今資訊發達的年代,醫師查房都用平板了, 這樣對我來說,有什麼好處壞處呢?
Thumbnail
現今資訊發達的年代,醫師查房都用平板了, 這樣對我來說,有什麼好處壞處呢?
Thumbnail
「智慧醫療」不斷躍進為的就是精準治療,現在中醫也有「經脈血壓計」!遠距把脈、病理大數據分析與AI技術;您也誤入「養生陷阱」了嗎?本書除了大家常爭論、疑惑的流行養生話題,案例中還分享很多一般大眾不知道的醫療知識。
Thumbnail
「智慧醫療」不斷躍進為的就是精準治療,現在中醫也有「經脈血壓計」!遠距把脈、病理大數據分析與AI技術;您也誤入「養生陷阱」了嗎?本書除了大家常爭論、疑惑的流行養生話題,案例中還分享很多一般大眾不知道的醫療知識。
Thumbnail
近期很多人跟我討論精準醫療每個想的都不錯,但就是最好規劃產業的分配 生技醫療重點產業有分醫材、API(原料藥)、生物新藥製劑、通路智慧醫療(精準醫療)目前比較重點的領域 1.慢性病管理 2.疾病預防 3.自主管理 4,病症診斷 5,臨床決策 6.照護服務 這樣從最上面就會開始
Thumbnail
近期很多人跟我討論精準醫療每個想的都不錯,但就是最好規劃產業的分配 生技醫療重點產業有分醫材、API(原料藥)、生物新藥製劑、通路智慧醫療(精準醫療)目前比較重點的領域 1.慢性病管理 2.疾病預防 3.自主管理 4,病症診斷 5,臨床決策 6.照護服務 這樣從最上面就會開始
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News