在機器學習模型開發流程中,驗證階段至關重要,它直接影響模型的泛化能力和實際應用效果。驗證的核心目標是評估模型在未見資料上的預測能力,選擇可靠且穩健的模型。除了標準的留出法和交叉驗證,針對不同資料特性,例如時間序列資料,需要採用特定的驗證方法,例如滾動交叉驗證。此外,理解驗證集的規模、訓練集大小、資料的季節性以及間隔設定等因素,都有助於更準確地評估模型效能。

7.1 可靠的評估

驗證的主要目標是提供對系統效能的可靠且穩健的估計,理想情況下還應具備一定的理論保證。例如,我們可以保證真實值在95%的情況下會落在下置信界限和上置信界限之間(Valerii稍後將在章節中的一個營火故事中介紹這種情況)。驗證還有助於檢測和防止資料洩漏、過擬合以及離線和線上效能之間的差異。

效能估計是驗證的主要目標。我們使用驗證來估計模型在未見資料上的預測能力,通常首選的模式是具有最高可靠性和穩健性(即低偏差/低變異數)的模式。只要我們有可靠和穩健的效能估計,我們就可以將其用於各種用途,例如超引數最佳化、架構選擇、演算法選擇和特徵選擇。在一定程度上,這與A/B測試相似,其中產生較低變異數的模式提供更高的靈敏度,我們將在本章後面討論這一點。

建立可靠的驗證流程

在驗證任何事物時,建立一個穩定且可靠的流程以產生可重複的結果幾乎總是一個好主意(參見圖7.1)。文獻中常見的標準建議歸結為以下三個經典條件:將資料分成訓練集、驗證集和測試集。訓練集用於模型訓練,驗證集用於在訓練過程中評估效能,測試集用於計算最終指標。

需要注意的事項

  • 簡單的訓練-驗證-測試分割假設所有三個資料集都來自相同的分佈,並且這種情況在未來仍然成立。這是一個需要被驗證的強假設。如果這個假設不成立,那麼對未來效能就沒有任何保證。
  • 必須重複使用驗證集來估計模型的效能。根據驗證集過度估計模型的效能會導致偏差和過擬合。停止並思考:當我們談論超引數最佳化、特徵選擇或模型選擇等事情時,從高層次的角度來看,這基本上也是學習過程的一部分。透過歸納,測試集也可能以相同的方式被濫用。

因此,反覆使用相同的驗證分割進行評估和搜尋最佳超引數或任何其他事情,都會導致有偏差/過擬合和不穩健的結果。因此,我們不是將驗證視為一開始就做一次的事情,而是將其視為一個連續的過程,一旦系統的上下文發生變化(例如,有新的資料來源、新的特徵、由模型使用引起的潛在回饋環等),就需要重複進行。

7.2 標準模式

實踐表明,在為機器學習系統選擇驗證模式時,無需重新發明輪子。大多數標準模式都是經過時間考驗且表現良好的解決方案,主要需要選擇一個符合專案需求的模式。我們將在幾個小節中簡要介紹這些模式。

7.2.1 留出法

首先,我們將資料集分成兩個或更多塊。大概在幾乎所有有關機器學習的書中都提到的黃金經典方法是我們之前討論過的訓練/驗證/測試分割。

使用這種方法,我們將資料分成三個集合(可能是隨機的,也可能根據特定的標準或層),具有不同的比例——例如,60/20/20(參見圖7.2)。百分比可能會根據樣本數量和指標(資料量、指標變異數、靈敏度、穩健性和可靠性要求)而有所不同。經驗上,整個資料集越大,分配給驗證和測試的比例越小,因此訓練集的增長速度更快。測試集(即外部驗證)用於最終的模型評估,不應被用於任何其他目的。同時,我們可以使用驗證集(即內部驗證)主要用於模型比較或調整超引數。

此圖示展示了標準的資料分割方法,將可用資料分成訓練集、驗證集和測試集。

內容解密:

  1. 資料分割是機器學習模型開發中的關鍵步驟。
  2. 訓練集用於模型的初始訓練。
  3. 驗證集用於在訓練過程中評估模型效能,並進行超引數調整。
  4. 測試集用於最終評估模型的效能,不應在訓練或驗證過程中使用。

7.2.2 交叉驗證

留出法驗證是計算成本高昂的模型(如深度學習模型)的一個不錯選擇。它易於實作,並且不會為學習迴圈增加太多時間。

但我們要記住,我們只是從所有資料中抽取一個單一的隨機子樣本。我們沒有重複使用所有可用的資料,這可能會導致評估有偏差或未充分利用可用資料。最糟糕的是,我們得到的是一個單一的數字,這無法讓我們瞭解估計值的分佈。

解決這個問題的統計學上的銀彈是自助法。在驗證案例中,它看起來像是多次隨機抽樣訓練驗證分割,每次迭代都訓練和評估模型。訓練模型非常耗時,我們希望能夠快速迭代以進行一般引數調整和實驗。那麼,我們該怎麼做呢?

我們可以使用一個類別似但簡化了的抽樣程式,稱為交叉驗證。我們可以將資料分成K個折疊(通常是五個),每次排除其中一個折疊,將模型擬合到K-1個折疊的資料上,並在被排除的折疊上衡量效能。因此,我們得到K個估計值,並可以計算它們的平均值和標準差。結果,我們得到五個數字而不是一個,這更具代表性(參見圖7.3)。

此圖示展示了K折交叉驗證的過程,將資料分成K個折疊,每次使用K-1個折疊進行訓練,並在剩餘的一個折疊上進行評估。

內容解密:

  1. 交叉驗證是一種統計方法,用於評估模型的效能。
  2. 它透過將資料分成多個折疊,並輪流使用每個折疊作為測試集來進行。
  3. 這種方法可以提供多個效能估計值,從而計算出平均效能和其變異數。
  4. 與留出法相比,交叉驗證能夠更充分地利用可用資料,提供更穩健的效能估計。

驗證模式的選擇與應用

在機器學習領域中,驗證模式(Validation Schema)的選擇對於模型的評估和最佳化至關重要。不同的驗證模式會對模型的效能評估產生不同的影響,因此,瞭解各種驗證模式的特點和適用場景對於建立穩健的機器學習模型是必不可少的。

交叉驗證的多種變體

交叉驗證(Cross-Validation)是一種常見的驗證模式,旨在透過將資料集分成多個子集來評估模型的效能。其中,每個子集都會被用作一次驗證集,而剩下的子集則被用作訓練集。交叉驗證有多種變體,包括:

  • 分層交叉驗證(Stratified Cross-Validation):這種方法確保了每個類別在訓練集和驗證集中的比例保持一致,特別適用於類別不平衡的資料集。
  • 重複交叉驗證(Repeated Cross-Validation):透過多次重複交叉驗證過程,可以提高評估的穩定性和可靠性。
  • 分組交叉驗證(Grouped Cross-Validation):當資料集中存在相關性較高的樣本組時,分組交叉驗證可以確保同一個組內的樣本不會同時出現在訓練集和驗證集中,從而避免過度樂觀的評估結果。

選擇適當的K值

在K折交叉驗證中,K值的選擇對於評估結果有著重要的影響。K值的選擇需要考慮偏差(Bias)、方差(Variance)和計算時間三個因素。一般來說,K=5是一個常見的選擇,因為它在偏差和方差之間取得了較好的平衡。

留一法交叉驗證

當K等於資料集的大小時,就變成了留一法交叉驗證(Leave-One-Out Cross-Validation)。這種方法的偏差最小,但計算成本高,且方差較大。

根據Ron Kohavi在1995年的研究,增加K值可以減少偏差,但同時也會增加方差。使用K=2或K=3的重複交叉驗證進行模型比較是一個好的選擇,但對於偏差最佳化,重複K折交叉驗證並不是非常有效。

時間序列資料的驗證

對於時間序列資料,不能隨機抽樣,因為鄰近時間點的資料往往具有相關性。時間序列驗證需要考慮時間戳的順序,通常使用滾動交叉驗證(Rolling Cross-Validation)或其變體。

時間序列驗證的額外考慮因素

  • 視窗大小:測試集的大小應該反映預測的時間範圍和模型在生產環境中重新訓練前的執行時間。
  • 訓練集大小:可以使用所有可用的歷史資料進行訓練,也可以限制訓練集的大小到前一或兩個週期。
  • 季節性:資料中可能存在按天、周、月、季度或年為週期的模式。選擇測試集和訓練集的大小時應考慮這些模式。
  • 間隔:在訓練集和測試集之間設定間隔,可以減少資料洩露的風險,並考慮到新資料的延遲。

雖然簡單的時間序列驗證規則可以避免大多數常見錯誤,但在某些情況下,如金融資料分析,可能需要違反這一規則以應對特定的挑戰,如過擬合或異常情況下的模型效能評估。

驗證模式的進階探討

在機器學習(ML)應用中,驗證模式的選擇對於模型的評估和最佳化至關重要。標準的驗證模式,如時間序列驗證和分組K折交叉驗證,在大多數情況下都能發揮作用,但在某些特定場景下,可能需要採用更為複雜和非傳統的驗證策略。

結合多種驗證模式

在某些情況下,單一的驗證模式可能不足以滿足需求。例如,在流量預測問題中,可以結合分組K折交叉驗證和時間序列驗證。

程式碼範例:分組時間序列K折交叉驗證

import numpy as np
from sklearn.model_selection import GroupKFold
from sklearn.exceptions import NotFittedError

def grouped_time_series_kfold(model, X, y, groups, n_folds=5, n_repeats=10, seed=0):
    scores = []
    np.random.seed(seed)
    unique_groups = np.unique(groups)
    
    for i in range(n_repeats):
        gkf = GroupKFold(n_splits=n_folds)
        shuffled_groups = np.random.permutation(unique_groups)
        
        for train_group_idx, test_group_idx in gkf.split(X, y, groups=shuffled_groups):
            train_groups = shuffled_groups[train_group_idx]
            test_groups = shuffled_groups[test_group_idx]
            
            # 找出訓練集和測試集的最早和最晚索引
            train_indices = np.where(np.isin(groups, train_groups))[0]
            test_indices = np.where(np.isin(groups, test_groups))[0]
            train_end = np.min(test_indices)
            
            # 確保時間順序
            train_mask = np.isin(groups, train_groups) & (np.arange(len(groups)) < train_end)
            test_mask = np.isin(groups, test_groups)
            
            model.fit(X[train_mask], y[train_mask])
            score = model.score(X[test_mask], y[test_mask])
            scores.append(score)
    
    return np.array(scores)

內容解密:

  1. grouped_time_series_kfold函式:結合分組K折交叉驗證和時間序列驗證,適用於需要按組別劃分資料並保持時間順序的場景。
  2. GroupKFold類別:用於實作分組K折交叉驗證,確保不同組別的資料在不同的折中。
  3. np.random.permutation:隨機打亂組別順序,增加驗證的魯棒性。
  4. train_masktest_mask:確保訓練集的時間早於測試集,符合時間序列驗證的要求。
  5. model.fitmodel.score:對訓練集進行模型訓練,並在測試集上評估模型效能。

非傳統驗證模式

在某些特殊情況下,傳統的驗證模式可能不足以反映真實的模型效能。例如,在動態定價服務中,由於產品種類別和銷量的異質性,簡單的時間序列驗證可能導致評估指標的波動。

案例分析:延遲偏移驗證

在一個大型線上零售商的銷售預測專案中,初始的驗證策略是每天更新驗證集。然而,由於產品種類別和銷量動態的高度異質性,模型的評估指標出現了顯著的波動。為瞭解決這一問題,團隊採用了“延遲偏移”驗證策略,即每月更新一次驗證集,同時保持驗證集的時間範圍為一週。這個策略減少了評估指標的噪音,使得模型效能的比較更加有意義。

巢狀驗證

巢狀驗證是一種在模型選擇過程中進行超引數最佳化的有效方法。它透過在外部迴圈中進行模型評估,在內部迴圈中進行超引數調優,避免了對測試集的過度擬合。

巢狀驗證的工作原理

  1. 外部迴圈:將資料集分成訓練集和測試集,用於評估模型的最終效能。
  2. 內部迴圈:在訓練集中再次進行劃分,用於超引數調優。
  3. 超引數調優:在內部迴圈中選擇最優的超引陣列合。
  4. 模型評估:使用選定的超引數在外部迴圈的測試集上進行模型評估。

巢狀驗證可以應用於不同的驗證模式,如交叉驗證、時間序列驗證等,並且可以根據具體需求調整內外部迴圈的劃分方式。

驗證機制的進階策略與動態更新方法

在機器學習模型的開發過程中,驗證機制扮演著至關重要的角色。傳統的驗證方法,如簡單的留出法(holdout validation),在某些情況下可能不足以評估模型的真實效能。本章將探討幾種非傳統的驗證機制,包括對抗驗證(adversarial validation)、資料集洩漏量化(quantifying dataset leakage exploitation),以及動態更新驗證集的策略。

對抗驗證:評估資料集代表性的新方法

對抗驗證是一種在機器學習競賽中廣泛使用的技術,尤其是在Kaggle等平台上。它透過訓練一個輔助模型來評估兩個資料集之間的差異,從而判斷它們是否來自相同的分佈。

對抗驗證的基本步驟

  1. 合併資料集:將感興趣的資料集合併,並標記其中一個資料集(通常是我們想要代表的資料集)為1,其他資料集為0。
  2. 訓練輔助模型:在合併後的資料集上訓練一個二元分類別模型,以區分不同的資料集。
  3. 評估模型效能:如果兩個資料集來自相同的分佈,模型的接收者操作特徵曲線下面積(ROC AUC)應該接近0.5。如果ROC AUC大於0.6,則表明資料集之間存在可分離性,可以使用模型的輸出作為接近程度的衡量指標。

對抗驗證不僅能夠評估資料集之間的相似性,還能找出導致差異的關鍵特徵,為模型的改進提供方向。

量化資料集洩漏:提升語言模型的魯棒性

資料集洩漏是指模型在訓練過程中記憶了訓練資料的某些部分,導致在驗證或測試時出現異常高的效能。DeepMind的研究人員提出了一種量化資料集洩漏的方法,並用於提升語言模型的效能。

量化資料集洩漏的步驟

  1. 分割資料集:將資料集分割為訓練集和驗證集。
  2. 分塊處理:將訓練集和驗證集分成固定長度的區塊。
  3. 計算相似度:對於驗證集中的每個區塊,從訓練集中檢索出最相似的N個鄰居,並計算區塊之間的Jaccard相似度。
  4. 過濾重複內容:如果相似度超過某個閾值,則從訓練集中過濾掉該區塊,以避免模型簡單地複製訓練資料。

這種方法迫使模型從相似文字中檢索有用的資訊並進行改寫,而不是簡單地複製貼上,從而提高了模型的魯棒性和泛化能力。

動態更新驗證集:保持評估的相關性

在實際應用中,資料的分佈可能會隨著時間而變化,因此需要定期更新驗證集以保持評估的相關性。

常見的更新策略

  1. 固定偏移(Fixed Shift):適用於具有強烈時間依賴性的資料,如每天更新最近兩週的資料作為驗證集。

    1. 固定比例(Fixed Ratio):適用於沒有強烈時間依賴性的資料,如保持訓練集與驗證集的比例不變,將新資料按比例分配到訓練集和驗證集中。

@startuml skinparam backgroundColor #FEFEFE skinparam componentStyle rectangle

title 機器學習模型驗證方法與穩健性評估

package “標準驗證模式” { component [留出法\nHold-out] as holdout component [K折交叉驗證\nK-Fold CV] as kfold component [自助法\nBootstrap] as boot }

package “資料分割策略” { component [訓練集 60%] as train component [驗證集 20%] as val component [測試集 20%] as test }

package “進階驗證方法” { component [滾動交叉驗證\n時序資料] as rolling component [對抗驗證\nAdversarial] as adv component [資料洩漏量化] as leak }

package “穩健性評估” { component [信賴區間\nConfidence Interval] as ci component [低偏差/低變異] as bias component [過擬合檢測] as overfit }

holdout –> train holdout –> val holdout –> test

kfold –> rolling boot –> ci

train –> bias val –> overfit test –> ci

note right of holdout : 黃金經典方法\n分佈假設需驗證 note bottom of rolling : 適用時間序列\n保持時間順序 @enduml

note right of eval 評估指標:

  • 準確率/召回率
  • F1 Score
  • AUC-ROC end note

@enduml


3. **固定集合(Fixed Set)**:保持驗證集不變,但這種方法可能無法反映模型的最新效能。

#### 內容解密:
- 固定偏移和固定比例是兩種常見的動態更新策略,前者適用於時間序列資料,後者適用於無明顯時間依賴的資料。
- 動態更新驗證集能夠確保模型的評估始終保持相關性和準確性。

## 驗證模型的穩健性:超越點估計

在機器學習模型的開發過程中,驗證模型的效能是一個至關重要的步驟。傳統上,我們依賴點估計來評估模型在驗證集上的表現。然而,這種方法存在著一定的侷限性,因為它無法考慮到評估過程中的不確定性。為了更全面地瞭解模型的效能,我們需要引入穩健的評估方法。

### 點估計的侷限性

點估計僅僅提供了一個單一的數值來描述模型的效能,例如精確率或召回率。然而,這種單一的數值無法反映評估過程中的變異性或不確定性。就像擲一枚公平的硬幣100次,我們得到的正面次數是一個點估計,但如果重複這個過程,我們可能會得到不同的結果。

#### 以擲硬幣為例

如果我們擲一枚公平的硬幣100次,我們可以計算出正面出現的次數。這是一個點估計。如果我們重複這個過程,我們會得到另一個數字。與其依賴單一的點估計,我們可以使用信賴區間來表達我們的評估結果。例如,我們可以說,在95%的情況下,正面出現的次數會落在40到60之間。

### 使用信賴區間提升穩健性

為了克服點估計的侷限性,我們可以使用信賴區間來評估模型的效能。信賴區間提供了一個範圍,讓我們能夠以一定的信心水平(例如95%)斷言真實的模型效能會落在這個範圍內。

#### 圖表說明

在實際應用中,我們可以透過自助法(bootstrap)來估計模型的效能分佈。自助法是一種透過重複抽樣原始資料集來模擬不同場景的方法。下面的圖表展示了使用自助法估計召回率的分佈,其中紅線代表99%的下限信賴界限。

此圖示展示了召回率的分佈情況,每個點代表一個透過自助法生成的資料集,紅線是99%的下限信賴界限。

### 考慮閾值的不確定性

在某些情況下,模型的效能指標(如精確率和召回率)取決於我們選擇的閾值。下面的圖表展示了在不同閾值下,精確率和召回率的分佈情況。

#### 圖表分析

這些圖表顯示了在原始資料和新增少量雜訊後的資料上,精確率和召回率的分佈情況。結果表明,新增雜訊後,模型的召回率提高,但精確率下降。這意味著模型的決策邊界可能較為狹窄,缺乏穩健性。

此圖示展示了精確率和召回率在不同閾值下的分佈情況,分別對應原始資料和新增雜訊後的資料。

### 實踐中的解決方案

在實際應用中,我們可以透過以下方法來提升模型評估的穩健性:

1. **使用自助法估計模型效能的分佈**:這可以幫助我們瞭解模型效能的不確定性。
2. **考慮閾值的不確定性**:透過分析不同閾值下的模型效能,我們可以更好地理解模型的行為。
3. **使用信賴區間進行模型比較**:這可以幫助我們更穩健地比較不同模型的效能。