整合學習值Adaboost演算法原理和程式碼小結(轉載)
在中,我們講到了整合學習按照個體學習器之間是否存在依賴關係可以分為兩類:
- 第一個是個體學習器之間存在強依賴關係;
- 另一類是個體學習器之間不存在強依賴關係。
前者的代表演算法就是提升(boosting)系列演算法。在boosting系列演算法中, Adaboost是最著名的演算法之一。Adaboost既可以用作分類,也可以用作迴歸。本文就對Adaboost演算法做一個總結。
一 回顧boosting演算法的基本原理
AdaBoost是典型的Boosting演算法,屬於Boosting家族的一員。在說AdaBoost之前,先說說Boosting提升演算法。Boosting演算法是將“弱學習演算法“提升為“強學習演算法”的過程,主要思想是“三個臭皮匠頂個諸葛亮”。一般來說,找到弱學習演算法要相對容易一些,然後通過反覆學習得到一系列弱分類器,組合這些弱分類器得到一個強分類器。Boosting演算法要涉及到兩個部分,加法模型和前向分步演算法。加法模型就是說強分類器由一系列弱分類器線性相加而成。一般組合形式如下:$$f(x;P)=\sum_{k=1}^Kβ_kh(x;\gamma_k)$$
其中,$h(x;\gamma_k)$ 就是一個個的弱分類器,$\gamma_k$是弱分類器學習到的最優引數,$β_k$ 就是弱學習在強分類器中所佔比重,$P$ 是所有$\gamma_k$和$\beta_k$ 的組合。這些弱分類器線性相加組成強分類器。
前向分步就是說在訓練過程中,下一輪迭代產生的分類器是在上一輪的基礎上訓練得來的。也就是可以寫成這樣的形式:
$$f _k(x)=f_{k-1}(x)+ β_kh_k(x;\gamma_k)$$
由於採用的損失函式不同,Boosting演算法也因此有了不同的型別,AdaBoost就是損失函式為指數損失的Boosting演算法。
在前面一節,我們已經講到了boosting算法系列的基本思想,如下圖:
從圖中可以看出,Boosting演算法的工作機制是首先從訓練集用初始權重D(1)訓練出一個弱學習器1,根據弱學習的學習誤差率表現來更新訓練樣本的權重,使得之前弱學習器1學習誤差率高的訓練樣本點的權重變高,使得這些誤差率高的點在後面的弱學習器2中得到更多的重視。然後基於調整權重後的訓練集來訓練弱學習器2.,如此重複進行,直到弱學習器數達到事先指定的數目T,最終將這T個弱學習器通過集合策略進行整合,得到最終的強學習器。
在上圖中有幾個具體的問題我們沒有詳細說明。
- 如何計算分類誤差率e?
- 如何得到弱學習器權重係數$\alpha$(即上式中的$β_k$)?
- 如何更新訓練資料的樣本權重D?
- 使用何種結合策略?
只要是boosting大家族的演算法,都要解決這4個問題。那麼Adaboost是怎麼解決的呢?
二 Adaboost演算法的基本思想
我們這裡講解Adaboost是如何解決上面4個問題的。
假設我們的訓練集樣本是:$$T=\{(x_,y_1),(x_2,y_2), ...(x_m,y_m)\}$$
訓練集的在第k個弱學習器的樣本權重係數為:$$D(k) = (w_{k1}, w_{k2}, ...w_{km}) ;\;\;\sum\limits_{i=1}^{m}w_{ki}=1;\;\;w_{1i}=\frac{1}{m};\;\; i =1,2...m$$
注意:在初始化第一個弱分類器輸出權重時,我們假設訓練集樣本具有均勻的權值分佈,即每個訓練樣本在第一個弱分類器的學習中作用相同,這一假設保證可以在訓練集樣本上學習第一個弱分類器$G_1(x)$。
首先我們看看Adaboost的分類問題。
分類問題的誤差率很好理解和計算。由於多元分類是二元分類的推廣,這裡假設我們是二元分類問題,輸出為{-1,1},則第k個弱分類器$G_k(x)$在訓練集上的分類誤差率為:$$e_k = P(G_k(x_i) \neq y_i) = \sum\limits_{i=1}^{m}w_{ki}I(G_k(x_i) \neq y_i)$$
接著我們看弱學習器權重係數,對於二元分類問題,第k個弱分類器$G_k(x)$的權重係數為:$$\alpha_k = \frac{1}{2}log\frac{1-e_k}{e_k}$$
為什麼這樣計算弱學習器權重係數?從上式可以看出,如果分類誤差率$e_k$越大,則對應的弱分類器權重係數$\alpha_k$越小。也就是說,誤差率小的弱分類器權重係數越大。具體為什麼採用這個權重係數公式,我們在講Adaboost的損失函式優化時再講。
第三個問題,如何更新樣本權重D。假設第k個弱分類器的樣本集權重係數為$D(k) = (w_{k1}, w_{k2}, ...w_{km})$,則對應的第k+1個弱分類器的樣本權重係數為:$$w_{k+1,i} = \frac{w_{ki}}{Z_K}exp(-\alpha_ky_iG_k(x_i))$$
這裡$Z_k$是規範化因子:$$Z_k = \sum\limits_{i=1}^{m}w_{ki}exp(-\alpha_ky_iG_k(x_i))$$
從$w_{k+1,i}$計算公式可以看出,如果第i個樣本分類錯誤,則$y_iG_k(x_i) < 0$,導致樣本的權重在第k+1個弱分類器中增大,如果分類正確,則權重在第k+1個弱分類器中減少.不改變所給的訓練集資料,通過不斷的改變訓練樣本的權重,使得訓練集資料在弱分類器的學習中起不同的作用。具體為什麼採用這個樣本權重更新公式,我們在講Adaboost的損失函式優化時再講。
最後一個問題是集合策略。Adaboost分類採用的是加權平均法,最終的強分類器為:$$f(x) = sign(\sum\limits_{k=1}^{K}\alpha_kG_k(x))$$
係數$\alpha_k$表示了弱分類器$G_k(x)$的重要性,這裡所有$\alpha$之和並不為1,$f(x)$的符號決定例項$x$的類,$f(x)$的絕對值表示分類的置信度。
接著我們看看Adaboost的迴歸問題。由於Adaboost的迴歸問題有很多變種,這裡我們以Adaboost R2演算法為準。
我們先看看回歸問題的誤差率的問題,對於第k個弱學習器,計算他在訓練集上的最大誤差:$$E_k= max|y_i - G_k(x_i)|\;i=1,2...m$$
然後計算每個樣本的相對誤差$$e_{ki}= \frac{|y_i - G_k(x_i)|}{E_k}$$
這裡是誤差損失為線性時的情況,如果我們用平方誤差,則$e_{ki}= \frac{(y_i - G_k(x_i))^2}{E_k^2}$,如果我們用的是指數誤差,則$e_{ki}= 1 - exp(\frac{-y_i + G_k(x_i))}{E_k})$
最終得到第k個弱學習器的 誤差率:$$e_k = \sum\limits_{i=1}^{m}w_{ki}e_{ki}$$
我們再來看看如何得到弱學習器權重係數$\alpha$。這裡有:$$\alpha_k =\frac{e_k}{1-e_k}$$
對於更新更新樣本權重D,第k+1個弱學習器的樣本集權重係數為:$$w_{k+1,i} = \frac{w_{ki}}{Z_k}\alpha_k^{1-e_{ki}}$$
這裡$Z_k$是規範化因子:$$Z_k = \sum\limits_{i=1}^{m}w_{ki}\alpha_k^{1-e_{ki}}$$
最後是結合策略,和分類問題稍有不同,採用的是對加權的弱學習器取中位數的方法,最終的強迴歸器為:$$f(x) = \sum\limits_{k=1}^{K}(ln\frac{1}{\alpha_k})g(x)$$
其中,$g(x)$是所有$\alpha_kG_k(x), k=1,2,....K$的中位數。
三 AdaBoost分類問題的損失函式優化
上面我們講到了分類Adaboost的弱學習器權重係數公式和樣本權重更新公式。但是沒有解釋選擇這個公式的原因,讓人覺得是魔法公式一樣。其實它可以從Adaboost的損失函式推匯出來。
從另一個角度講,Adaboost是模型為加法模型,學習演算法為前向分步學習演算法,損失函式為指數函式的分類問題。
模型為加法模型好理解,我們的最終的強分類器是若干個弱分類器加權平均而得到的。
前向分步學習演算法也好理解,我們的演算法是通過一輪輪的弱學習器學習,利用前一個弱學習器的結果來更新後一個弱學習器的訓練集權重。也就是說,第k-1輪的強學習器為:$$f_{k-1}(x) = \sum\limits_{i=1}^{k-1}\alpha_iG_{i}(x)$$
而第k輪的強學習器為:$$f_{k}(x) = \sum\limits_{i=1}^{k}\alpha_iG_{i}(x)$$
上兩式一比較可以得到:$$f_{k}(x) = f_{k-1}(x) + \alpha_kG_k(x) $$
可見強學習器的確是通過前向分步學習演算法一步步而得到的。
Adaboost損失函式為指數函式,即定義損失函式為:$$loss=\sum\limits_{i=1}^{m}exp(-y_if_{k}(x_i))$$
利用前向分步學習演算法的關係可以得到損失函式為:$$loss=\sum\limits_{i=1}^{m}exp[-y_i(f_{k-1}(x_i) + \alpha_kG_k(x_i))]$$
假設已經經過了$k-1$次迭代,$f_{k-1}(x)$已知,令$w_{ki}^{’} = exp(-y_if_{k-1}(x_i))$, $w_{ki}^{’}$依賴於$f_{k-1}(x_i)$。
將$w_{ki}^{’}$帶入損失函式,損失函式轉化為:$$loss=\sum\limits_{i=1}^{m}w_{ki}^{’}exp[-y_i\alpha_k G_k(x_i)]$$我們繼續化簡$loss$:$$loss=\sum\limits_{y_i=G_k(x_i)}w_{ki}^{'}exp(-\alpha_k)+\sum\limits_{y_i \neq G_k(x_i)}w_{ki}^{'}exp(\alpha_k)$$
$$=(exp(\alpha_k)-exp(-\alpha_k))\sum\limits_{i=1}^{m}w_{ki}^{'}I(y_i \neq G_k(x_i))+exp(-\alpha_k)\sum\limits_{i=1}^{m}w_{ki}^{'}$$
並對$\alpha$求導,使其等於0,則就得到了:$$\alpha_k = \frac{1}{2}log\frac{1-e_k}{e_k}$$
其中,$e_k$即為我們前面的分類誤差率。$$e_k = \frac{\sum\limits_{i=1}^{m}w_{ki}^{’}I(y_i \neq G(x_i))}{\sum\limits_{i=1}^{m}w_{ki}^{’}} = \sum\limits_{i=1}^{m}w_{ki}I(y_i \neq G(x_i))$$
最後看樣本權重的更新。利用$f_{k}(x) = f_{k-1}(x) + \alpha_kG_k(x) $和$w_{ki}^{’} = exp(-y_if_{k-1}(x))$,即可得:$$w_{k+1,i}^{’} = w_{ki}^{’}exp[-y_i\alpha_kG_k(x)]$$
這與我們上面說到的樣本權重的更新只差一個規範化因子$Z_k$,兩者是等價的。
四 AdaBoost二元分類問題演算法流程
這裡我們對AdaBoost二元分類問題演算法流程做一個總結。
輸入為樣本集$T=\{(x_,y_1),(x_2,y_2), ...(x_m,y_m)\}$,輸出為{-1, +1},弱分類器演算法, 弱分類器迭代次數K。
輸出為最終的強分類器$f(x)$
1) 初始化樣本集權重為:$$D(1) = (w_{11}, w_{12}, ...w_{1m}) ;\;\; w_{1i}=\frac{1}{m};\;\; i =1,2...m$$
2) 對於k=1,2,...K:
a) 使用具有權重$D_k$的樣本集來訓練資料,得到弱分類器$G_k(x)$
b)計算$G_k(x)$的分類誤差率:$$e_k = P(G_k(x_i) \neq y_i) = \sum\limits_{i=1}^{m}w_{ki}I(G_k(x_i) \neq y_i)$$
c) 計算弱分類器的係數:$$\alpha_k = \frac{1}{2}log\frac{1-e_k}{e_k}$$
d) 更新樣本集的權重分佈:$$w_{k+1,i} = \frac{w_{ki}}{Z_K}exp(-\alpha_ky_iG_k(x_i)) \;\; i =1,2,...m$$
這裡$Z_k$是規範化因子:$$Z_k = \sum\limits_{i=1}^{m}w_{ki}exp(-\alpha_ky_iG_k(x_i))$$
3) 構建最終分類器為:$$f(x) = sign(\sum\limits_{k=1}^{K}\alpha_kG_k(x))$$
對於Adaboost多元分類演算法,其實原理和二元分類類似,最主要區別在弱分類器的係數上。比如Adaboost SAMME演算法,它的弱分類器的係數:$$\alpha_k = \frac{1}{2}log\frac{1-e_k}{e_k} + log(R-1)$$
其中R為類別數。從上式可以看出,如果是二元分類,R=2,則上式和我們的二元分類演算法中的弱分類器的係數一致。
五 Adaboost迴歸問題的演算法流程
這裡我們對AdaBoost迴歸問題演算法流程做一個總結。AdaBoost迴歸演算法變種很多,下面的演算法為Adaboost R2迴歸演算法過程。
輸入為樣本集$T=\{(x_,y_1),(x_2,y_2), ...(x_m,y_m)\}$,,弱學習器演算法, 弱學習器迭代次數K。
輸出為最終的強學習器$f(x)$
1) 初始化樣本集權重為:$$D(1) = (w_{11}, w_{12}, ...w_{1m}) ;\;\; w_{1i}=\frac{1}{m};\;\; i =1,2...m$$
2) 對於k=1,2,...K:
a) 使用具有權重$D_k$的樣本集來訓練資料,得到弱學習器$G_k(x)$
b) 計算訓練集上的最大誤差:$$E_k= max|y_i - G_k(x_i)|\;i=1,2...m$$
c) 計算每個樣本的相對誤差:
如果是線性誤差,則$e_{ki}= \frac{|y_i - G_k(x_i)|}{E_k}$;
如果是平方誤差,則$e_{ki}= \frac{(y_i - G_k(x_i))^2}{E_k^2}$
如果是指數誤差,則$e_{ki}= 1 - exp(\frac{-|y_i -G_k(x_i)|}{E_k})$
d) 計算迴歸誤差率:$$e_k = \sum\limits_{i=1}^{m}w_{ki}e_{ki}$$
c) 計算弱學習器的係數:$$\alpha_k =\frac{e_k}{1-e_k}$$
d) 更新樣本集的權重分佈為:$$w_{k+1,i} = \frac{w_{ki}}{Z_k}\alpha_k^{1-e_{ki}}$$
這裡$Z_k$是規範化因子:$$Z_k = \sum\limits_{i=1}^{m}w_{ki}\alpha_k^{1-e_{ki}}$$
3) 構建最終強學習器為:$$f(x) = \sum\limits_{k=1}^{K}(ln\frac{1}{\alpha_k})g(x)$$
其中,$g(x)$是所有$\alpha_kG_k(x), k=1,2,....K$的中位數。
六 Adaboost演算法的正則化
為了防止Adaboost過擬合,我們通常也會加入正則化項,這個正則化項我們通常稱為步長(learning rate)。定義為$\nu$,對於前面的弱學習器的迭代:$$f_{k}(x) = f_{k-1}(x) + \alpha_kG_k(x) $$
如果我們加上了正則化項,則有:$$f_{k}(x) = f_{k-1}(x) + \nu\alpha_kG_k(x) $$
$\nu$的取值範圍為$0 < \nu \leq 1 $。對於同樣的訓練集學習效果,較小的$\nu$意味著我們需要更多的弱學習器的迭代次數。通常我們用步長和迭代最大次數一起來決定演算法的擬合效果。
七 Adaboost的例子
給定如下表所示訓練資料,假設弱分類器由$x<v$或$x>v$產生,可以看做由一個根節點直接連線兩個葉節點的簡單決策樹,其閾值$v$使該分類器在訓練資料集上的分類誤差率最低,試用Adaboost演算法學習一個強分類器。
序號 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
$x$ | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
$y$ | 1 | 1 | 1 | -1 | -1 | -1 | 1 | 1 | 1 | -1 |
解:初始化樣本權重係數:$$D_1={w_{11},w_{12},...,w_{110}};\;\;w_{1i}=0.1,i=1,2,...,10$$
對於$k$=1:
a、在權重為$D_1$的訓練資料上、閾值$v$取2.5時分類誤差率最低,故弱分類器為:$$G_1(x)=\begin{cases}1, { x<2.5}\\ - 1, {x>2.5 }\end{cases}$$
b、$G_1(x)$在訓練資料集上的分類誤差率$e_1=P(G_1(x_i) \neq y_i) = 0.3$
c、計算$G_1(x)$的係數:$\alpha_1=\frac{1}{2}log\frac{1-e_1}{e_1}=0.4236$
d、更新樣本的權重分佈:$$D_2={w_{21},...,w_{2i},...,w_{210}};\;\;w_{2i}=\frac{w_{1i}}{Z_1}exp(-\alpha_1 y_i G_1(x_i)), i=1,2,...,10$$ $$D_2=(0.07143,0.07143,0.07143,0.07143,0.07143,0.07143,0.16667,0.16667,0.16667,0.07143)$$ $$f_1(x)=0.4236G_1(x)$$
分類器$sign[f_1(x)]$在訓練資料集上有3個誤分類點。
對於$k$=2:
a、在權重為$D_2$的訓練資料上、閾值$v$取8.5時分類誤差率最低,故弱分類器為:$$G_2(x)=\begin{cases}1, { x<8.5}\\ - 1, {x>8.5 }\end{cases}$$
b、$G_2(x)$在訓練資料集上的分類誤差率$e_2=P(G_2(x_i) \neq y_i) = 0.2143$
c、計算$G_2(x)$的係數:$\alpha_2=\frac{1}{2}log\frac{1-e_2}{e_2}=0.6496$
d、更新樣本的權重分佈:$$D_3={w_{31},...,w_{3i},...,w_{310}};\;\;w_{3i}=\frac{w_{2i}}{Z_2}exp(-\alpha_2 y_i G_2(x_i)), i=1,2,...,10$$ $$D_3=(0.0455,0.0455,0.0455,0.1667,0.1667,0.1667,0.1060,0.1060,0.1060,0.0455)$$ $$f_2(x)=0.4236G_1(x)+0.6496G_2(x)$$
分類器$sign[f_2(x)]$在訓練資料集上有3個誤分類點。
對於$k$=3:
a、在權重為$D_3$的訓練資料上、閾值$v$取5.5時分類誤差率最低,故弱分類器為:$$G_3(x)=\begin{cases}1, { x>5.5}\\ - 1, {x<5.5 }\end{cases}$$
b、$G_3(x)$在訓練資料集上的分類誤差率$e_3=P(G_3(x_i) \neq y_i) = 0.1820$
c、計算$G_3(x)$的係數:$\alpha_3=\frac{1}{2}log\frac{1-e_3}{e_3}=0.7514$
d、更新樣本的權重分佈:$$D_4={w_{41},...,w_{4i},...,w_{410}};\;\;w_{4i}=\frac{w_{3i}}{Z_3}exp(-\alpha_3 y_i G_3(x_i)), i=1,2,...,10$$ $$D_4=(0.125,0.125,0.125,0.102,0.102,0.102,0.065,0.065,0.065,0.125)$$ $$f_3(x)=0.4236G_1(x)+0.6496G_2(x)+0.7514G_3(x)$$
分類器$sign[f_3(x)]$在訓練資料集上有0個誤分類點。
於是最終分類器為:$$G(x)=sign[f_3(x)]=sign[0.4236G_1(x)+0.6496G_2(x)+0.7514G_3(x)]$$
八 scikit-learn Adaboost類庫使用小結
1. Adaboost類庫概述
scikit-learn中Adaboost類庫比較直接,就是AdaBoostClassifier和AdaBoostRegressor兩個,從名字就可以看出AdaBoostClassifier用於分類,AdaBoostRegressor用於迴歸。
AdaBoostClassifier使用了兩種Adaboost分類演算法的實現,SAMME和SAMME.R。而AdaBoostRegressor則使用了講到的Adaboost迴歸演算法的實現,即Adaboost.R2。
當我們對Adaboost調參時,主要要對兩部分內容進行調參,第一部分是對我們的Adaboost的框架進行調參, 第二部分是對我們選擇的弱分類器進行調參。兩者相輔相成。下面就對Adaboost的兩個類:AdaBoostClassifier和AdaBoostRegressor從這兩部分做一個介紹。
2. AdaBoostClassifier和AdaBoostRegressor框架引數
我們首先來看看AdaBoostClassifier和AdaBoostRegressor框架引數。兩者大部分框架引數相同,下面我們一起討論這些引數,兩個類如果有不同點我們會指出。
1)base_estimator:AdaBoostClassifier和AdaBoostRegressor都有,即我們的弱分類學習器或者弱迴歸學習器。理論上可以選擇任何一個分類或者回歸學習器,不過需要支援樣本權重。我們常用的一般是CART決策樹或者神經網路MLP。預設是決策樹,即AdaBoostClassifier預設使用CART分類樹DecisionTreeClassifier,而AdaBoostRegressor預設使用CART迴歸樹DecisionTreeRegressor。另外有一個要注意的點是,如果我們選擇的AdaBoostClassifier演算法是SAMME.R,則我們的弱分類學習器還需要支援概率預測,也就是在scikit-learn中弱分類學習器對應的預測方法除了predict還需要有predict_proba。
2)algorithm:這個引數只有AdaBoostClassifier有。主要原因是scikit-learn實現了兩種Adaboost分類演算法,SAMME和SAMME.R。兩者的主要區別是弱學習器權重的度量,SAMME使用了和我們的原理篇裡二元分類Adaboost演算法的擴充套件,即用對樣本集分類效果作為弱學習器權重,而SAMME.R使用了對樣本集分類的預測概率大小來作為弱學習器權重。由於SAMME.R使用了概率度量的連續值,迭代一般比SAMME快,因此AdaBoostClassifier的預設演算法algorithm的值也是SAMME.R。我們一般使用預設的SAMME.R就夠了,但是要注意的是使用了SAMME.R, 則弱分類學習器引數base_estimator必須限制使用支援概率預測的分類器。SAMME演算法則沒有這個限制。
3)loss:這個引數只有AdaBoostRegressor有,Adaboost.R2演算法需要用到。有線性‘linear’, 平方‘square’和指數 ‘exponential’三種選擇, 預設是線性,一般使用線性就足夠了,除非你懷疑這個引數導致擬合程度不好。這個值的意義在原理中我們也講到了,它對應了我們對第k個弱分類器的中第i個樣本的誤差的處理,即:如果是線性誤差,則$e_{ki}= \frac{|y_i - G_k(x_i)|}{E_k}$;如果是平方誤差,則$e_{ki}= \frac{(y_i - G_k(x_i))^2}{E_k^2}$,如果是指數誤差,則$e_{ki}= 1 - exp(\frac{-y_i + G_k(x_i))}{E_k})$,$E_k$為訓練集上的最大誤差$E_k= max|y_i - G_k(x_i)|\;i=1,2...m$
4) n_estimators: AdaBoostClassifier和AdaBoostRegressor都有,就是我們的弱學習器的最大迭代次數,或者說最大的弱學習器的個數。一般來說n_estimators太小,容易欠擬合,n_estimators太大,又容易過擬合,一般選擇一個適中的數值。預設是50。在實際調參的過程中,我們常常將n_estimators和下面介紹的引數learning_rate一起考慮。
5) learning_rate: AdaBoostClassifier和AdaBoostRegressor都有,即每個弱學習器的權重縮減係數$\nu$,在原理中的正則化小節我們也講到了,加上了正則化項,我們的強學習器的迭代公式為$f_{k}(x) = f_{k-1}(x) + \nu\alpha_kG_k(x) $。$\nu$的取值範圍為$0 < \nu \leq 1 $。對於同樣的訓練集擬合效果,較小的$\nu$意味著我們需要更多的弱學習器的迭代次數。通常我們用步長和迭代最大次數一起來決定演算法的擬合效果。所以這兩個引數n_estimators和learning_rate要一起調參。一般來說,可以從一個小一點的$\nu$開始調參,預設是1。
3. AdaBoostClassifier和AdaBoostRegressor弱學習器引數
這裡我們再討論下AdaBoostClassifier和AdaBoostRegressor弱學習器引數,由於使用不同的弱學習器,則對應的弱學習器引數各不相同。這裡我們僅僅討論預設的決策樹弱學習器的引數。即CART分類樹DecisionTreeClassifier和CART迴歸樹DecisionTreeRegressor。
DecisionTreeClassifier和DecisionTreeRegressor的引數基本類似,在scikit-learn決策樹演算法類庫使用小結這篇文章中我們對這兩個類的引數做了詳細的解釋。這裡我們只拿出調引數時需要尤其注意的最重要幾個的引數再拿出來說一遍:
1) 劃分時考慮的最大特徵數max_features: 可以使用很多種型別的值,預設是"None",意味著劃分時考慮所有的特徵數;如果是"log2"意味著劃分時最多考慮log
個特徵;如果是"sqrt"或者"auto"意味著劃分時最多考慮$log_2N$個特徵。如果是整數,代表考慮的特徵絕對數。如果是浮點數,代表考慮特徵百分比,即考慮(百分比xN)取整後的特徵數。其中N為樣本總特徵數。一般來說,如果樣本特徵數不多,比如小於50,我們用預設的"None"就可以了,如果特徵數非常多,我們可以靈活使用剛才描述的其他取值來控制劃分時考慮的最大特徵數,以控制決策樹的生成時間。
2) 決策樹最大深max_depth: 預設可以不輸入,如果不輸入的話,決策樹在建立子樹的時候不會限制子樹的深度。一般來說,資料少或者特徵少的時候可以不管這個值。如果模型樣本量多,特徵也多的情況下,推薦限制這個最大深度,具體的取值取決於資料的分佈。常用的可以取值10-100之間。
3) 內部節點再劃分所需最小樣本數min_samples_split: 這個值限制了子樹繼續劃分的條件,如果某節點的樣本數少於min_samples_split,則不會繼續再嘗試選擇最優特徵來進行劃分。 預設是2.如果樣本量不大,不需要管這個值。如果樣本量數量級非常大,則推薦增大這個值。
4) 葉子節點最少樣本數min_samples_leaf: 這個值限制了葉子節點最少的樣本數,如果某葉子節點數目小於樣本數,則會和兄弟節點一起被剪枝。 預設是1,可以輸入最少的樣本數的整數,或者最少樣本數佔樣本總數的百分比。如果樣本量不大,不需要管這個值。如果樣本量數量級非常大,則推薦增大這個值。
5)葉子節點最小的樣本權重和min_weight_fraction_leaf:這個值限制了葉子節點所有樣本權重和的最小值,如果小於這個值,則會和兄弟節點一起被剪枝。 預設是0,就是不考慮權重問題。一般來說,如果我們有較多樣本有缺失值,或者分類樹樣本的分佈類別偏差很大,就會引入樣本權重,這時我們就要注意這個值了。
6) 最大葉子節點數max_leaf_nodes: 通過限制最大葉子節點數,可以防止過擬合,預設是"None”,即不限制最大的葉子節點數。如果加了限制,演算法會建立在最大葉子節點數內最優的決策樹。如果特徵不多,可以不考慮這個值,但是如果特徵分成多的話,可以加以限制,具體的值可以通過交叉驗證得到。
4. AdaBoostClassifier實戰
這裡我們用一個具體的例子來講解AdaBoostClassifier的使用。
首先我們載入需要的類庫:
import numpy as np import matplotlib.pyplot as plt %matplotlib inline from sklearn.ensemble import AdaBoostClassifier from sklearn.tree import DecisionTreeClassifier from sklearn.datasets import make_gaussian_quantiles
接著我們生成一些隨機資料來做二元分類,如果對如何產生隨機資料不熟悉,在另一篇文章機器學習演算法的隨機資料生成中有比較詳細的介紹。
# 生成2維正態分佈,生成的資料按分位數分為兩類,500個樣本,2個樣本特徵,協方差係數為2 X1, y1 = make_gaussian_quantiles(cov=2.0,n_samples=500, n_features=2,n_classes=2, random_state=1) # 生成2維正態分佈,生成的資料按分位數分為兩類,400個樣本,2個樣本特徵均值都為3,協方差係數為2 X2, y2 = make_gaussian_quantiles(mean=(3, 3), cov=1.5,n_samples=400, n_features=2, n_classes=2, random_state=1) #講兩組資料合成一組資料 X = np.concatenate((X1, X2)) y = np.concatenate((y1, - y2 + 1))
我們通過視覺化看看我們的分類資料,它有兩個特徵,兩個輸出類別,用顏色區別。
plt.scatter(X[:, 0], X[:, 1], marker='o', c=y,s=10)
可以看到資料有些混雜,我們現在用基於決策樹的Adaboost來做分類擬合。
bdt = AdaBoostClassifier(DecisionTreeClassifier(max_depth=2, min_samples_split=20, min_samples_leaf=5), algorithm="SAMME", n_estimators=200, learning_rate=0.8) bdt.fit(X, y)
這裡我們選擇了SAMME演算法,最多200個弱分類器,步長0.8,在實際運用中你可能需要通過交叉驗證調參而選擇最好的引數。擬合完了後,我們用網格圖來看看它擬合的區域。並把擬合的區域用輪廓繪製出來。
x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1 y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1 xx, yy = np.meshgrid(np.arange(x_min, x_max, 0.02), np.arange(y_min, y_max, 0.02)) Z = bdt.predict(np.c_[xx.ravel(), yy.ravel()]) Z = Z.reshape(xx.shape) cs = plt.contourf(xx, yy, Z, cmap=plt.cm.Paired) plt.scatter(X[:, 0], X[:, 1], marker='o', c=y) plt.show()
從圖中可以看出,我們的樣本資料集基本上被輪廓分割開來,Adaboost的擬合效果還是不錯的,現在我們看看擬合分數:
print('Score:',bdt.score(X,y))
也就是說擬合訓練集資料的分數還不錯。當然分數高並不一定好,因為可能過擬合。
現在我們將最大弱分離器個數從200增加到300。再來看看擬合分數。
bdt = AdaBoostClassifier(DecisionTreeClassifier(max_depth=2, min_samples_split=20, min_samples_leaf=5), algorithm="SAMME", n_estimators=300, learning_rate=0.8) bdt.fit(X, y) print("Score:", bdt.score(X,y))
此時的輸出為:Score: 0.962222222222
這印證了我們前面講的,弱分離器個數越多,則擬合程度越好,當然也越容易過擬合。
現在我們降低步長,將步長從上面的0.8減少到0.5,再來看看擬合分數。
bdt = AdaBoostClassifier(DecisionTreeClassifier(max_depth=2, min_samples_split=20, min_samples_leaf=5), algorithm="SAMME