中級科目三程式實戰 · scikit-learn 實作題

StandardScaler × PCA × LogisticRegression:
一條 Pipeline 與交叉驗證的 17 行程式

這段程式做的事是:拿乳癌資料,先標準化、再降維、最後分類,然後用 5 折交叉驗證評分。它藏了一個最容易被扣分的觀念——為什麼前處理一定要放進 Pipeline,而不能先對整份資料做

閱讀模式

00題目

使用 scikit-learn 的 Breast Cancer 資料集評估 StandardScaler、PCA 與 LogisticRegression 的組合。下列寫法將前處理放入 Pipeline,再交由交叉驗證執行。

 1  from sklearn.datasets import load_breast_cancer
 2  from sklearn.decomposition import PCA
 3  from sklearn.linear_model import LogisticRegression
 4  from sklearn.model_selection import StratifiedKFold, cross_val_score
 5  from sklearn.pipeline import Pipeline
 6  from sklearn.preprocessing import StandardScaler
 7
 8  X, y = load_breast_cancer(return_X_y=True)
 9
10  pipe = Pipeline([
11      ("scale", StandardScaler()),
12      ("pca", PCA(n_components=10)),
13      ("clf", LogisticRegression(max_iter=2000))
14  ])
15
16  cv = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)
17  scores = cross_val_score(pipe, X, y, cv=cv, scoring="roc_auc")

相較於先在完整 X 上執行 scaler.fit_transform(X)pca.fit_transform(X),上述 Pipeline 在交叉驗證中最重要的優點為何?

不熟 AI 專有名詞?你需要先認識下列名詞

點擊後出現漸進式說明:白話說明 → 說清楚一點 → 常見錯誤與考點。

資料與任務
特徵 featureX 與 y監督式學習非監督式學習
前處理與降維
標準化 StandardScalerPCA 主成分分析解釋變異數比例降維
模型與訓練
LogisticRegressionSigmoid 函數max_iter 與收斂超參數
驗證方式
交叉驗證K 折 K-Fold分層 Stratifiedrandom_state 隨機種子訓練折與驗證折
評估指標
ROC-AUCAccuracy 準確率Recall 召回率正類 positive class
最容易被扣分的三個
資料洩漏Pipeline 流程管線過擬合

不熟 Python?你需要先認識下列名詞

點擊後出現漸進式說明

把工具拿進來
importfrom模組 module函式庫 library
存東西、取名字
= 指派變數X, y = ... 多重指派
呼叫與設定
函式 function( ) 呼叫括號參數關鍵字參數括號內的 =
資料的裝法
[ ] list 串列( ) tuple 元組" " 字串True / False縮排
設計圖與機器
類別 class實例化大小寫命名慣例
物件與方法(點的用法)
. 點運算子方法 method屬性 attribute尾巴有底線的屬性估計器統一介面
scikit-learn 的三個動詞
fittransformfit_transformpredictpredict_proba
資料與機器學習
X 與 yshape 形狀NumPy 陣列監督式學習訓練折與驗證折

01逐行拆解:第 1 行到第 17 行

17 行,前 6 行是把工具拿進來,第 8 行載入資料,第 10–14 行組裝流程,第 16 行定義切法,第 17 行才真的開始跑

先認識一個符號:點 .

這是物件導向的寫法。scikit-learn 整套都建立在它上面——先做出一台機器,再叫這台機器做事,而「叫它做事」就是靠這個點。

sklearn.datasets   點的左邊是模組 唸「裡面的」
scaler.fit(X)      點的左邊是物件 唸「它的」

scaler.fit(X)      括號 = 方法,叫它做一件事
X.shape            括號 = 屬性,看一格資料

想深入的話點這裡:點 . 到底是什麼?方法和函式差在哪?屬性和方法差在哪?為什麼有些屬性尾巴有底線?什麼是估計器統一介面?

第 1–6 行:匯入區

這六行的句型完全一樣:from 模組 import 名字,差別只在拿的是哪個東西。import 本身不執行任何運算,它只是把工具擺到桌上,讓你之後可以直接叫它的名字。

第 1 行取得「載入乳癌資料」的函式
from sklearn.datasets import load_breast_cancer

sklearn.datasets 是 scikit-learn 收錄示範資料集的模組,裡面還有 load_iris(鳶尾花)、load_digits(手寫數字)、make_classification(自己生一份假資料)。這行只是把 load_breast_cancer 這個函式拿到手上,資料一筆都還沒讀進來——真正讀取是第 8 行。

名字全小寫加底線(load_breast_cancer)是 Python 對函式命名慣例,看到這種長相就可以猜「它是一台做事的機器,加括號會吐東西出來」。

第 2 行取得 PCA 降維工具
from sklearn.decomposition import PCA

decomposition分解。PCA 被放在這裡,是因為它的數學核心就是對資料的共變異矩陣做特徵分解,把矩陣拆成幾個主要方向。同一個模組裡還有 TruncatedSVD(適合稀疏矩陣)、NMF(非負矩陣分解)、FastICA

PCA大寫開頭,代表它是一個類別,也就是「設計圖」,要加括號才會做出一台真的機器。這和第 1 行小寫的函式是兩種不同的東西。

第 3 行取得邏輯迴歸分類器
from sklearn.linear_model import LogisticRegression

linear_model 收的是「輸出=輸入的線性組合」那一族:LinearRegressionRidgeLassoElasticNetSGDClassifier。邏輯迴歸雖然是做分類,仍被歸在線性模型,因為它在套 Sigmoid 之前那一段確實是把特徵加權相加。

第 4 行一次取得兩樣東西
from sklearn.model_selection import StratifiedKFold, cross_val_score

這是唯一一行拿兩樣東西的,用逗號分隔。兩者的分工要分清楚:

名字角色負責什麼
StratifiedKFold規則資料怎麼切:切幾折、要不要洗牌、每折的類別比例怎麼維持。它自己不會訓練任何模型。
cross_val_score執行者拿著上面那個規則,真的去跑:切折、訓練、預測、計分,最後回傳分數陣列。

model_selection 模組專門放「怎麼切資料、怎麼評估、怎麼調參」,常見的還有 train_test_splitGridSearchCVcross_validateKFold

第 5 行取得 Pipeline 生產線工具
from sklearn.pipeline import Pipeline

用來把多個步驟串成一個整體。同模組還有 make_pipeline(不用自己取步驟名稱的簡寫版)與 FeatureUnion(把多組特徵並聯後接起來)。這行也只是把工具拿到手,還沒串任何東西。

第 6 行取得標準化工具
from sklearn.preprocessing import StandardScaler

preprocessing資料進模型之前的加工。這個模組是特徵工程的大本營:縮放、編碼、離散化都在這裡。這行拿的 StandardScaler 負責把每一欄變成「平均 0、標準差 1」,是最通用的縮放方式,也是 PCA 前面幾乎一定要接的一站。

工具做什麼什麼時候用它而不是 StandardScaler
StandardScaler平均 0、標準差 1本題用的,最通用
MinMaxScaler壓到 0~1 之間需要固定值域時(例如餵給神經網路的影像)
RobustScaler用中位數與四分位距資料有明顯離群值,不想被極端值拉歪
OneHotEncoder類別欄位轉成 0/1 欄處理的是文字類別而非數字
第 8 行真正載入資料
X, y = load_breast_cancer(return_X_y=True)

到這行資料才真的被讀進記憶體。拆成三塊看:

片段意思
load_breast_cancer()括號就是啟動鈕——沒有括號只是「指那台機器」,加了括號它才會動。
return_X_y=True關鍵字參數:告訴它「我只要特徵和答案兩包,其他不用」。不加的話它會回傳一個大包裹,要自己拆 .data.target
X, y =多重指派:右邊一次吐出兩包,左邊兩個箱子分別接住。順序不能顛倒。

拿到的東西是:X569 筆 × 30 個特徵的表格,y569 個 0/1 答案形狀分別寫成 (569, 30)(569,)

這裡有個反直覺、但考試會考的點:0 = 惡性 malignant1 = 良性 benign——1 是好消息。scikit-learn 預設把標籤 1 當成正類,所以本題的 ROC-AUC 衡量的是「把良性排在惡性前面的能力」。它本質上仍是兩類的區分能力,數值不受影響。

總樣本 569 惡性 (0) 212 · 37.3% 良性 (1) 357 · 62.7% 特徵數 30

30 個特徵是 10 種測量 × 3 種統計:半徑、紋理、周長、面積、平滑度、緊密度、凹陷度、凹點數、對稱性、碎形維度,每種各取平均值、標準誤、最差值。為什麼要分成 X 和 y?

第 10 行開始組裝生產線
pipe = Pipeline([

Pipeline 要收一個清單當參數,清單裡按順序放各個步驟。所以這行的結尾出現兩個括號連在一起:(呼叫 Pipeline[開一個 list 清單這不是打錯字。

左邊的 pipe 是你自己取的變數名,換成 modelmy_pipeline 都可以。

第 11 行第 1 站:標準化
    ("scale", StandardScaler()),

每一站都寫成 ("步驟名稱", 工具物件) 這樣的一組,這種括起來的一組叫 tuple

片段是什麼可以改嗎
"scale"你自己取的步驟名稱,加引號代表這是文字可以。之後能用 pipe.named_steps["scale"] 把這一站抓出來檢查;做網格搜尋時寫成 scale__with_mean兩個底線)指定這一站的參數。
StandardScaler()實際做出來的機器(注意有括號)括號裡可以放設定,例如 StandardScaler(with_mean=False)。這裡留空表示全用預設值。

結尾的逗號代表「還有下一站」。前面那四格縮排在括號內部只是為了好讀,怎麼排都不影響執行。

這一站在訓練時會做的事:從訓練資料算出每一欄的平均值與標準差並記住,然後把資料轉成 \(z=(x-\mu)/\sigma\)。詳細在 第 02 節

第 12 行第 2 站:降維
    ("pca", PCA(n_components=10)),

n_components=10 表示最後保留 10 個主成分,所以資料形狀會從 (455, 30) 變成 (455, 10)(455 是一折的訓練筆數)。

10 是整數,不用加引號——加了就變成文字,會報錯。這個位置也可以填小數:PCA(n_components=0.95) 代表「自動選到累積解釋變異達 95% 為止」,這份資料剛好會選到 10 個。詳細在 第 03 節

第 13 行第 3 站:分類模型
    ("clf", LogisticRegression(max_iter=2000))

"clf" 是 classifier(分類器)的慣用縮寫,跟 cv = cross-validation、pipe = pipeline 一樣純粹是取名。

這是 Pipeline 的最後一站。Pipeline 有個硬性規定:前面每一站都必須會 transform,只有最後一站可以是模型

max_iter=2000 是最佳化的迭代次數上限,不是「一定要跑 2000 次」。詳細在 第 04 節

注意這行結尾沒有逗號——因為它是清單的最後一項。(Python 其實允許最後一項後面也加逗號,加了不會錯。)

第 14 行生產線組裝完成
])

] 關閉步驟清單、) 關閉 Pipeline 的呼叫,剛好跟第 10 行的 ([ 對稱。

到這裡,pipe 代表整套處理流程——但一克原料都還沒送進去。這叫延遲執行:先把流程定義好,之後才餵資料。好處是同一條生產線可以重複用在不同資料上,也是交叉驗證能「每折重組一次」的前提。
輸入原始 X
      ↓
  ① scale   StandardScaler       每欄減平均、除標準差
      ↓
  ② pca     PCA(10)              30 維 → 10 維
      ↓
  ③ clf     LogisticRegression   輸出良性機率
      ↓
   預測結果
第 16 行定義資料怎麼切
cv = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)

三個關鍵字參數

參數意思不設會怎樣
n_splits=5切成 5 份 → 跑 5 輪,每筆資料被訓練 4 次、驗證 1 次預設就是 5。切越多份越接近真實效能但越慢
shuffle=True切之前先洗牌原始資料若有排序(前面都惡性、後面都良性),不洗牌會切出偏頗的折
random_state=42固定亂數種子,每次執行結果一模一樣因為有 shuffle,不固定的話每次跑分數都不同,沒辦法比較模型也沒辦法除錯。42 沒有統計意義,換成任何整數都行,重點是固定

Stratified(分層)是關鍵字:普通的 KFold 只管切成 5 等份,不管每份的類別比例;StratifiedKFold 會確保每一折的良性/惡性比例都跟整體一樣(62.7% 良性),避免切出「某一折幾乎全是良性」的荒謬結果。

跟第 10 行一樣,這行也只是定義規則,還沒真的去切。cv 這個名字是自己取的。

第 17 行整段唯一真正動起來的一行
scores = cross_val_score(pipe, X, y, cv=cv, scoring="roc_auc")

前三個是位置參數(照順序認人),後兩個是關鍵字參數:

參數意思
pipe要評估的東西。注意這裡評估的不是單一模型,而是整條 Pipeline(標準化 → PCA → 邏輯迴歸)。
X輸入特徵,569 × 30 的原始資料——沒有先標準化、沒有先降維,全部交給 Pipeline 處理。
y每一筆的正確答案(0 惡性、1 良性)。
cv=cv左邊的 cv 是 sklearn 規定的參數名,右邊的 cv 是第 16 行建立的變數,兩者剛好同名而已。為什麼不是廢話?
scoring="roc_auc"用 ROC-AUC 當評估指標。它需要連續的機率分數,所以 sklearn 會自動去呼叫 predict_proba 而不是 predict。詳細在 第 06 節

它實際會做的事,是把下面這段跑 5 遍:

── 第 k 折 ────────────────────────────
  複製一套全新的 Pipeline(不沿用上一折學到的任何東西)

  【訓練折 455 筆】
    StandardScaler.fit        只從這 455 筆算平均值、標準差
    PCA.fit                   只從這 455 筆找 10 個主成分方向
    LogisticRegression.fit    用轉換後的資料訓練

  【驗證折 114 筆】
    StandardScaler.transform  用訓練折的平均值 / 標準差,不重學
    PCA.transform             用訓練折的主成分方向,不重學
    predict_proba → 計算這一折的 ROC-AUC

最後 scores 裡是 5 個數字。本題實跑結果:

array([0.99384, 0.99770, 0.98412, 1.00000, 0.99870])
        第1折     第2折     第3折     第4折    第5折

scores.mean()  → 0.9949    平均表現
scores.std()   → 0.0058    折與折之間的波動,越小越穩定

scores.mean() 這種寫法就是方法——scores 是一個 NumPy 陣列物件,mean() 是它自帶的功能,不用你自己寫迴圈加總再除以 5。

整段程式的重點就在這一行的兩個字:pipe因為送進去的是整條 Pipeline 而不是「已經處理好的資料」,前處理才會被關在每一折裡面重新學一次——這就是本題答案 A 說的事。詳細在 第 05 節

02深入:StandardScaler 為什麼非做不可

這 30 個特徵的實際數值範圍差距非常大(本站實跑):

特徵最小值最大值平均值標準差
mean area 面積143.52501.0654.89351.60
worst area 最差面積185.24254.0880.58568.86
mean perimeter 周長43.79188.591.9724.28
mean radius 半徑6.98128.1114.133.52
mean smoothness 平滑度0.05260.16340.09640.0141

面積動輒上千,平滑度只有 0.1,差了將近兩萬倍。對 PCA 來說,「變異最大的方向」幾乎一定被面積霸佔;對 LogisticRegression 來說,梯度下降在尺度懸殊的空間裡很難收斂。

\[ z = \frac{x - \mu}{\sigma} \qquad(\mu = \text{該欄平均值},\ \sigma = \text{該欄標準差}) \]

白話是「你比平均高多少個標準差」。轉換後每一欄的平均值都變成 0、標準差都變成 1。

標準化不會改變資料的形狀或排名。誰大誰小、分布長什麼樣都一樣,只是換了刻度,就像攝氏換華氏。所以它不會憑空增加資訊,只是讓後面的演算法別被單位騙了。
互動實驗室:標準化前後對照真實資料 90 筆
同一批資料,只是換刻度

誰需要標準化

演算法需要嗎原因
PCA強烈需要直接找變異最大方向,數值大的欄位會通吃
Logistic Regression需要梯度下降收斂快很多;用正則化時更是必須
KNN / SVM / K-means需要都在算距離,尺度大的欄位主宰距離
決策樹 / 隨機森林 / XGBoost不需要只比較大於或小於某個門檻,換刻度不影響切點
本站實跑:只丟給 LogisticRegression 不標準化,5 折 ROC-AUC 平均 0.9925,而且會噴 ConvergenceWarning(迭代 2000 次還沒收斂)。加上 StandardScaler 後升到 0.9953,而且乖乖收斂。
分數差距不大是因為這份資料本來就很好分,但「跑不收斂」本身就是尺度沒對齊的警訊。

03深入:PCA 到底做了什麼

最常見的誤解:以為 PCA 是從 30 欄裡選出最重要的 10 欄,其他丟掉。
正確理解:PCA 把 30 欄重新加權混合,造出 10 個全新的欄位。每個新欄位都是原本 30 欄的加權總和,例如 PC1 = 0.22×半徑 + 0.10×紋理 + 0.23×周長 + …(30 項全部有份)。

為什麼要這樣做?因為原本 30 個特徵高度重複——半徑、周長、面積根本是同一件事的三種說法(周長 ≈ 2πr,面積 ≈ πr²)。PCA 把這種重複壓掉,用比較少的軸描述同樣多的資訊。

它會把新造出來的軸由重要到不重要排序。第 1 主成分是資料變化最大的方向,第 2 主成分是跟第 1 垂直、變化次大的方向,以此類推。每個主成分能解釋多少比例的總變異,就叫 explained variance ratio。以標準化後的乳癌資料實跑:

PC1 44.27%PC2 18.97%PC3 9.39%PC4 6.60%PC5 5.50%

前 10 個加起來是 95.16%——用 10 個新軸保留了原本 30 欄裡九成五的資訊,維度砍掉三分之二。

互動實驗室:PCA 降維滑桿AUC 為實跑數據
保留資訊量(累積解釋變異)95.16%
維度30 → 10
5 折 ROC-AUC 平均0.9949
優點代價
降低維度、減少計算量與過擬合風險新特徵失去可解釋性(PC1 到底是什麼?說不清)
去除特徵間的重複與共線性可能丟掉變異小但對分類有用的資訊
壓到 2~3 維就能畫圖視覺化對尺度極度敏感,沒標準化等於白做
PCA 不保證提高準確率。它是非監督式的——只看 X 的變異,完全不知道 y 是什麼,所以挑出的「變異最大方向」不見得是「最會分辨良性惡性的方向」。
本題實跑:不降維(30 維)0.9953、降到 10 維 0.9949、降到 1 維掉到 0.9709。降維換到的是速度與簡潔,不是準確率。

這也是選項 B 錯的原因:pca.fit(X) 的簽名裡 y 是被忽略的參數,PCA 從頭到尾只看 X 的共變異結構。用標籤決定投影方向的那是 LDA,不是 PCA。

04深入:LogisticRegression 與 max_iter

它名字叫迴歸,工作是分類。先算一個迴歸式:把 10 個主成分加權相加得到分數 \(z\),然後用 Sigmoid 壓成 0~1 的機率:

\[ z = w_1x_1 + \dots + w_{10}x_{10} + b \qquad P = \frac{1}{1+e^{-z}} \]

輸出是「良性的機率」,例如 0.93。要變成硬答案時再套門檻(預設 0.5)。所以它輸出的是機率,只是最後被切成類別——這也是為什麼本題能算 ROC-AUC。

max_iter=2000 在幹嘛

模型要找出最好的那組權重,是靠反覆微調(預設用 lbfgs 演算法),直到幾乎不再進步為止——這叫收斂。max_iter安全上限

情況會發生什麼
第 180 次就收斂提早停止max_iter 是上限,不是「一定要跑幾次」
2000 次還沒收斂印出 ConvergenceWarning,用目前最好的權重交差,結果可能不是最佳解
本站實跑:這份資料經過標準化後,用預設的 max_iter=100 就足夠收斂;不標準化時,即使給到 2000 次也照樣噴警告。
換句話說,把 max_iter 調大只是止痛藥,把資料標準化才是治本——sklearn 的警告訊息本身也是這樣寫的:「You might also want to scale the data」。

05核心考點:Pipeline 與資料洩漏

很多人會很自然地這樣寫,因為看起來比較簡單:

# 錯誤示範
X_scaled = scaler.fit_transform(X)      # 對全部 569 筆學平均值與標準差
X_pca = pca.fit_transform(X_scaled)     # 對全部 569 筆學主成分方向

scores = cross_val_score(model, X_pca, y, cv=cv)  # 現在才切折
問題:切折之前,前處理已經看過全部資料了。等到 cross_val_score 把第 1 折當驗證資料時,那 114 筆的資訊早就混進 scaler 的平均值、標準差,以及 PCA 的主成分方向裡。驗證資料本來應該扮演「模型從沒見過的新病人」,現在卻已經偷偷參與過前處理的訓練——這就是資料洩漏

有人會反駁「可是 PCA 又沒用到 y,哪來的洩漏?」——洩漏不只發生在標籤上。即使只看 X,驗證折仍然貢獻了:

結果就是交叉驗證分數偏樂觀,模型真正上線遇到全新病人時,表現會比報告數字差。

洩漏不是抽象概念,它有具體的存放位置。執行 scaler.fit_transform(X) 之後,那組被汙染的平均值與標準差就躺在 scaler.mean_scaler.scale_ 這兩個尾巴帶底線的屬性裡;PCA 的主成分方向則躺在 pca.components_。之後不管你怎麼切折,模型用的都是這幾組已經看過驗證資料的數字。

Pipeline 怎麼堵住這個洞

呼叫 pipe.fit(X_train, y_train) 時,內部自動這樣做:

前面每一站(scale、pca)→ fit_transform(訓練資料)      學參數 + 轉換
最後一站(clf)        → fit(轉換後資料, y_train)       訓練模型

呼叫 pipe.predict(X_val) 時:

前面每一站(scale、pca)→ 只呼叫 transform(驗證資料)     用訓練學到的參數,不重學
最後一站(clf)        → predict()
驗證折全程只被 transform,從來沒有被 fit 過。它完美扮演了「未來的新病人」。Pipeline 天生就分得清「什麼時候該 fit、什麼時候只能 transform」——你自己手寫很容易搞混,Pipeline 不會。
互動實驗室:Pipeline 逐步追蹤器比較訓練與驗證的差別
原始資料
(455, 30)
① scale
StandardScaler
② pca
PCA(10)
③ clf
LogisticRegression
互動實驗室:5 折交叉驗證動畫每折分數為實跑數據
569 筆資料,5 折
互動實驗室:資料洩漏對照實驗兩組數字都是實跑

先對完整 X 做 fit_transform

平均 —

放進 Pipeline 交給 cross_val_score

平均 —
選一組資料,按「開始跑 5 折」。
誠實地說:在乳癌這份資料上,洩漏版和 Pipeline 版分數幾乎一樣(0.9949 vs 0.9949)。原因是①樣本多(569 筆),多看 114 筆對平均值影響很小;②StandardScaler 與 PCA 都是非監督的,沒碰到 y,洩漏強度最弱。
但只要換成樣本少、或前處理用到 y(特徵選擇、目標編碼、SMOTE、用整體平均補缺失值),差距就會非常誇張。上面那個「純亂數」按鈕就是例子:資料完全是隨機的、真實 AUC 應該是 0.5,洩漏版卻報出 0.929。
所以正確做法不是「看情況」,而是養成永遠用 Pipeline 的習慣

06深入:ROC-AUC 在衡量什麼

ROC-AUC 不是「猜對幾筆」(那是 Accuracy)。它衡量的是:隨便抓一個良性病例和一個惡性病例,模型給良性的分數比較高的機率有多大。

換句話說,它問的是排序能力,不是判斷力。想像把 60 份報告依「模型覺得有多像良性」由高到低排成一列:

完美的模型   ●●●●●●●●●●●●●●●●●●●●●●●●│●●●●●●●●●●●●●●●●   AUC = 1.0
             ←──── 良性全部在左邊 ────┤─── 惡性全部在右邊 ──→

沒用的模型   ●●○●○○●●○●○●●○●○○●●○●○●●○●●○●○○●●○●○●●○●   AUC = 0.5
             ←──────────── 紅綠交錯,排了等於沒排 ────────────→

AUC 就是在量「這一列排得多乾淨」,跟你把切點畫在哪裡完全無關——這也是它比 Accuracy 穩的原因。下面這個實驗室可以直接拖看看。

互動實驗室:ROC-AUC 到底在量什麼拖動看 AUC 怎麼變
門檻只影響右邊四格,不影響 AUC
AUC意義
0.5跟丟銅板一樣,完全沒有區分能力
0.7尚可
0.8良好
0.9非常好
1.0完美區分(實務上看到 1.0 通常先懷疑資料洩漏

為什麼分類問題常用 AUC 而不是 Accuracy?①不受門檻影響:Accuracy 要先決定 0.5 這個切點,AUC 是把所有可能門檻都掃一遍算出來的。②對類別不平衡比較穩:如果 95% 都是良性,模型全猜良性也有 95% Accuracy,看起來很棒但毫無用處,AUC 會直接打回 0.5。

醫療情境要特別注意 Recall(召回率)。把惡性誤判成良性(漏掉癌症)比把良性誤判成惡性(虛驚一場)嚴重太多。實務上除了 AUC,一定要另外看惡性類別的 Recall,並可能把判定門檻從 0.5 往下調。

平均值回答「這個流程大概多強」,標準差回答「這個估計可不可信」。本題標準差 0.0058 很小,代表換一份資料表現也差不多;如果標準差很大(例如 0.08),代表模型對資料切分方式很敏感,平均值那個數字就別太當真。

07自我檢測

七題,答錯會直接告訴你錯在哪。

08重點整理

  1. from A import B =去 A 這個模組,把 B 拿到手上,不執行任何運算
  2. 有括號才會動:PCA 是設計圖,PCA() 是做出來的機器。
  3. 括號外的 = 是「存進箱子」,括號內的 = 是「指定參數」,所以 cv=cv 不是廢話。
  1. sklearn 只有三個動詞:fit(學並記住)、transform(套用已學的)、predict(預測)。
  2. StandardScaler 把每欄變成平均 0、標準差 1,讓 PCA 和 LogisticRegression 不被單位騙。決策樹家族不需要。
  3. PCA 不是挑欄位,是重新加權混合造新欄位;它是非監督的,完全不看 y,所以不保證提高準確率。
  4. LogisticRegression 名字是迴歸、工作是分類;max_iter 是上限不是固定次數,收斂了會提早停。
  5. StratifiedKFold 確保每折的類別比例跟整體一樣;shuffle=True 要搭配 random_state 才能重現。
  6. Pipeline 最大的價值不是少寫幾行,是不會把 fit 用錯地方。
  7. 本題答案 A:每一折的前處理只從該折的訓練資料學參數,驗證折全程只被 transform,避免資料洩漏,交叉驗證分數才可信。
容易洩漏的前處理:特徵選擇(SelectKBest)、目標編碼、過採樣(SMOTE)、用整體平均補缺失值、標準化與降維。只要它會從資料學到東西,就一定要放進 Pipeline。像「把公斤換成公克」這種固定規則的轉換就沒有洩漏問題。
完整程式碼
StratifiedKFold(5, shuffle=True, random_state=42) 切出來的結果 569 筆 · 每筆當過 4 次訓練、1 次驗證
load_breast_cancer() 拿到的資料
顯示方式 顯示 50 / 569 列,可左右與上下捲動