跳到主要內容
Lab Grimoire
TW
請喝咖啡
動手實作

機器學習流程:資料切分、洩漏、不平衡與漂移

學習類型,訓練、驗證、測試集的角色,過擬合處理,資料洩漏的五種來源,分層與群組交叉驗證,SMOTE 的正確位置,特徵儲存庫與漂移監控。

作者
CY
發表
AI 的資料基礎:從統計到生成式 AI · 第 12/19 篇

本系列第 12 篇|這篇回答:機器學習怎麼從資料學到規律?哪些步驟最容易讓評估分數失真? 讀完這篇,你應該能:

  • 畫出從切分、訓練、驗證到上線監控的機器學習流程,並說出每一步可以用哪些資訊
  • 從情境裡找出資料洩漏與不當驗證,包含切分前的前處理、目標洩漏、時間洩漏,以及同一人跨在訓練與測試兩邊
  • 面對不平衡資料時換指標、把重採樣放在正確的位置,並說明特徵儲存庫與漂移監控各自防哪一種上線失敗

一、大數據是機器學習的燃料,也是陷阱來源

模型學到的內容,同時取決於資料裡有什麼,以及訓練步驟被允許看到什麼。資料夠,規律才有機會被學到;資料裡若混進預測當下還沒有的資訊,驗證分數會偏高,上線就對不上。

學習類型

有現成標籤、沒有標籤、靠環境獎勵或自造標籤,學習類型各不相同。

詳細說明

標籤從哪裡來,決定學習類型。

監督式學習(supervised learning)使用現成標籤。預測類別是分類(classification),預測數值是迴歸(regression)。每一筆歷史都已經有答案,才有辦法算預測與答案的差距。

非監督式學習(unsupervised learning)沒有標籤。工作是分群(clustering)或降維(dimensionality reduction):把相似的觀測放在一起,或把很多欄位壓成較少的表示。

強化學習(reinforcement learning)的學習訊號來自環境。學習者採取行動,環境狀態隨之改變,再依獎勵(reward)調整之後的行動。學習紀錄包含獎懲與互動時,學習類型就是這一種。

自監督學習(self-supervised learning)的標籤從資料本身造出來。做法例如把句子裡的字詞遮住,再預測被遮住的部分。大型語言模型的預訓練也屬這一類:用前文預測下一個詞,答案直接來自原文。

三個子集

會估計統計量或做特徵選擇的步驟,只能在切分後對訓練側擬合。

詳細說明

監督式流程把歷史資料分成三份,三份的工作固定。

訓練集(training set)學參數,讓模型在這些筆上的擬合變好。

驗證集(validation set)調超參數(hyperparameter)、比較模型。設定可以更換,驗證表現也可以再看。

測試集(test set)只在最後用一次,估計上線表現。它不參加選模型。看過測試分數又回頭改模型,這一份就轉去承擔驗證的工作,那個數字不再是未參與選擇的估計。

因此,任何會從資料估計統計量或挑選欄位的前處理、特徵選擇,都要放在切分之後,而且只對訓練側擬合。切分前對全體做,測試集就參加了這些估計。

兩種擬合失敗

訓練遠好於驗證表示變異偏高,兩邊都不好表示偏差偏高。

詳細說明

過擬合(overfitting):訓練表現好、驗證表現差。模型把訓練集裡的雜訊也記進去,換一批資料就對不上。

欠擬合(underfitting):訓練與驗證都差。模型太簡單,訓練集裡的規律也沒有抓到。

中間是偏差(bias)與變異(variance)的權衡。模型越複雜,偏差下降、變異上升:它較能跟上彎曲的關係,也較會跟著手邊這一小批樣本搖。模型越簡單,偏差較高、變異較低。訓練遠好於驗證,表示變異已經偏高;兩邊都不好,表示偏差仍然偏高。

資料洩漏從哪進來

訓練用到預測當下拿不到的資訊,測試分數就會偏樂觀。

詳細說明

資料洩漏(data leakage)指訓練時用到預測當下拿不到的資訊。測試分數會偏樂觀,上線沒有那些資訊,表現就下滑。

切分前做前處理或特徵選擇。統計量與被選中的欄位若看過測試集,測試集就參與了訓練用的設定。

切分前做 SMOTE 這類過採樣。合成樣本來自少數類樣本與其鄰居的內插;鄰居後來若落在測試集,合成樣本就與測試筆相關。

目標洩漏(target leakage):特徵其實是結果的後果。用「是否已退款」預測「是否退貨」時,退款多半出現在退貨決定之後,下單當下還沒有這個欄位。

時間洩漏(temporal leakage):用未來資料預測過去或預測當下。本週之後才發生的交易,不能拿來預測本週的違約。

同一個人的多筆資料同時出現在訓練與測試。病患、顧客都是。模型可以記住「這個人」,測試就估不到「下一個沒見過的人」。

二、切分、重採樣、特徵與上線監控

減輕過擬合

過擬合時要讓模型較難記住訓練雜訊,加特徵或加輪數通常讓過擬合更嚴重。

詳細說明

訓練遠好於驗證時,過擬合已經發生,變異偏高。改善的方向是讓模型較難記住訓練雜訊。

增加資料量之後,只存在於少數訓練筆的雜訊較難被當成穩定規律。資料擴增(data augmentation)對影像做翻轉、旋轉,標籤維持不變,畫面變化變多。正則化(regularization)的 L1、L2 懲罰過大的權重:L1 較會把一部分權重壓到零,L2 較會讓權重的平方和變小。提早停止(early stopping)在驗證表現不再變好時停下,其後只討好訓練集的輪次就不會留下。Dropout 在訓練時隨機關掉一部分單元,模型較難靠單一路徑記住特定訓練筆。減少特徵、改用較簡單的模型,直接把容量降低。交叉驗證(cross-validation)用來選超參數,選擇過程不使用測試集。

增加更多特徵,或延長訓練輪數,通常會讓過擬合更嚴重。容量變大,反覆看訓練集的次數變多,記住雜訊的機會也變多。

折怎麼切

類別比例差用分層,沒見過的人用群組,時間序列只用過去預測未來。

詳細說明

K-fold 把資料分成 K 份,輪流以其中一份當驗證集、其餘當訓練集,再綜合 K 次的驗證表現。

類別比例差很多時用分層 K-fold(Stratified K-fold)。每一折的類別比例與整體相同,驗證分數才不會因為某一折幾乎沒有少數類而跳動。

評估對象是沒見過的人時用群組 K-fold(GroupKFold)。同一群組,例如同一位病患、同一位使用者,只出現在同一側。以「筆」為單位隨機切開,守不住這件事。

時間序列用 TimeSeriesSplit。驗證段在訓練段之後,只用過去預測未來。

少數類很少的時候

全猜正常也有 99.5% 準確率,少數類卻可以一筆都沒抓到。

詳細說明

全體準確率在不平衡時會誤導。正常個案佔 99.5% 時,全部猜正常,準確率也是 99.5%,少數類可以一筆都沒抓到。

改看精確率(precision)、召回率(recall)、F1 與 PR 曲線(precision-recall curve)下面積。精確率是判成正例的筆數之中,真正屬於正例的比例。召回率是真正的正例之中,被抓到的比例。兩者合成為 F1 = 2 × 精確率 × 召回率 / (精確率 + 召回率)。PR 曲線以召回率與精確率為兩軸,曲線下面積把不同門檻下的取捨收成一個數。

類別權重(class weight)讓少數類的錯誤在訓練裡佔更重,資料筆數可以維持原樣。欠採樣(undersampling)減少多數類的筆數。過採樣(oversampling)增加少數類。SMOTE 在少數類樣本與其鄰居之間內插,產生合成樣本。重採樣只能做在訓練集,或交叉驗證的訓練折裡面。SMOTE 本身可以用,問題在位置:切分前對全體做就會洩漏。決策門檻(decision threshold)決定模型多容易把一筆判成少數類,從而更換精確率與召回率的組合。門檻若要調,放在驗證階段;用測試集反覆試到分數好看,測試集就參加了選擇。

特徵怎麼共用

共用特徵要與線上同一套計算,並取時間點正確的值。

詳細說明

特徵儲存庫(Feature Store)集中定義、計算、儲存特徵,供多個團隊與多個模型重用。風控與防弊都要「過去 30 天交易行為」時,共用同一段計算。

它對上兩種不一致。訓練/服務不一致(training-serving skew)指訓練用的特徵算法和線上推論不同,上線輸入已經偏離模型學過的數字。時間點正確(point-in-time correct)指取某一天的歷史特徵時,只用該時點之前已經存在的值,從而避開時間洩漏。

MLOps 把實驗到上線做成可重複的過程:實驗追蹤,例如 MLflow 記錄參數、指標與模型檔;模型註冊與版本;自動化訓練與部署;上線監控。監控用來發現漂移。

上線之後什麼在變

偵測到資料漂移或概念漂移,都要重新評估並重新訓練。

詳細說明

資料漂移(data drift)是輸入特徵的分佈改變,例如新客群湧入,金額、時段的分佈與訓練時不同。概念漂移(concept drift)是輸入與標籤的關係改變。特徵分佈可以差不多,同樣的特徵組合所對應的詐欺機率卻變了,因為手法變了。

偵測到其中一種,都要重新評估並重新訓練。

多台機器怎麼拆

資料量很大且模型放得進一台就資料平行,放不下才模型平行。

詳細說明

資料平行(data parallelism):每台機器持有完整模型,各自處理不同資料,再同步梯度。模型放得進一台、資料量很大時,用這種拆法。

模型平行(model parallelism):模型太大,一台放不下,把模型拆到多台機器。拆開的是模型本身。

把切分與 SMOTE 放在對的位置

SMOTE 放在 Pipeline 第一步,每次只送該折的訓練資料。

詳細說明

分層切分要能重現,群組切分要把人留在同一側,時間切分只能由過去預測未來。SMOTE 放在 imblearn.pipeline.Pipeline 的第一步,模型放在後面;交叉驗證每次擬合,只把該折的訓練資料送進 SMOTE。

from imblearn.over_sampling import SMOTE
from imblearn.pipeline import Pipeline
from sklearn.model_selection import GroupKFold, StratifiedKFold, TimeSeriesSplit

stratified = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)
grouped = GroupKFold(n_splits=5)
temporal = TimeSeriesSplit(n_splits=5)

# grouped.split(X, y, groups=patient_id): one patient stays on one side.
# temporal.split(X): validation uses a later block; training uses only earlier rows.


def make_resample_pipe(model):
    return Pipeline([
        ("smote", SMOTE()),
        ("model", model),
    ])

從資料到上線的順序

先判斷學習類型並切分,測試留到最後,上線後再看兩種漂移。

詳細說明
  1. 判斷學習類型:現成標籤、沒有標籤、環境獎勵,或從資料自身造標籤。
  2. 先切分,再做前處理、特徵選擇與重採樣。不平衡用分層,評估新的人用群組,有時間順序用 TimeSeriesSplit。
  3. 只在訓練集或訓練折上學參數,並在同一範圍內做 SMOTE、欠採樣或類別權重。
  4. 用驗證表現選模型、決定提早停止,也在這一階段調整決策門檻。測試集留到最後一次。
  5. 上線特徵走特徵儲存庫,與訓練使用同一套計算,並取時間點正確的值。
  6. 以實驗追蹤留下參數、指標與模型版本。上線後看資料漂移與概念漂移,發現了就重新評估、重新訓練。

三、容易混淆的地方

實務上常把下表左右兩種方法混在一起。先確認流程要守住的是類別比例、同一個人、時間順序,還是上線後改變的分佈或特徵與標籤間的關係。

容易混淆 差別在哪 實際遇到時的線索
驗證集 vs 測試集 驗證集用來調超參數、選模型,可以多次查看;測試集只在最後用一次,估計上線表現 評估流程看過測試分數後又改模型,表示測試集已被拿來選模型
過擬合 vs 欠擬合 過擬合是訓練好、驗證差;欠擬合是兩邊都差 訓練紀錄顯示 99%、驗證 72% 時是過擬合;兩邊都低才是欠擬合
資料漂移 vs 概念漂移 資料漂移是輸入特徵分佈改變;概念漂移是輸入與標籤的關係改變 上線監控若出現新客群湧入、特徵分佈改變,屬資料漂移;分佈變化不大、同樣特徵下的機率改變,屬概念漂移
分層 K-fold vs 群組 K-fold 分層維持每折類別比例;群組讓同一人只在同一側 驗證需求是讓極少數類別在每折維持接近整體比例時用分層;要評估新病患或新使用者時用群組
SMOTE 在切分前 vs SMOTE 在訓練折內 切分前做,合成樣本的鄰居會落到測試集;只在訓練折內做,測試折保持原樣 資料流程先對全部資料過採樣再切分,可能出現測試分數高、上線大幅下滑
資料平行 vs 模型平行 資料平行是每台都有完整模型、分不同資料、同步梯度;模型平行是模型太大、拆到多台 系統需處理大量資料而模型單台放得下時用資料平行;模型單台放不下時用模型平行

四、基礎練習

第 1 題

某銀行的信用卡違約率是 1.6%。分析師拿全部 5 萬筆先做 SMOTE,再切成訓練集與測試集。測試集 AUC 是 0.91,模型上線後表現大幅下滑。這次失敗最合理的解釋是什麼?

  • (A) AUC 這個指標本來就不可靠,所以 0.91 不能說明模型好壞
  • (B) 測試集太小,把測試集放大後,上線表現就會回到 0.91
  • (C) 切分前對全部資料做 SMOTE,合成樣本與測試樣本相關,形成資料洩漏;應先切分,只在訓練集內重採樣
  • (D) 模型欠擬合,應改用一個更簡單、故意欠擬合的模型
看答案與解析

答案:C

5 萬筆就是 50000 筆,違約筆數是 50000 × 1.6 ÷ 100 = 800。SMOTE 在這 800 筆與其鄰居之間內插出合成樣本。這一步若做在切分之前,鄰居可以落在後來的測試集,測試 AUC 0.91 是在這種相關之下量到的。上線的新案件沒有這些鄰居,分數就下滑。應先切成訓練集與測試集,只在訓練集內重採樣。

  • (A) 情境的落差對上的是合成樣本與測試樣本相關,支持不了「AUC 一律不可靠」。
  • (B) 情境沒有給出測試集太小的證據;5 萬筆是被提前做 SMOTE 的全部資料,放大測試集去不掉已經形成的相關。
  • (D) 欠擬合是訓練與驗證都差。這裡出現的是切分前重採樣,以及測試分數與上線的落差;換成更簡單的模型仍然留著那層相關。

第 2 題

某支付公司的交易裡,詐欺只佔 2%。團隊要用 5-fold 交叉驗證評估分類模型。哪一種做法對得上這個類別比例?

  • (A) 使用一般 K-fold,而且不要打亂,依原始順序切成 5 折
  • (B) 改成留一法,因為留一法一定最好
  • (C) 只報告訓練集準確率,不必在意每一折的詐欺比例
  • (D) 使用分層 K-fold,讓每一折的類別比例都與整體相同
看答案與解析

答案:D

詐欺只佔 2%。某一折的詐欺比例若偏離整體,驗證分數會跟著折跳動,模型本身穩不穩就看不清。分層 K-fold 讓每一折的類別比例相同,5 折都維持接近整體的詐欺比例。

  • (A) 這一題要守的是類別比例。一般 K-fold 即使打亂,仍不保證每折都接近 2%;「不要打亂」也不是交叉驗證的要件。
  • (B) 留一法沒有處理 2% 這個類別比例,不能當成不平衡時一定最好的切法。
  • (C) 詐欺只佔 2% 時,訓練集準確率一樣會被多數類撐高,而且它沒有使用驗證折。

第 3 題

某醫院的資料裡,每位病患有多筆住院紀錄。評估目標是模型對沒見過的新病患表現如何。切分應怎麼做?

  • (A) 以住院紀錄為單位隨機切分,讓訓練與測試的筆數都盡量大
  • (B) 使用 GroupKFold,以病患為群組,同一位病患只出現在同一側
  • (C) 使用分層 K-fold 即可,類別比例正確就完成了對新病患的評估
  • (D) 使用 TimeSeriesSplit,同一位病患的紀錄可以同時出現在訓練側與驗證側
看答案與解析

答案:B

新病患指訓練時完全沒出現過的人。GroupKFold 以病患為群組,同一群組只放在同一側,驗證折裡的人在訓練折沒有出現過,估到的才是新病患。

  • (A) 隨機逐筆切分會把同一病患的不同住院分到訓練與測試,模型可以記住這個人。
  • (C) 分層 K-fold 守的是每折類別比例,同一病患仍可出現在兩邊。
  • (D) TimeSeriesSplit 守的是只用過去預測未來;同一病患仍可跨在兩側,回答不了新病患的表現。

第 4 題

某銀行的風控團隊與防弊團隊都需要「過去 30 天交易行為」這組特徵。較合適的做法是哪一個?

  • (A) 導入特徵儲存庫,統一定義與計算,供兩邊與多個模型重用,並讓訓練與線上推論使用相同邏輯
  • (B) 兩隊各自寫一套特徵程式,保持彈性,上線前再各自核對
  • (C) 把算好的特徵存成 Excel,用檔案共享給另一隊
  • (D) 用特徵儲存庫取代模型訓練,之後只更新特徵、不再訓練模型
看答案與解析

答案:A

兩邊要的是同一段定義。特徵儲存庫集中定義、計算、儲存,讓多個團隊與模型重用同一套邏輯,訓練與線上推論才對得上,也才能取時間點正確的歷史特徵。

  • (B) 各自實作會讓同名特徵算出不同數字,訓練與上線、兩隊之間都會分叉。
  • (C) Excel 只交換檔案,沒有統一的計算邏輯,也沒有時間點正確的約束。
  • (D) 特徵儲存庫提供特徵,模型仍要在訓練集上學參數,它不取代訓練。

第 5 題

某金流公司遇到詐騙集團改變手法。同一組特徵組合所對應的詐欺機率變了,這些特徵的分佈變化不大。此時最貼近的判斷是什麼?

  • (A) 資料漂移:輸入特徵的分佈已經改變
  • (B) 過擬合:模型把舊手法的雜訊背下來了
  • (C) 概念漂移:輸入與標籤的關係改變,應重新評估並重新訓練
  • (D) 資料洩漏:訓練時用了預測當下拿不到的欄位
看答案與解析

答案:C

特徵分佈變化不大,改變的是同樣特徵組合所對應的詐欺機率,也就是輸入與標籤的關係。這是概念漂移。接下來要重新評估並重新訓練。

  • (A) 資料漂移指輸入特徵分佈改變,例如新客群湧入;情境寫的是分佈變化不大。
  • (B) 過擬合是訓練表現好、驗證表現差,情境描述的是上線後手法與機率關係改變。
  • (D) 資料洩漏是訓練時用了預測當下拿不到的資訊,情境沒有這個訓練程序。

第 6 題

某服飾電商同時用商品影像與訂單資料預測退貨。目前訓練集準確率 99%,驗證集準確率 72%。下列何者最無法改善這種過擬合?

  • (A) 對商品影像做翻轉、旋轉等資料擴增
  • (B) 加入 L1 或 L2 正則化
  • (C) 依驗證表現做提早停止
  • (D) 再加入大量新特徵,並延長訓練輪數
看答案與解析

答案:D

99 − 72 = 27,驗證比訓練低 27 個百分點:訓練好、驗證差,符合過擬合。再加入大量新特徵並延長訓練輪數,容量與看訓練集的次數都增加,通常會讓過擬合更嚴重,所以這一項最無法改善。

  • (A) 影像翻轉、旋轉是資料擴增,用來增加畫面變化、減輕過擬合。
  • (B) L1 或 L2 正則化懲罰過大的權重,用來限制擬合。
  • (C) 提早停止在驗證表現不再變好時停下,避免後續輪次繼續記住訓練集。

五、重點回顧

  • 監督式學習使用現成標籤,做分類或迴歸;非監督式學習沒有標籤,做分群或降維;強化學習的訊號是環境給的獎勵;自監督學習從資料自身造標籤,遮住字詞再預測、以及大型語言模型預訓練,都屬這一類。
  • 訓練集學參數,驗證集可以多次用來調超參數與選模型,測試集只在最後用一次以估計上線表現;會看全體資料的前處理與特徵選擇放在切分之後。
  • 訓練好、驗證差是過擬合,兩邊都差是欠擬合;模型越複雜,偏差越低、變異越高。加特徵或拉長訓練通常加重過擬合;資料擴增、L1/L2、提早停止、Dropout、減少特徵與簡化模型用來減輕它。
  • 正常佔 99.5% 時,全部猜正常也有 99.5% 的準確率。不平衡時改看精確率、召回率、F1 與 PR 曲線下面積;類別權重、欠採樣、SMOTE 與決策門檻可以處理,SMOTE 只做在訓練集或訓練折內。
  • 分層 K-fold 守每折類別比例,群組 K-fold 守同一病患或使用者只在同一側,TimeSeriesSplit 守只用過去預測未來。
  • 特徵儲存庫統一特徵計算,避開訓練/服務不一致,並提供時間點正確的歷史特徵。輸入分佈改變是資料漂移,輸入與標籤的關係改變是概念漂移;偵測到之後要重新評估與重新訓練。

覺得有幫助? RSS · X · 請我喝杯咖啡

編號 1 到 10 裡,前段 6 格是訓練、接著 2 格驗證、最後 2 格測試。

訓練、驗證、測試各有工作
1 / 4
10 格切成三份
10 格示意切分:6 格訓練、2 格驗證、2 格測試;測試集留到最後估計表現。數值為示意。
  1. 6 格訓練、2 格驗證、2 格測試只是示意比例;重點是三份各有不同的工作。
  2. 參數只在這些筆上擬合。
  3. 超參數與要比較的模型都在這裡挑選,可以反覆看。
  4. 它只估計上線表現,不參加選模型。看過分數再回頭改模型,這個數字就不再是未參與選擇的估計。

散點給出示意資料,三條曲線分別太直、適中、以及追著雜訊。

模型太簡單會欠擬合,太彎會過擬合
1 / 4
散點把示意資料標出來
欠擬合抓不到規律;過擬合追著訓練雜訊跑。資料與曲線為示意。
  1. 後續曲線都在擬合這些點,彎多少決定抓到的是規律還是雜訊。
  2. 模型太簡單,訓練集裡的規律也沒有抓到。訓練與驗證都差,表示偏差仍然偏高。
  3. 這條曲線取中間:模型較能跟上彎曲的關係,偏差與變異在這裡權衡。
  4. 訓練表現好、驗證表現差,是因為雜訊也被記進去。換一批資料就對不上,變異已經偏高。

五種常見的洩漏來源:訓練時用到了預測當下拿不到的資訊。

訓練不能看到預測時未知的資訊
1 / 5
第 1 種:切分前的前處理
洩漏可能來自切分前處理、切分前 SMOTE、結果後果欄位、未來資料或同人跨集合。
  1. 統計量與被選中的欄位若看過測試集,測試集就參與了訓練用的設定。
  2. 合成樣本來自少數類樣本與其鄰居的內插。鄰居後來若落在測試集,合成樣本就與測試筆相關。
  3. 這種特徵其實是結果的後果。用是否已退款預測是否退貨時,退款多半出現在退貨決定之後,下單當下還沒有這個欄位。
  4. 用未來資料預測過去或預測當下都不可以。本週之後才發生的交易,不能拿來預測本週的違約。
  5. 病患或顧客的多筆若同時出現在訓練與測試,模型可以記住這個人,測試就估不到下一個沒見過的人。

表頭列出折 1 到折 5,每一列只把一格換成驗證。

K-fold 輪流留一折驗證
1 / 3
第 1 輪以折 1 驗證
每一輪輪換一折作驗證,其餘四折作訓練;格子為示意。
  1. K-fold 把資料分成 K 份,這裡是 5 份;其餘四折當訓練集。
  2. 上一輪的驗證折回到訓練集,不會永遠用同一份來看表現。
  3. 五輪走完,每一折都當過一次驗證集,再綜合 K 次的驗證表現。

類別占比這一畫面裡,正常是 0.995,少數類是 0.005。

全猜多數類仍有 99.5% 準確率
1 / 2
切到畫面,正常 0.995、少數類 0.005
正常個案占 99.5% 時,全猜正常也有 99.5% 準確率,卻可能一個少數類都抓不到。
  1. 這兩根長條是類別占比。正常個案佔 99.5% 時,全體準確率在這種不平衡下會誤導。
  2. 若全部猜成正常,準確率也是 99.5%,少數類可以一筆都沒抓到。所以不平衡時不要只看全體準確率。