💡 一句話定義
K-Fold 交叉驗證 = 把訓練資料 切成 K 份,輪流拿其中 1 份當驗證、其餘 K−1 份拿來訓練,總共跑 K 輪。每一輪都從零開始重新訓練一個新模型 ,最後把 K 個分數平均起來,當作這個模型「對沒看過的資料」的預期表現。
以 5-Fold 為例,訓練資料切成 A、B、C、D、E 五份:
輪次 訓練資料 驗證資料 這輪產生的模型
第 1 輪 B + C + D + E A 全新模型 ①(用完就丟)
第 2 輪 A + C + D + E B 全新模型 ②(用完就丟)
第 3 輪 A + B + D + E C 全新模型 ③(用完就丟)
第 4 輪 A + B + C + E D 全新模型 ④(用完就丟)
第 5 輪 A + B + C + D E 全新模型 ⑤(用完就丟)
最容易搞混的一句話: 第 2 輪不會 繼承第 1 輪的學習成果。五輪是五個彼此獨立、從零開始的模型,跑完之後這五個模型的任務就結束了——它們存在的目的只是吐出五個分數 。
🎛️ 互動一:切成幾份、誰當驗證、跑幾次
拉動 K 值看切法怎麼變,按「下一輪」看驗證區塊怎麼輪流。注意右邊的「已從零訓練」計數器——它等於 K,不是 1。
K-Fold 切分實驗室
訓練資料共 800 筆(Test Set 的 200 筆已經先藏起來,不在這裡面)
K =
5
← 上一輪
下一輪 →
▶ 自動播放
訓練用(K−1 塊)
本輪驗證(1 塊)
目前輪次 1 / 5
本輪訓練筆數 640
本輪驗證筆數 160
已從零訓練 1 個模型
K 越大會怎樣? 每輪能用的訓練資料越多(K=10 時有 720 筆),驗證集越小(80 筆)——估計比較貼近「用全部資料訓練」的實力,但要跑的次數也變成 10 次,計算成本線性上升。實務上 K=5 或 K=10 是最常見的折衷。
🎯 為什麼非得跑 K 次?
如果只切一次 80% / 20%,你等於只擲了一次骰子。萬一那 20% 剛好特別簡單或特別難,分數就整個偏掉,而你完全不會知道。K-Fold 讓每一份資料都輪到一次當驗證 ,用 K 個分數的分布來取代單一個數字。
關鍵不是只有平均值。下面兩組分數平均都是 88% ,但意義天差地遠——所以評估報告通常寫成 Accuracy = 88% ± 1.41% 這種「平均 ± 標準差」的格式。
穩定度對賭:一樣的平均,不一樣的體質
拖動每一折的分數,看平均、標準差與全距怎麼變
套用「穩定組」 87/89/86/90/88
套用「不穩組」 98/95/80/75/92
平均 mean 88.00%
標準差 std 1.41
全距 max−min 4
報告寫法 88.00% ± 1.41%
標準差用哪一種? 這裡跟 sklearn 的慣用寫法一致,用 scores.std()(母體標準差,ddof=0)。穩定組是 1.41 ;若改用樣本標準差 ddof=1 會得到 1.58 。兩者都對,重點是報告時說清楚用哪一種 ,不要拿不同定義的數字互比。
⚔️ 互動二:要比較多個模型的時候
常見的誤會是「反正有 5 折,那就一折配一個模型」。不行。 每一種模型都得各自跑完整的 K 折——因為你要比的是「同樣的考卷下,誰的平均比較高」,考卷不一樣就沒得比。
3 種模型 × 5 折 = 15 次訓練
按下開始,看格子一格一格點亮——每一格都是一次完整的從零訓練
▶ 開始跑 15 次
↺ 重置
看「錯誤示範」
已完成訓練次數:0 / 15
錯誤示範:一折配一個模型
Fold 1 給 Logistic、Fold 2 給 Random Forest、Fold 3 給 XGBoost……這樣只跑了 5 次,看起來省事,但每個模型都只被一份不同的驗證資料 考過一次。分數高低可能純粹是「誰抽到比較好考的那一折」,跟模型強弱無關——這就是 K-Fold 一開始要解決的問題,繞了一圈又掉回去了。
只用一種模型也完全可以。 K-Fold 不是非得拿來比賽。你只跑 Logistic Regression 的 5 折、得到平均 88%,那 88% 就是「Logistic Regression 在這批資料上的泛化能力估計」。如果 88% 已經達標,直接用它,完全沒問題。
🔒 互動三:Test Set 從頭到尾都不在 K-Fold 裡
這是整個流程最關鍵、也最常被違反的一條線。假設手上有 1000 筆資料,正確的順序是這樣——點「下一步」跟著走一遍,注意右邊保險箱什麼時候才打開。
完整流程:1000 筆資料的一生
Test Set 在第 2 步就上鎖,一路到最後一步才第一次被打開
← 上一步
下一步 →
↺ 從頭開始
⏭ 直接看完整流程
🔒
Test Set 200 筆
已封存,禁止查看
被使用次數:0
Test Set 在被打開之前,
不參與訓練、不參與調參、不參與模型選擇、不參與任何一次 K-Fold 。只要它提早被看過一次,最後那個分數就不再是「對全新資料的表現」,而是一個灌了水的數字——這就是
資料洩漏 。
🧩 跑完 5 折之後,那 5 份要怎麼處理?
這是最容易卡住的一步。答案是:三個選項裡面,正解是第三個。
🥇 挑分數最高的那一折模型? 不是。 它只是剛好抽到比較好考的驗證集,而且它少看了 1/5 的資料。
🧬 把 5 個模型融合起來? 不一定。 那是另一種做法(Bagging/Ensemble),不是 K-Fold 的預設收尾。
🔁 全部合起來重訓一次? 正解。 A+B+C+D+E = 完整 800 筆,用選定的模型與參數重新訓練一次。
為什麼要重訓?因為 K-Fold 的每個模型都只看過 640 筆。既然你已經用交叉驗證確認「這組設定的預期表現是 88%」,那就沒有理由讓上線的模型少看 160 筆資料。更多資料 → 通常更好的模型。
跑完 K 折 ,得到平均 ± 標準差,例如 88% ± 1.41%。
做決定 :用哪個模型、哪組超參數。K 個臨時模型的任務到此結束,全部丟掉。
用完整 800 筆訓練資料 ,以選定的設定重新訓練一次 → 這才是最終模型。
打開 Test Set 200 筆 ,考一次,得到最終測試成績(例如 87%)。
注意第 4 步的 87% 跟 CV 的 88% 略有差距,這很正常——兩個數字本來就來自不同的資料。如果差距大到誇張 (例如 CV 95%、Test 只有 70%),那通常代表調參時把驗證集用過頭了,或是資料切分本身有問題。
🎓 Validation 與 Test 一定要分清楚
比較 Validation Set 驗證集 Test Set 測試集
它在哪 K-Fold 裡輪流當驗證的那 1 份,來自 Training Set 一開始就切出去、單獨封存的那一份
用途 比較模型、比較參數、選模型 最後一次評估最終模型的泛化能力
看幾次 很多次(每輪、每組參數都會看) 只有一次
白話比喻 平常的模擬考——可以一直考、考完檢討 最後的大考——只考一次,考完就定生死
被違反時 還好,本來就是拿來反覆用的 成績失效,等於作弊
一句話記憶法: K-Fold 是拿來「評估模型」,不是拿來產生 K 個最終模型。
K 次各自從零訓練 → 看平均成績 → 決定模型與參數 → 全部 Training Data 再訓練一次 → Test Set 最後才考。
📌 三個最常見的誤解
誤解一:跑完 5-Fold,我就有一個準確率 88% 的模型了
沒有。88% 是「Logistic Regression 這套做法在這批資料上的預期泛化表現」,是一個對方法的評價 ,不是某個實體模型的成績單。那 5 個實體模型跑完就丟了。真正的模型要等到用完整訓練資料重訓那一次才誕生,而它的成績要等 Test Set 考完才知道。
誤解二:第 2 折會接著第 1 折繼續訓練,越練越強
不會。每一折都是 model = LogisticRegression() 重新建一個、fit() 從零開始。如果會繼承,那第 5 折的模型就等於看過全部資料了,驗證集也就不再是「沒看過的資料」——整個交叉驗證的意義會直接歸零。
誤解三:有 5 折又有 3 個模型,那就一折分一個、剩下的隨便配
不行。要比較就必須同卷同分 :3 個模型各自跑完整的 5 折,總共 15 次訓練,然後比三個平均值。一折配一個模型的話,每個模型的成績都來自不同的驗證資料,高低差可能純粹是運氣。
那 K 要選多少?
K=5 和 K=10 最常見。K 大 → 每輪訓練資料多、估計偏差小,但要跑 K 次、成本高,而且各折的估計之間相關性變高。資料量很小時,有人會用極端的 K=樣本數,也就是 Leave-One-Out。資料類別不平衡時,記得改用 Stratified K-Fold ,讓每一折的類別比例都跟整體一致。
時間序列資料也能這樣切嗎?
不能。一般 K-Fold 會打亂順序,導致「用未來的資料訓練、去預測過去」,這是典型的資料洩漏。時間序列要用 TimeSeriesSplit :永遠拿過去訓練、未來驗證,訓練窗口逐步往前推。