集成學習之Boosting —— Gradient Boosting原理


集成學習之Boosting —— AdaBoost原理

集成學習之Boosting —— AdaBoost實現

集成學習之Boosting —— Gradient Boosting原理

集成學習之Boosting —— Gradient Boosting實現




上一篇介紹了AdaBoost算法,AdaBoost每一輪基學習器訓練事後都會更新樣本權重,再訓練下一個學習器,最後將全部的基學習器加權組合。AdaBoost使用的是指數損失,這個損失函數的缺點是對於異常點很是敏感,(關於各類損失函數可見以前的文章: 常見迴歸和分類損失函數比較),於是一般在噪音比較多的數據集上表現不佳。Gradient Boosting在這方面進行了改進,使得可使用任何損失函數 (只要損失函數是連續可導的),這樣一些比較robust的損失函數就能得以應用,使模型抗噪音能力更強。html

Boosting的基本思想是經過某種方式使得每一輪基學習器在訓練過程當中更加關注上一輪學習錯誤的樣本,區別在因而採用何種方式?AdaBoost採用的是增長上一輪學習錯誤樣本的權重的策略,而在Gradient Boosting中則將負梯度做爲上一輪基學習器犯錯的衡量指標,在下一輪學習中經過擬合負梯度來糾正上一輪犯的錯誤。這裏的關鍵問題是:爲何經過擬合負梯度就能糾正上一輪的錯誤了?Gradient Boosting的發明者給出的答案是:函數空間的梯度降低。node



函數空間的的梯度降低

這裏首先回顧一下梯度降低 (Gradient Descend)。機器學習的一大主要步驟是經過優化方法最小化損失函數\(L(\theta)\),進而求出對應的參數\(\theta\)。梯度降低是經典的數值優化方法,其參數更新公式:web

\[ \theta = \theta - \alpha \cdot \frac{\partial}{\partial \theta}L(\theta) \tag{1.1}\]算法


Gradient Boosting 採用和AdaBoost一樣的加法模型,在第m次迭代中,前m-1個基學習器都是固定的,即\[f_m(x) = f_{m-1}(x) + \rho_m h_m(x) \tag{1.2}\]bootstrap

於是在第m步咱們的目標是最小化損失函數 \(L(f) = \sum\limits_{i=1}^NL(y_i,f_m(x_i))\),進而求得相應的基學習器。若將\(f(x)\)當成參數,則一樣可使用梯度降低法:app

\[f_m(x) = f_{m-1}(x) - \rho_m \cdot \frac{\partial}{\partial f_{m-1}(x)}L(y,f_{m-1}(x)) \tag{1.3}\]框架

對比式 (1.2)和 (1.3),能夠發現若將\(h_m(x) \approx -\frac{\partial L(y,f_{m-1}(x))}{\partial f_{m-1}(x)}\),即用基學習器\(h_m(x)\)擬合前一輪模型損失函數的負梯度,就是經過梯度降低法最小化\(L(f)\) 。因爲\(f(x)\)實際爲函數,因此該方法被認爲是函數空間的梯度降低。


負梯度也被稱爲「響應 (response)」或「僞殘差 (pseudo residual)」,從名字能夠看出是一個與殘差接近的概念。直覺上來看,殘差\(r = y-f(x)\)越大,代表前一輪學習器\(f(x)\)的結果與真實值\(y\)相差較大,那麼下一輪學習器經過擬合殘差或負梯度,就能糾正以前的學習器犯錯較大的地方。機器學習



Gradient Boosting算法流程

  1. 初始化: \(f_0(x) = \mathop{\arg\min}\limits_\gamma \sum\limits_{i=1}^N L(y_i, \gamma)\)函數

  2. for m=1 to M:
    (a) 計算負梯度: \(\tilde{y}_i = -\frac{\partial L(y_i,f_{m-1}(x_i))}{\partial f_{m-1}(x_i)}, \qquad i = 1,2 \cdots N\)
    (b) 經過最小化平方偏差,用基學習器\(h_m(x)\)擬合\(\tilde{y_i}\)\(w_m = \mathop{\arg\min}\limits_w \sum\limits_{i=1}^{N} \left[\tilde{y}_i - h_m(x_i\,;\,w) \right]^2\)
    (c) 使用line search肯定步長\(\rho_m\),以使\(L\)最小,\(\rho_m = \mathop{\arg\min}\limits_{\rho} \sum\limits_{i=1}^{N} L(y_i,f_{m-1}(x_i) + \rho h_m(x_i\,;\,w_m))\)
    (d) \(f_m(x) = f_{m-1}(x) + \rho_m h_m(x\,;\,w_m)\)
  3. 輸出\(f_M(x)\)性能



迴歸提高樹

在Gradient Boosting框架中,最經常使用的基學習器是決策樹 (通常是CART),兩者結合就成了著名的梯度提高樹 (Gradient Boosting Decision Tree, GBDT)算法。下面先敘述迴歸問題,再敘述分類問題。注意GBDT不管是用於迴歸仍是分類,其基學習器 (即單顆決策樹) 都是迴歸樹,即便是分類問題也是將最後的預測值映射爲機率。

決策樹能夠看做是一個分段函數,將特徵空間劃分爲多個獨立區域,在每一個區域預測一個常數,以下圖所示:

所以單棵決策樹可表示爲 \(h(x\,;\,\left \{R_j,b_j \right \}_1^J) = \sum \limits_{j=1}^J b_j I(x \in R_j)\),其中\(\left \{R_j \right \}_1^J\)爲劃分出來的獨立區域 (即各個葉結點),\(\left \{ b_j \right \}_1^J\)爲各區域上的輸出值。爲了求出這兩個參數,因而上面Gradient Boosting中的2.b步變爲:
\[\left \{ R_{jm} \right\}_1^J = \mathop{\arg\min}\limits_{\left \{ R_{jm} \right\}_1^J}\sum\limits_{i=1}^N \left [\tilde{y}_i - h_m(x_i\,;\,\left \{R_{jm},b_{jm} \right\}_1^J) \right]^2\]

即先求出樹劃分出的區域,而相應的\(b_{jm} = \mathop{mean} \limits_{x \in R_{jm}} \tilde{y}_{im}\)爲該區域的平均值。

接下來注意到2.c步中求出的\(\rho_m\)對於整棵樹中全部區域都是同樣的,這樣可能並不會使損失最小,所以Friedman提出能夠對每一個區域\(R_j\)分別求一個最優的值\(\gamma_{jm} = \rho_m b_{jm}\),則2.c步變爲:
\[\gamma_{jm} = \mathop{\arg\min}\limits_\gamma \sum\limits_{x_i \in R_{jm}}L(y_i,f_{m-1}(x_i)+\gamma)\]



GBDT迴歸算法流程

  1. 初始化: \(f_0(x) = \mathop{\arg\min}\limits_\gamma \sum\limits_{i=1}^N L(y_i, \gamma)\)

  2. for m=1 to M:
    (a) 計算負梯度: \(\tilde{y}_i = -\frac{\partial L(y_i,f_{m-1}(x_i))}{\partial f_{m-1}(x_i)}, \qquad i = 1,2 \cdots N\)
    (b) \(\left \{ R_{jm} \right\}_1^J = \mathop{\arg\min}\limits_{\left \{ R_{jm} \right\}_1^J}\sum\limits_{i=1}^N \left [\tilde{y}_i - h_m(x_i\,;\,\left \{R_{jm},b_{jm} \right\}_1^J) \right]^2\)
    (c) \(\gamma_{jm} = \mathop{\arg\min}\limits_\gamma \sum\limits_{x_i \in R_{jm}}L(y_i,f_{m-1}(x_i)+\gamma)\)
    (d) \(f_m(x) = f_{m-1}(x) + \sum\limits_{j=1}^J \gamma_{jm}I(x \in R_{jm})\)
  3. 輸出\(f_M(x)\)



迴歸問題損失函數的選擇

經常使用的損失函數爲平方損失 (squared loss),絕對值損失 (absolute loss),Huber損失 (huber loss),下面給出各自的負梯度 (來自ESL 360頁):



分類提高樹

將GBDT由迴歸拓展到分類,關鍵是損失函數的選擇。若是選用了指數損失 (exponential loss),則退化爲AdaBoost算法。另外一種經常使用的分類損失函數爲logistic loss,形式爲\(L(y,f(x)) = log(1+e^{-2yf(x)})\)


要將其最小化,則對於\(f(x)​\)求導並令其爲0:\[\frac{\partial\,log(1+e^{-2yf(x)})}{\partial f(x)} = P(y=1|x) \frac{-2e^{-2f(x)}}{1+e^{-2f(x)}} + P(y=-1|x) \frac{2e^{2f(x)}}{1+e^{2f(x)}} = 0 \quad \Longrightarrow \quad f(x) = \frac12 log\frac{P(y=1|x)}{P(y=-1|x)}\]


能夠看到這與指數損失的目標函數同樣,都是對數概率,見下圖 (來自MLAPP 566頁):

區別在於指數損失容易受異常點的影響,不夠robust,且只能用於二分類問題。因此像scikit-learn中GradientBoostingClassifier的默認損失函數就是deviance。


與迴歸提高樹的流程相似,求logistic loss的負梯度爲:\(\tilde{y} = -\frac{\partial \, log(1+e^{-2yf(x)})}{\partial f(x)} = -\frac{-2y e^{-2yf(x)}}{1+e^{-2yf(x)}} = \frac{2y}{1+e^{2yf(x)}}\)

對於每一個區域\(R_j\)的最優值爲:\(\gamma_j = \mathop{\arg\min}\limits_\gamma \sum\limits_{x \in R_j} L(y,f_{m-1}(x)+\gamma) = \mathop{\arg\min}\limits_\gamma \sum \limits_{x \in R_j} log(1+e^{-2y(f_{m-1}(x)+\gamma)})\)

上式難以直接求出,所以經常使用近似值代替: \(\gamma_j = \frac{\sum\limits_{x \in R_j}\tilde{y}}{\sum\limits_{x \in R_j}|\tilde{y}|(2-|\tilde{y}|)}\)

由於是分類問題,最後輸出\(f_M(x)\)後要進行機率估計:設 \(P = P(y=1|x)\)\[f(x) = \frac12 log\frac{P(y=1|x)}{P(y=-1|x)} = \frac12log \frac{P}{1-P} \quad \color{Blue}{\Longrightarrow}\quad P = P(y=1|x) = \frac{1}{1+e^{-2f(x)}} \;\in \left\{0,1 \right\}\]



正則化 (Regularization)

一、Shrinkage

對每一個基學習器乘以一個係數\(\,\nu\, (0 < \nu <1)\),使其對最終模型的貢獻減少,從而防止學的太快產生過擬合。\(\nu\)又稱學習率,即scikit-learn中的learning rate。因而上文的加法模型就從:
\[f_m(x) = f_{m-1}(x) + \rho_m h_m(x\,;\,w_m)\]

變爲:
\[f_m(x) = f_{m-1}(x) + \nu \rho_m h_m(x\,;\,w_m)\]

通常\(\nu\)要和迭代次數M結合起來使用,較小的\(\nu\)意味着須要較大的M。ESL中推薦的策略是先將\(\nu\)設得很小 (\(\nu\) < 0.1),再經過early stopping選擇M,不過現實中也經常使用cross-validation進行選擇。


二、Early stopping

將數據集劃分爲訓練集和測試集,在訓練過程當中不斷檢查在測試集上的表現,若是測試集上的準確率降低到必定閾值之下,則中止訓練,選用當前的迭代次數M,這一樣是防止過擬合的手段。


三、限制樹的複雜度

不加限制徹底生成的樹一樣可能會學的太快致使過擬合,於是一般對其進行預剪枝。經常使用的方法是限制樹的深度(scikit-learn中的max_depth)等。


四、Subsampling

借用bootstrap的思想,每一輪訓練時只使用一部分樣本,不一樣點是這裏的採樣是無放回抽樣,這個方法被稱爲Stochastic Gradient Boosting。對於單棵樹來講,只使用一部分樣本擬合會增長單棵樹的誤差和方差,然而subsampling會使樹與樹之間的相關性減小,從而下降模型的總體方差,不少時候會提升準確性。

subsampling的另外一個好處是由於只使用一部分樣本進行訓練,因此能顯著下降計算開銷。



特徵重要性

單棵決策樹的可解釋性很強,GBDT則繼承了這個優勢。

對於單棵樹T,用下式來衡量每一個特徵\(X_l\)的重要性:\[\mathcal{I}_{l}^2(T) = \sum\limits_{t=1}^{J-1}\hat{i}_t^2I(v(t) = l)\]

其中\(J\)表示葉結點 (leaf node) 數量,\(J-1\)表示內部結點 (internal node) 數量,\(X_{v(t)}\)是與內部結點t相關聯的分裂特徵。對於每一個內部結點t,用特徵\(X_{v(t)}\)來模擬劃分特徵空間,獲得一個分裂後的平方偏差減小量,即\(\hat{i}^2_t\),最後將全部內部節點上的偏差減小量加起來,就是特徵\(X_l\)的重要性。總偏差減小地越多,該特徵就越重要。


對於M棵樹的集成而言,特徵重要性就是各棵樹相應值的平均:\[\mathcal{I}_{l}^2 = \frac1M\sum\limits_{m=1}^M\mathcal{I}_l^2(T_m)\]



終末 —— 決策樹和GBDT

Gradient Boosting算法理論上能夠選擇多種不一樣的學習算法做爲基學習器,但實際使用地最多的無疑是決策樹,這並不是偶然。決策樹有不少優良的特性,好比能靈活處理各類類型的數據,包括連續值和離散值;對缺失值不敏感;不須要作特徵標準化/歸一化;可解釋性好等等,但其致命缺點是不穩定,致使容易過擬合,於是不少時候準確率不如其餘算法。

決策樹是非參數模型,這並不意味着其沒有參數,而是在訓練以前參數數量是不肯定的,所以徹底生長的決策樹有着較大的自由度,能最大化地擬合訓練數據。然而單顆決策樹是不穩定的,樣本數相同的訓練集產生微小變更就能致使最終模型的較大差別,即模型的方差大,泛化性能很差。集成學習的另外一表明Bagging是對付這個問題的一大利器 (詳見前一篇文章Bagging與方差) 。而Bagging的拓展算法 —— 隨機森林,經過在樹內部結點的分裂過程當中,隨機選取固定數量的特徵歸入分裂的候選項,這樣就進一步下降了單模型之間的相關性,整體模型的方差也比Bagging更低。

另外一方面,決策樹和Gradient Boosting結合誕生了GBDT,GBDT繼承了決策樹的諸多優勢,同時也改進了其缺點。因爲GBDT採用的樹都是複雜度低的樹,因此方差很小,經過梯度提高的方法集成多個決策樹,最終可以很好的解決過擬合的問題。然而Boosting共有的缺點爲訓練是按順序的,難以並行,這樣在大規模數據上可能致使速度過慢,所幸近年來XGBoost和LightGBM的出現都極大緩解了這個問題,後文詳述。





Reference:

  1. Friedman, J. Greedy Function Approximation: A Gradient Boosting Machine
  2. Friedman, J. Stochastic Gradient Boosting
  3. Friedman, J., Hastie, T. and Tibshirani, R. The Elements of Staistical Learning

/

相關文章
相關標籤/搜索