本章內容
5.1 混淆矩陣與分類指標
5.2 交叉驗證
5.3 偏誤-變異分解
5.4 集成學習:Bagging
5.5 集成學習:Boosting
5.6 參考資料
模型訓練完成後,第一個問題是「它到底好不好」。這個問題比看起來複雜:同一個模型,換一個評估指標,可能從優秀變成堪用;同一個指標,換一種切分資料的方式,估計出來的誤差也可能差很多。
這一章先整理分類問題的評估指標與交叉驗證,再用偏誤-變異分解說明誤差從何而來,最後介紹兩類從「組合多個模型」下手的集成學習(ensemble learning)方法:主要降低變異的 Bagging,與主要降低偏誤的 Boosting。
5.1 混淆矩陣與分類指標Confusion Matrix & Classification Metrics
評估指標就像考試的評分標準。同一張考卷,評分標準不同,分數的意義也不同;有時候拿到 100 分,並不代表每一題都答對,可能只是加分題補回了失分。因此在解讀任何一個數字之前,都要先弄清楚它是「以什麼為分母」算出來的。
以二元分類為例,把「正確解答」(實際類別)與「預測結果」交叉排列,就得到混淆矩陣(confusion matrix)的四個格子:
真陽性(True Positive, TP):答案為 1,預測也為 1。
假陽性(False Positive, FP):答案為 0,卻預測為 1,又稱第一型錯誤。
假陰性(False Negative, FN):答案為 1,卻預測為 0,又稱第二型錯誤。
真陰性(True Negative, TN):答案為 0,預測也為 0。
實際值 Ground truth 以預測結果為分母
正(1) 負(0)
預測值Prediction 正(1)
真陽性 TP True positive
假陽性 FP 第一型錯誤
精確率 Precision TP / (TP + FP)
負(0)
假陰性 FN 第二型錯誤
真陰性 TN True negative
陰性預測值 NPV TN / (TN + FN)
以實際值為分母
召回率 Recall Sensitivity・TPR TP / (TP + FN)
特異度 Specificity Selectivity・TNR TN / (TN + FP)
準確率 Accuracy (TP + TN) / 全部
圖 5.1 混淆矩陣與常用指標。深色格是預測正確的情形;指標依分母不同,分成「以實際值為分母」與「以預測結果為分母」兩組。
所有分類指標都是這四個數字之間的比例,差別只在分母。
以「正確解答」為分母
固定實際類別,問模型在這一群資料裡答對了多少:
Recall = TPR = T P T P + F N Specificity = TNR = T N T N + F P
\begin{aligned}
\text{Recall} = \text{TPR} &= \frac{TP}{TP + FN} \\
\text{Specificity} = \text{TNR} &= \frac{TN}{TN + FP}
\end{aligned}
Recall = TPR Specificity = TNR = TP + FN TP = TN + FP TN
召回率(recall),又稱敏感度(sensitivity)或真陽性率(True Positive Rate, TPR):答案為 1 的情況下,答對的比例。
特異度(specificity),又稱選擇性(selectivity)或真陰性率(True Negative Rate, TNR):答案為 0 的情況下,答對的比例。
兩者的補數就是兩種錯誤率:假陰性率 FNR = F N / ( T P + F N ) = 1 − TPR \text{FNR} = FN/(TP+FN) = 1 - \text{TPR} FNR = FN / ( TP + FN ) = 1 − TPR ,以及假陽性率 FPR = F P / ( F P + T N ) = 1 − TNR \text{FPR} = FP/(FP+TN) = 1 - \text{TNR} FPR = FP / ( FP + TN ) = 1 − TNR 。
以「預測結果」為分母
固定模型的預測,問模型說「是」(或「不是」)的時候有多可信:
Precision = PPV = T P T P + F P NPV = T N T N + F N
\begin{aligned}
\text{Precision} = \text{PPV} &= \frac{TP}{TP + FP} \\
\text{NPV} &= \frac{TN}{TN + FN}
\end{aligned}
Precision = PPV NPV = TP + FP TP = TN + FN TN
精確率(precision),又稱陽性預測值(Positive Predictive Value, PPV):預測為 1 的情況下,答對的比例。
陰性預測值(Negative Predictive Value, NPV):預測為 0 的情況下,答對的比例。
對應的補數是錯誤發現率(False Discovery Rate)FDR = F P / ( T P + F P ) = 1 − PPV \text{FDR} = FP/(TP+FP) = 1 - \text{PPV} FDR = FP / ( TP + FP ) = 1 − PPV ,以及錯誤遺漏率(False Omission Rate)FOR = F N / ( T N + F N ) = 1 − NPV \text{FOR} = FN/(TN+FN) = 1 - \text{NPV} FOR = FN / ( TN + FN ) = 1 − NPV 。
以「全部資料」為分母與綜合指標
準確率(accuracy)可以想成整張考卷的總得分:
Accuracy = T P + T N T P + T N + F P + F N
\text{Accuracy} = \frac{TP + TN}{TP + TN + FP + FN}
Accuracy = TP + TN + FP + FN TP + TN F1 分數(F1 score)是精確率與召回率的調和平均數(harmonic mean):
F 1 = 2 ( Precision − 1 + Recall − 1 ) − 1 = 2 ⋅ Precision ⋅ Recall Precision + Recall = 2 T P 2 T P + F P + F N
F_1 = 2\left(\text{Precision}^{-1} + \text{Recall}^{-1}\right)^{-1} = \frac{2 \cdot \text{Precision} \cdot \text{Recall}}{\text{Precision} + \text{Recall}} = \frac{2\,TP}{2\,TP + FP + FN}
F 1 = 2 ( Precision − 1 + Recall − 1 ) − 1 = Precision + Recall 2 ⋅ Precision ⋅ Recall = 2 TP + FP + FN 2 TP 調和平均數會被較小的一項拉低:精確率 1.0、召回率 0.1 時,算術平均是 0.55,F1 卻只有約 0.18。因此只有兩者都不差,F1 才會高。答案的分布不平均時,建議使用 F1 而不是準確率;若兩種錯誤的代價不同,可以改用 F β = ( 1 + β 2 ) P R / ( β 2 P + R ) F_\beta = (1+\beta^2)\,PR/(\beta^2 P + R) F β = ( 1 + β 2 ) PR / ( β 2 P + R ) (P P P 、R R R 分別為精確率與召回率),β > 1 \beta > 1 β > 1 時更重視召回率。F1 這類單一數字的指標能加快模型比較與迭代,用法見第 1 章 。
醫學檢驗常用的診斷勝算比(diagnostic odds ratio, DOR)則把四個比率合成一個數字:
DOR = TPR × TNR FPR × FNR = T P ⋅ T N F P ⋅ F N
\text{DOR} = \frac{\text{TPR} \times \text{TNR}}{\text{FPR} \times \text{FNR}} = \frac{TP \cdot TN}{FP \cdot FN}
DOR = FPR × FNR TPR × TNR = FP ⋅ FN TP ⋅ TN DOR 等於 1 代表檢驗毫無鑑別力,越大越好,而且不受陽性比例(盛行率)影響。
門檻與精確率-召回率的取捨
多數分類器輸出的是分數或機率 p ^ \hat p p ^ ,再用門檻 τ \tau τ 判定:p ^ ≥ τ \hat p \ge \tau p ^ ≥ τ 就預測為 1。門檻不是模型的一部分,而是可以依需求調整的決策:
提高門檻 :模型只在很有把握時才說「是」,假陽性減少,精確率通常上升;但漏掉的正例變多,召回率下降。
降低門檻 :抓到更多正例,召回率上升,代價是更多誤報,精確率下降。
該偏向哪一端,取決於兩種錯誤的成本。癌症篩檢、詐欺偵測漏掉一個正例的代價很高,傾向高召回率;垃圾郵件過濾把正常信件丟進垃圾桶的代價較高,傾向高精確率。門檻應該在開發集上決定,不要拿測試集來調整。
類別不平衡
類別不平衡(class imbalance)時,準確率會嚴重誤導。若 1,000 筆交易中只有 10 筆是詐欺,一個永遠預測「正常」的模型準確率高達 99%,召回率卻是 0,這正是「100 分不代表全部答對」的典型例子。常見的處理方式有:改看精確率、召回率、F1 或精確率-召回率曲線;訓練時給少數類別較高的權重(class weight),或重新抽樣(少數類別過採樣、多數類別欠採樣);切分資料時使用分層抽樣(stratified sampling),讓各份資料的類別比例一致。
ROC 曲線與 AUC
把門檻從 1 逐漸降到 0,每個門檻都得到一組 ( FPR , TPR ) (\text{FPR}, \text{TPR}) ( FPR , TPR ) ,連起來就是 ROC 曲線(Receiver Operating Characteristic curve)。曲線下面積 AUC(Area Under the Curve)介於 0 到 1:隨機猜測對應對角線,AUC 為 0.5;完美分類器為 1。AUC 有一個直觀的解釋:隨機抽一個正例與一個負例,模型給正例較高分數的機率。
AUC 與門檻無關,適合比較模型整體的排序能力。但 FPR 的分母是數量龐大的負例,類別極度不平衡時,即使誤報不少,FPR 依然很小,ROC 曲線會顯得過度樂觀;這時精確率-召回率曲線(PR curve)通常更有參考價值。
交並比(IoU)
物件偵測(object detection)預測的是一個框,而不只是一個類別。判斷「這個框算不算對」的標準是交並比(Intersection over Union, IoU):
IoU = ∣ A ∩ B ∣ ∣ A ∪ B ∣
\text{IoU} = \frac{\lvert A \cap B \rvert}{\lvert A \cup B \rvert}
IoU = ∣ A ∪ B ∣ ∣ A ∩ B ∣ 其中 A A A 是預測框、B B B 是真實框(ground truth)。IoU 介於 0 到 1,常以 IoU ≥ 0.5 \text{IoU} \ge 0.5 IoU ≥ 0.5 視為正確偵測並計入 TP,之後就能照樣計算精確率與召回率。IoU 在非極大值抑制(non-max suppression)等偵測流程中的用法,請見第 10 章 。
5.2 交叉驗證Cross-Validation
估計測試誤差最直接的方法,是留下一份模型沒看過的資料來評估。資料量大時,一個夠大的開發集就足夠(見第 1 章 );資料量小時,留出的那一份會讓訓練資料變得更少,估計值也很不穩定,這時交叉驗證(cross-validation, CV)是更好的選擇。
驗證集方法
把資料隨機切成訓練集與驗證集(validation set),只訓練並評估一次。做法簡單,但有兩個缺點:一是估計值高度依賴這一次怎麼切,換個隨機種子結果可能差很多(變異大);二是模型只用部分資料訓練,表現通常比用全部資料差,因此會高估測試誤差。
留一交叉驗證(LOOCV)
每次只留下 1 筆資料作為驗證,用其餘 n − 1 n-1 n − 1 筆訓練,重複 n n n 次讓每一筆都輪過,再取平均:
CV ( n ) = 1 n ∑ i = 1 n Err i
\text{CV}_{(n)} = \frac{1}{n}\sum_{i=1}^{n} \text{Err}_i
CV ( n ) = n 1 i = 1 ∑ n Err i 其中 Err i \text{Err}_i Err i 是第 i i i 筆的誤差,例如迴歸問題的 ( y i − y ^ i ( − i ) ) 2 \big(y_i - \hat y_i^{(-i)}\big)^2 ( y i − y ^ i ( − i ) ) 2 ,y ^ i ( − i ) \hat y_i^{(-i)} y ^ i ( − i ) 是不含第 i i i 筆資料所訓練出的模型的預測。
偏誤 :每次用 n − 1 n-1 n − 1 筆訓練,幾乎等於全部資料,所以對測試誤差的估計幾乎不偏。
變異 :n n n 個模型的訓練集幾乎完全相同,預測高度相關,平均高度相關的數字無法有效抵銷波動,因此估計值的變異大。
成本 :需要訓練 n n n 次。例外是最小平方線性迴歸(及其他線性平滑器),只要擬合一次就能用捷徑公式算出:
CV ( n ) = 1 n ∑ i = 1 n ( y i − y ^ i 1 − h i ) 2
\text{CV}_{(n)} = \frac{1}{n}\sum_{i=1}^{n}\left(\frac{y_i - \hat y_i}{1 - h_i}\right)^2
CV ( n ) = n 1 i = 1 ∑ n ( 1 − h i y i − y ^ i ) 2 其中 y ^ i \hat y_i y ^ i 是用全部資料擬合的預測值,h i h_i h i 是第 i i i 筆的槓桿值(leverage),即帽子矩陣的對角元素。
K 折交叉驗證(K-fold CV)
把資料隨機分成 K K K 份(fold),輪流以其中一份作為驗證、其餘 K − 1 K-1 K − 1 份訓練,共訓練 K K K 次後平均:
CV ( K ) = 1 K ∑ k = 1 K Err k
\text{CV}_{(K)} = \frac{1}{K}\sum_{k=1}^{K}\text{Err}_k
CV ( K ) = K 1 k = 1 ∑ K Err k LOOCV 就是 K = n K = n K = n 的特例。實務上常用 K = 5 K = 5 K = 5 或 10 10 10 :每次只用 ( K − 1 ) / K (K-1)/K ( K − 1 ) / K 的資料訓練,模型略差,估計值帶有些微向上的偏誤(略為高估測試誤差);但 K K K 個模型的訓練集重疊較少,估計值的變異較低,而且只需訓練 K K K 次。經驗上這兩個 K K K 值在偏誤與變異之間取得了不錯的平衡。分類問題建議使用分層 K 折(stratified K-fold),讓每一折的類別比例與整體一致。
常見誤區Common pitfall
LOOCV 與 K 折交叉驗證都不是「完全不偏」的估計:LOOCV 幾乎不偏但變異大、計算昂貴;K 折略為高估誤差,但變異較小。另一個常見錯誤,是在交叉驗證之外先做特徵選擇或標準化。所有會用到資料分布或標籤的前處理,都必須放在每一折的訓練流程之內,否則驗證資料的資訊會洩漏進模型,得到過度樂觀的誤差。
把前處理與模型包成一條 pipeline,就能確保每一折都只用該折的訓練資料計算標準化參數:
from sklearn.model_selection import StratifiedKFold, cross_val_score
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
model = make_pipeline(StandardScaler(), LogisticRegression())
cv = StratifiedKFold(n_splits=5, shuffle=True, random_state=0)
scores = cross_val_score(model, X, y, cv=cv, scoring="f1")
print(scores.mean(), scores.std())
5.3 偏誤-變異分解Bias–Variance Decomposition
建模的目標是讓總誤差最小。偏誤-變異分解把模型的期望測試誤差拆成三個來源,說明為什麼「更複雜的模型」不一定更好。實務上如何以訓練集與開發集誤差診斷這兩個問題,請見第 1 章 。
設定
假設真實世界中,y y y 由 x x x 的函數加上雜訊產生:
y = f ( x ) + ε , E [ ε ] = 0 , Var ( ε ) = σ ε 2
y = f(x) + \varepsilon, \qquad \mathbb{E}[\varepsilon] = 0, \quad \operatorname{Var}(\varepsilon) = \sigma_\varepsilon^2
y = f ( x ) + ε , E [ ε ] = 0 , Var ( ε ) = σ ε 2 我們從訓練集 D D D 學到一個近似函數 y ^ = f ^ ( x ) \hat y = \hat f(x) y ^ = f ^ ( x ) 。訓練集是隨機抽出來的,換一份 D D D 就會得到不同的 f ^ \hat f f ^ 。把所有可能訓練集上的平均預測記為
f ˉ ( x ) = E D [ f ^ ( x ) ]
\bar f(x) = \mathbb{E}_D\big[\hat f(x)\big]
f ˉ ( x ) = E D [ f ^ ( x ) ] 可以把 f ˉ \bar f f ˉ 想像成:同一個演算法,用無數份不同的訓練集各訓練一次,再把預測取平均所得到的「中心估計」。以下先固定一個測試點 x x x ,最後再對 x x x 取期望。
第一步:分離出模型變異
在 f ^ − y \hat f - y f ^ − y 中加減 f ˉ \bar f f ˉ :
E D , y [ ( f ^ ( x ) − y ) 2 ] = E D , y [ ( f ^ ( x ) − f ˉ ( x ) + f ˉ ( x ) − y ) 2 ] = E D [ ( f ^ ( x ) − f ˉ ( x ) ) 2 ] ⏟ variance + E y [ ( f ˉ ( x ) − y ) 2 ]
\begin{aligned}
\mathbb{E}_{D,y}\big[(\hat f(x) - y)^2\big]
&= \mathbb{E}_{D,y}\big[(\hat f(x) - \bar f(x) + \bar f(x) - y)^2\big] \\
&= \underbrace{\mathbb{E}_{D}\big[(\hat f(x) - \bar f(x))^2\big]}_{\text{variance}} + \mathbb{E}_{y}\big[(\bar f(x) - y)^2\big]
\end{aligned}
E D , y [ ( f ^ ( x ) − y ) 2 ] = E D , y [ ( f ^ ( x ) − f ˉ ( x ) + f ˉ ( x ) − y ) 2 ] = variance E D [ ( f ^ ( x ) − f ˉ ( x ) ) 2 ] + E y [ ( f ˉ ( x ) − y ) 2 ] 交叉項 2 E D , y [ ( f ^ ( x ) − f ˉ ( x ) ) ( f ˉ ( x ) − y ) ] 2\,\mathbb{E}_{D,y}\big[(\hat f(x) - \bar f(x))(\bar f(x) - y)\big] 2 E D , y [ ( f ^ ( x ) − f ˉ ( x )) ( f ˉ ( x ) − y ) ] 等於 0,因為測試點的 y y y 與訓練集 D D D 互相獨立,而 E D [ f ^ ( x ) − f ˉ ( x ) ] = 0 \mathbb{E}_D\big[\hat f(x) - \bar f(x)\big] = 0 E D [ f ^ ( x ) − f ˉ ( x ) ] = 0 。
第二步:分離出偏誤與雜訊
對第二項再加減 f ( x ) f(x) f ( x ) ,並代入 y = f ( x ) + ε y = f(x) + \varepsilon y = f ( x ) + ε :
E y [ ( f ˉ ( x ) − y ) 2 ] = E ε [ ( f ˉ ( x ) − f ( x ) − ε ) 2 ] = ( f ˉ ( x ) − f ( x ) ) 2 ⏟ bias 2 + E [ ε 2 ] ⏟ σ ε 2
\begin{aligned}
\mathbb{E}_{y}\big[(\bar f(x) - y)^2\big]
&= \mathbb{E}_{\varepsilon}\big[(\bar f(x) - f(x) - \varepsilon)^2\big] \\
&= \underbrace{\big(\bar f(x) - f(x)\big)^2}_{\text{bias}^2} + \underbrace{\mathbb{E}\big[\varepsilon^2\big]}_{\sigma_\varepsilon^2}
\end{aligned}
E y [ ( f ˉ ( x ) − y ) 2 ] = E ε [ ( f ˉ ( x ) − f ( x ) − ε ) 2 ] = bias 2 ( f ˉ ( x ) − f ( x ) ) 2 + σ ε 2 E [ ε 2 ] 這裡的交叉項是 − 2 ( f ˉ ( x ) − f ( x ) ) E [ ε ] = 0 -2\big(\bar f(x) - f(x)\big)\,\mathbb{E}[\varepsilon] = 0 − 2 ( f ˉ ( x ) − f ( x ) ) E [ ε ] = 0 。
結果
合併兩步,再對 x x x 取期望:
E x , y , D [ ( f ^ ( x ) − y ) 2 ] = E x [ Var D ( f ^ ( x ) ) ⏟ variance + ( f ˉ ( x ) − f ( x ) ) 2 ⏟ bias 2 ] + σ ε 2 ⏟ noise
\mathbb{E}_{x,y,D}\big[(\hat f(x) - y)^2\big] = \mathbb{E}_x\Big[\underbrace{\operatorname{Var}_D\big(\hat f(x)\big)}_{\text{variance}} + \underbrace{\big(\bar f(x) - f(x)\big)^2}_{\text{bias}^2}\Big] + \underbrace{\sigma_\varepsilon^2}_{\text{noise}}
E x , y , D [ ( f ^ ( x ) − y ) 2 ] = E x [ variance Var D ( f ^ ( x ) ) + bias 2 ( f ˉ ( x ) − f ( x ) ) 2 ] + noise σ ε 2
模型變異 :不同訓練集學出的 f ^ \hat f f ^ 散佈在中心估計周圍的程度,也就是模型對訓練資料變動的敏感度。彈性越大的模型,越容易連訓練資料中的雜訊也一起學進去,變異就越大。降低方式包括:降低模型複雜度、正則化、增加訓練資料或資料擴增、Bagging。
偏誤 :中心估計 f ˉ \bar f f ˉ 與真實函數 f f f 之間的距離,代表模型的假設本身就無法表達真實的關係。降低方式包括:更複雜的模型、更多或更好的特徵、Boosting。
雜訊 :資料本身的隨機性,無論用什麼模型都無法降低,是期望誤差的下限。
模型複雜度
偏誤
變異
典型例子
常見問題
低
高
低
線性模型、淺層樹
欠擬合(underfitting)
高
低
高
高次多項式、深層樹
過擬合(overfitting)
隨著複雜度提高,偏誤下降、變異上升,測試誤差通常呈現 U 形,最佳的複雜度落在兩者總和最小的位置;雜訊項則完全不受影響。
補充Note
「模型變異」與「樣本變異數」是兩回事。模型變異描述預測函數 f ^ \hat f f ^ 隨訓練集變動的程度,可以透過模型選擇與更多資料降低;σ ε 2 \sigma_\varepsilon^2 σ ε 2 則描述給定 x x x 時 y y y 本身的離散程度,屬於資料而非模型,因此稱為不可約誤差(irreducible error)。簡單地說,變異描述分布的「散佈」,偏誤描述估計與目標之間的「距離」。
5.4 集成學習:BaggingBootstrap Aggregating
集成學習把多個模型的預測組合起來,得到比任何單一模型更穩定或更準確的結果。Bagging 是 bootstrap aggregating 的縮寫(Breiman 1996),目標是降低變異。
做法
自助抽樣(bootstrap) :從大小為 n n n 的訓練集 D D D 中,取後放回地抽出 n n n 筆,得到一份自助樣本;重複 B B B 次,得到 D 1 , … , D B D_1, \dots, D_B D 1 , … , D B 。
各自訓練 :在每份自助樣本上訓練一個模型 f ^ b \hat f_b f ^ b 。
匯總(aggregating) :迴歸問題取平均,分類問題取多數決(majority vote)。
f ^ bag ( x ) = 1 B ∑ b = 1 B f ^ b ( x )
\hat f_{\text{bag}}(x) = \frac{1}{B}\sum_{b=1}^{B} \hat f_b(x)
f ^ bag ( x ) = B 1 b = 1 ∑ B f ^ b ( x ) 為什麼能降低變異
若 B B B 個模型的預測變異數皆為 σ 2 \sigma^2 σ 2 ,兩兩之間的相關係數為 ρ \rho ρ ,平均後的變異數為
Var ( 1 B ∑ b = 1 B f ^ b ( x ) ) = ρ σ 2 + 1 − ρ B σ 2
\operatorname{Var}\Big(\frac{1}{B}\sum_{b=1}^{B}\hat f_b(x)\Big) = \rho\,\sigma^2 + \frac{1-\rho}{B}\,\sigma^2
Var ( B 1 b = 1 ∑ B f ^ b ( x ) ) = ρ σ 2 + B 1 − ρ σ 2 B B B 越大,第二項越小;但第一項不會因為 B B B 增加而消失,所以 Bagging 的效果取決於模型之間有多「不相關」。平均不會改變期望值,因此 Bagging 幾乎不影響偏誤,最適合搭配低偏誤、高變異的模型,例如不剪枝的深層決策樹。
袋外樣本(Out-of-Bag)
每抽一次,某一筆資料沒被抽中的機率是 1 − 1 / n 1 - 1/n 1 − 1/ n ;抽 n n n 次都沒被抽中的機率為
( 1 − 1 n ) n → n → ∞ e − 1 ≈ 0.368
\Big(1 - \frac{1}{n}\Big)^n \xrightarrow{\;n \to \infty\;} e^{-1} \approx 0.368
( 1 − n 1 ) n n → ∞ e − 1 ≈ 0.368 也就是說,每份自助樣本大約只包含 63.2% 的不重複資料,其餘約 36.8% 稱為袋外(out-of-bag, OOB)樣本。對每一筆資料,只用「沒看過它」的那些模型來預測,就能得到 OOB 誤差:不需另外切出驗證集,效果卻接近交叉驗證的誤差估計。
隨機森林
隨機森林(random forest,Breiman 2001)是 Bagging 決策樹的改良:每次分裂節點時,只從隨機挑選的 m m m 個特徵中尋找最佳切分(分類常取 m ≈ p m \approx \sqrt{p} m ≈ p ,迴歸常取 m ≈ p / 3 m \approx p/3 m ≈ p /3 ,p p p 為特徵數)。這讓各棵樹不會都被同一個強特徵主導,降低了樹與樹之間的相關係數 ρ \rho ρ ,進一步壓低上式的第一項。決策樹本身請見第 4 章 。
常見誤區Common pitfall
Bagging 不一定能提升表現。它對「不穩定」的學習器(訓練資料稍有變動,模型就大幅改變,例如深層決策樹)效果最好;對 k 近鄰(kNN)這類穩定的學習器,各份自助樣本訓練出的模型幾乎相同,平均後變異降不了多少,而每個模型只看到約 63% 的不重複資料,反而可能讓表現變差。
5.5 集成學習:BoostingBoosting
Boosting 的核心想法,是把多個弱學習器(weak learner,只比隨機猜測好一點的模型,例如只分裂一次的決策樹樁 decision stump)依序組合成一個強學習器(strong learner)。與 Bagging 平行且獨立地訓練不同,Boosting 是序列式 的:每一個新模型都專注於修正前面模型犯的錯,最後以加權總和輸出:
F T ( x ) = ∑ t = 1 T α t h t ( x )
F_T(x) = \sum_{t=1}^{T}\alpha_t\,h_t(x)
F T ( x ) = t = 1 ∑ T α t h t ( x ) 因為每一步都在擬合前面尚未解釋的部分,Boosting 主要降低的是偏誤。
AdaBoost
AdaBoost(Adaptive Boosting,Freund & Schapire 1997)用於二元分類,標籤 y i ∈ { − 1 , + 1 } y_i \in \{-1, +1\} y i ∈ { − 1 , + 1 } 。它透過調整樣本權重,讓後面的模型關注被分錯的資料:
初始化樣本權重 w i = 1 / n w_i = 1/n w i = 1/ n 。
對 t = 1 , … , T t = 1, \dots, T t = 1 , … , T 重複:
以權重 w i w_i w i 訓練弱學習器 h t h_t h t ,計算加權錯誤率 ϵ t = ∑ i w i I ( h t ( x i ) ≠ y i ) / ∑ i w i \epsilon_t = \sum_i w_i\,\mathbb{I}\big(h_t(x_i) \neq y_i\big) \big/ \sum_i w_i ϵ t = ∑ i w i I ( h t ( x i ) = y i ) / ∑ i w i 。
計算模型權重 α t = 1 2 ln 1 − ϵ t ϵ t \alpha_t = \tfrac{1}{2}\ln\frac{1-\epsilon_t}{\epsilon_t} α t = 2 1 ln ϵ t 1 − ϵ t :錯誤率越低,這個學習器的發言權越大。
更新樣本權重 w i ← w i exp ( − α t y i h t ( x i ) ) w_i \leftarrow w_i \exp\big(-\alpha_t\,y_i\,h_t(x_i)\big) w i ← w i exp ( − α t y i h t ( x i ) ) 並正規化:分錯的樣本(y i h t ( x i ) = − 1 y_i h_t(x_i) = -1 y i h t ( x i ) = − 1 )權重放大,分對的縮小。
最終分類器為 sign ( F T ( x ) ) \operatorname{sign}\big(F_T(x)\big) sign ( F T ( x ) ) 。
換個角度看,AdaBoost 等價於以指數損失(exponential loss)L ( y , F ) = e − y F L(y, F) = e^{-yF} L ( y , F ) = e − y F 進行前向逐步加法建模(forward stagewise additive modeling):每一步固定前面的結果,選擇新的 h t h_t h t 與 α t \alpha_t α t 使總損失最小。
( α t , h t ) = arg min α , h ∑ i = 1 n L ( y i , F t − 1 ( x i ) + α h ( x i ) )
(\alpha_t, h_t) = \operatorname*{arg\,min}_{\alpha,\,h}\ \sum_{i=1}^{n} L\big(y_i,\ F_{t-1}(x_i) + \alpha\,h(x_i)\big)
( α t , h t ) = α , h arg min i = 1 ∑ n L ( y i , F t − 1 ( x i ) + α h ( x i ) ) 常見誤區Common pitfall
AdaBoost 對離群值與標註雜訊很敏感。指數損失對分錯的樣本以指數速度放大懲罰,一筆標錯的資料會一輪一輪累積越來越大的權重,讓後面的弱學習器都忙著擬合它。資料雜訊較多時,可以改用以邏輯損失等較溫和的損失函數訓練的梯度提升。
梯度提升與 XGBoost
梯度提升(gradient boosting,Friedman 2001)把 Boosting 推廣到任意可微分的損失函數。第 t t t 步先計算損失對目前預測的負梯度,作為虛擬殘差(pseudo-residual):
r i = − ∂ L ( y i , F ) ∂ F ∣ F = F t − 1 ( x i )
r_i = -\left.\frac{\partial L(y_i, F)}{\partial F}\right|_{F = F_{t-1}(x_i)}
r i = − ∂ F ∂ L ( y i , F ) F = F t − 1 ( x i ) 再用一棵迴歸樹 h t h_t h t 擬合 r i r_i r i ,乘上學習率 ν \nu ν (shrinkage,常取 0.01 到 0.1)後加入模型:F t = F t − 1 + ν h t F_t = F_{t-1} + \nu\,h_t F t = F t − 1 + ν h t 。以平方損失 1 2 ( y − F ) 2 \tfrac{1}{2}(y - F)^2 2 1 ( y − F ) 2 為例,負梯度正好是殘差 y i − F t − 1 ( x i ) y_i - F_{t-1}(x_i) y i − F t − 1 ( x i ) ,也就是「每棵新樹去擬合前面還沒解釋完的部分」。這相當於在函數空間中做梯度下降(梯度下降見第 8 章 )。
XGBoost(Chen & Guestrin 2016)是梯度提升樹的高效實作,主要改進有:
正則化的目標函數 :∑ i L ( y i , y ^ i ) + ∑ t Ω ( h t ) \sum_i L(y_i, \hat y_i) + \sum_t \Omega(h_t) ∑ i L ( y i , y ^ i ) + ∑ t Ω ( h t ) ,其中 Ω ( h ) = γ J + 1 2 λ ∑ j = 1 J w j 2 \Omega(h) = \gamma J + \tfrac{1}{2}\lambda \sum_{j=1}^{J} w_j^2 Ω ( h ) = γ J + 2 1 λ ∑ j = 1 J w j 2 ,J J J 是葉節點數、w j w_j w j 是葉節點的輸出值,直接懲罰樹的複雜度。
二階近似 :對損失做二階泰勒展開,同時使用一階與二階導數。令 G j G_j G j 、H j H_j H j 分別為葉節點 j j j 內所有樣本損失的一階、二階導數總和,最佳葉節點值有封閉解 w j ∗ = − G j / ( H j + λ ) w_j^* = -G_j/(H_j + \lambda) w j ∗ = − G j / ( H j + λ ) ,分裂增益也能直接算出。
工程最佳化 :缺失值的預設分支方向、近似分割點搜尋、平行化與快取設計,使它能有效處理大量資料。
XGBoost 與後續的 LightGBM、CatBoost,至今仍是表格資料(tabular data)上最常用、也最難超越的方法之一。
比較
Bagging
Boosting
訓練方式
平行、彼此獨立
序列、依賴前一步
主要降低
變異
偏誤
適合的基礎模型
低偏誤高變異(深層樹)
高偏誤低變異(樹樁、淺層樹)
對雜訊
較穩健
較敏感,需搭配學習率與正則化
代表方法
隨機森林
AdaBoost、梯度提升、XGBoost
5.6 參考資料References
James, Witten, Hastie & Tibshirani, An Introduction to Statistical Learning , Springer, 2013(第 2 版 2021),第 5 章 Resampling Methods、第 8 章 Tree-Based Methods。
Hastie, Tibshirani & Friedman, The Elements of Statistical Learning , 2nd ed., Springer, 2009,第 7、8、10、15 章。
Fawcett, T., "An introduction to ROC analysis", Pattern Recognition Letters , 2006。
Breiman, L., "Bagging predictors", Machine Learning , 1996;"Random forests", Machine Learning , 2001。
Freund, Y. & Schapire, R. E., "A decision-theoretic generalization of on-line learning and an application to boosting", Journal of Computer and System Sciences , 1997。
Friedman, J. H., "Greedy function approximation: A gradient boosting machine", Annals of Statistics , 2001。
Chen, T. & Guestrin, C., "XGBoost: A scalable tree boosting system", KDD , 2016。