機器學習經典算法之AdaBoost


一、引言

在數據挖掘中,分類算法可以說是核心算法,其中 AdaBoost 算法與隨機森林算法一樣都屬於分類算法中的集成算法。

/*請尊重作者勞動成果,轉載請標明原文鏈接:*/

/* https://www.cnblogs.com/jpcflyer/p/11268859.html * /

集成的含義就是集思廣益,博取眾長,當我們做決定的時候,我們先聽取多個專家的意見,再做決定。集成算法通常有兩種方式,分別是投票選舉(bagging)和再學習(boosting)。投票選舉的場景類似把專家召集到一個會議桌前,當做一個決定的時候,讓 K 個專家(K 個模型)分別進行分類,然后選擇出現次數最多的那個類作為最終的分類結果。再學習相當於把 K 個專家(K 個分類器)進行加權融合,形成一個新的超級專家(強分類器),讓這個超級專家做判斷。

所以你能看出來,投票選舉和再學習還是有區別的。Boosting 的含義是提升,它的作用是每一次訓練的時候都對上一次的訓練進行改進提升,在訓練的過程中這 K 個“專家”之間是有依賴性的,當引入第 K 個“專家”(第 K 個分類器)的時候,實際上是對前 K-1 個專家的優化。而 bagging 在做投票選舉的時候可以並行計算,也就是 K 個“專家”在做判斷的時候是相互獨立的,不存在依賴性。

 

二、 AdaBoost 的工作原理

AdaBoost 的英文全稱是 Adaptive Boosting,中文含義是自適應提升算法。它由 Freund 等人於 1995 年提出,是對 Boosting 算法的一種實現。

什么是 Boosting 算法呢?Boosting 算法是集成算法中的一種,同時也是一類算法的總稱。這類算法通過訓練多個弱分類器,將它們組合成一個強分類器,也就是我們俗話說的“三個臭皮匠,頂個諸葛亮”。為什么要這么做呢?因為臭皮匠好訓練,諸葛亮卻不好求。因此要打造一個諸葛亮,最好的方式就是訓練多個臭皮匠,然后讓這些臭皮匠組合起來,這樣往往可以得到很好的效果。這就是 Boosting 算法的原理。

 

 

我可以用上面的圖來表示最終得到的強分類器,你能看出它是通過一系列的弱分類器根據不同的權重組合而成的。

假設弱分類器為 G_{i}(x) ,它在強分類器中的權重 α_{i} ,那么就可以得出強分類器 f(x):

有了這個公式,為了求解強分類器,你會關注兩個問題:

1.如何得到弱分類器,也就是在每次迭代訓練的過程中,如何得到最優弱分類器?

2.每個弱分類器在強分類器中的權重是如何計算的?

我們先來看下第二個問題。實際上在一個由 K 個弱分類器中組成的強分類器中,如果弱分類器的分類效果好,那么權重應該比較大,如果弱分類器的分類效果一般,權重應該降低。所以我們需要基於這個弱分類器對樣本的分類錯誤率來決定它的權重,用公式表示就是:

其中 e_{i} 代表第 i 個分類器的分類錯誤率。

然后我們再來看下第一個問題,如何在每次訓練迭代的過程中選擇最優的弱分類器?

實際上,AdaBoost 算法是通過改變樣本的數據分布來實現的。AdaBoost 會判斷每次訓練的樣本是否正確分類,對於正確分類的樣本,降低它的權重,對於被錯誤分類的樣本,增加它的權重。再基於上一次得到的分類准確率,來確定這次訓練樣本中每個樣本的權重。然后將修改過權重的新數據集傳遞給下一層的分類器進行訓練。這樣做的好處就是,通過每一輪訓練樣本的動態權重,可以讓訓練的焦點集中到難分類的樣本上,最終得到的弱分類器的組合更容易得到更高的分類准確率。

我們可以用 D_{k+1} 代表第 k+1 輪訓練中,樣本的權重集合,其中 W_{k+1,1} 代表第 k+1 輪中第一個樣本的權重,以此類推 W_{k+1,N} 代表第 k+1 輪中第 N 個樣本的權重,因此用公式表示為:

第 k+1 輪中的樣本權重,是根據該樣本在第 k 輪的權重以及第 k 個分類器的准確率而定,具體的公式為:

 

三、 AdaBoost 算法示例

了解 AdaBoost 的工作原理之后,我們看一個例子,假設我有 10 個訓練樣本,如下所示:

現在我希望通過 AdaBoost 構建一個強分類器。

該怎么做呢?按照上面的 AdaBoost 工作原理,我們來模擬一下。

首先在第一輪訓練中,我們得到 10 個樣本的權重為 1/10,即初始的 10 個樣本權重一致,D1=(0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1)。

假設我有 3 個基礎分類器:

我們可以知道分類器 f1 的錯誤率為 0.3,也就是 x 取值 6、7、8 時分類錯誤;分類器 f2 的錯誤率為 0.4,即 x 取值 0、1、2、9 時分類錯誤;分類器 f3 的錯誤率為 0.3,即 x 取值為 3、4、5 時分類錯誤。

這 3 個分類器中,f1、f3 分類器的錯誤率最低,因此我們選擇 f1 或 f3 作為最優分類器,假設我們選 f1 分類器作為最優分類器,即第一輪訓練得到:

根據分類器權重公式得到:

然后我們對下一輪的樣本更新求權重值,代入 W_{k+1,i} 和 D_{k+1} 的公式,可以得到新的權重矩陣:D2=(0.0715, 0.0715, 0.0715, 0.0715, 0.0715, 0.0715, 0.1666, 0.1666, 0.1666, 0.0715)。

在這 3 個分類器中,f3 分類器的錯誤率最低,因此我們選擇 f3 作為第二輪訓練的最優分類器,即:

根據分類器權重公式得到:

同樣,我們對下一輪的樣本更新求權重值,代入 W_{k+1,i} 和 D_{k+1} 的公式,可以得到 D3=(0.0455,0.0455,0.0455,0.1667, 0.1667,0.01667,0.1060, 0.1060, 0.1060, 0.0455)。

在第三輪訓練中,我們繼續統計三個分類器的准確率,可以得到分類器 f1 的錯誤率為 0.1060*3,也就是 x 取值 6、7、8 時分類錯誤。分類器 f2 的錯誤率為 0.0455*4,即 x 取值為 0、1、2、9 時分類錯誤。分類器 f3 的錯誤率為 0.1667*3,即 x 取值 3、4、5 時分類錯誤。

在這 3 個分類器中,f2 分類器的錯誤率最低,因此我們選擇 f2 作為第三輪訓練的最優分類器,即:

我們根據分類器權重公式得到:

假設我們只進行 3 輪的訓練,選擇 3 個弱分類器,組合成一個強分類器,那么最終的強分類器 G(x) = 0.4236G1(x) + 0.6496G2(x)+0.7514G3(x)。

實際上 AdaBoost 算法是一個框架,你可以指定任意的分類器,通常我們可以采用 CART 分類器作為弱分類器。通過上面這個示例的運算,你體會一下 AdaBoost 的計算流程即可。

 

四、 如何使用 AdaBoost 工具

我們可以直接在 sklearn 中使用 AdaBoost。如果我們要用 AdaBoost 進行分類,需要在使用前引用代碼:

1 from sklearn.ensemble import AdaBoostClassifier

我們之前講到過,如果你看到了 Classifier 這個類,一般都會對應着 Regressor 類。AdaBoost 也不例外,回歸工具包的引用代碼如下:

1 from sklearn.ensemble import AdaBoostRegressor

我們先看下如何在 sklearn 中創建 AdaBoost 分類器。

我們需要使用 AdaBoostClassifier(base_estimator=None, n_estimators=50, learning_rate=1.0, algorithm=’SAMME.R’, random_state=None) 這個函數,其中有幾個比較主要的參數,我分別來講解下:

1. base_estimator:代表的是弱分類器。在 AdaBoost 的分類器和回歸器中都有這個參數,在 AdaBoost 中默認使用的是決策樹,一般我們不需要修改這個參數,當然你也可以指定具體的分類器。

2. n_estimators:算法的最大迭代次數,也是分類器的個數,每一次迭代都會引入一個新的弱分類器來增加原有的分類器的組合能力。默認是 50。

3. learning_rate:代表學習率,取值在 0-1 之間,默認是 1.0。如果學習率較小,就需要比較多的迭代次數才能收斂,也就是說學習率和迭代次數是有相關性的。當你調整 learning_rate 的時候,往往也需要調整 n_estimators 這個參數。

4. algorithm:代表我們要采用哪種 boosting 算法,一共有兩種選擇:SAMME 和 SAMME.R。默認是 SAMME.R。這兩者之間的區別在於對弱分類權重的計算方式不同。

5. random_state:代表隨機數種子的設置,默認是 None。隨機種子是用來控制隨機模式的,當隨機種子取了一個值,也就確定了一種隨機規則,其他人取這個值可以得到同樣的結果。如果不設置隨機種子,每次得到的隨機數也就不同。

那么如何創建 AdaBoost 回歸呢?

我們可以使用 AdaBoostRegressor(base_estimator=None, n_estimators=50, learning_rate=1.0, loss=‘linear’, random_state=None) 這個函數。

你能看出來回歸和分類的參數基本是一致的,不同點在於回歸算法里沒有 algorithm 這個參數,但多了一個 loss 參數。

loss 代表損失函數的設置,一共有 3 種選擇,分別為 linear、square 和 exponential,它們的含義分別是線性、平方和指數。默認是線性。一般采用線性就可以得到不錯的效果。

創建好 AdaBoost 分類器或回歸器之后,我們就可以輸入訓練集對它進行訓練。我們使用 fit 函數,傳入訓練集中的樣本特征值 train_X 和結果 train_y,模型會自動擬合。使用 predict 函數進行預測,傳入測試集中的樣本特征值 test_X,然后就可以得到預測結果。

 

五、 如何用 AdaBoost 對房價進行預測

了解了 AdaBoost 工具包之后,我們看下 sklearn 中自帶的波士頓房價數據集。 這個數據集一共包括了 506 條房屋信息數據,每一條數據都包括了 13 個指標,以及一個房屋價位。

13 個指標的含義,可以參考下面的表格:

這些指標分析得還是挺細的,但實際上,我們不用關心具體的含義,要做的就是如何通過這 13 個指標推導出最終的房價結果。

首先加載數據,將數據分割成訓練集和測試集,然后創建 AdaBoost 回歸模型,傳入訓練集數據進行擬合,再傳入測試集數據進行預測,就可以得到預測結果。最后將預測的結果與實際結果進行對比,得到兩者之間的誤差。具體代碼如下:

 1 from sklearn.model_selection import train_test_split
 2 
 3 from sklearn.metrics import mean_squared_error
 4 
 5 from sklearn.datasets import load_boston
 6 
 7 from sklearn.ensemble import AdaBoostRegressor
 8 
 9 # 加載數據
10 
11 data=load_boston()
12 
13 # 分割數據
14 
15 train_x, test_x, train_y, test_y = train_test_split(data.data, data.target, test_size=0.25, random_state=33)
16 
17 # 使用 AdaBoost 回歸模型
18 
19 regressor=AdaBoostRegressor()
20 
21 regressor.fit(train_x,train_y)
22 
23 pred_y = regressor.predict(test_x)
24 
25 mse = mean_squared_error(test_y, pred_y)
26 
27 print(" 房價預測結果 ", pred_y)
28 
29 print(" 均方誤差 = ",round(mse,2))

運行結果:

 1 房價預測結果  [20.2        10.4137931  14.63820225 17.80322581 24.58931298 21.25076923
 2 
 3 27.52222222 17.8372093  31.79642857 20.86428571 27.87431694 31.09142857
 4 
 5 12.81666667 24.13131313 12.81666667 24.58931298 17.80322581 17.66333333
 6 
 7 27.83       24.58931298 17.66333333 20.90823529 20.10555556 20.90823529
 8 
 9 28.20877193 20.10555556 21.16882129 24.58931298 13.27619048 31.09142857
10 
11 17.08095238 26.19217391  9.975      21.03404255 26.74583333 31.09142857
12 
13 25.83960396 11.859375   13.38235294 24.58931298 14.97931034 14.46699029
14 
15 30.12777778 17.66333333 26.19217391 20.10206186 17.70540541 18.45909091
16 
17 26.19217391 20.10555556 17.66333333 33.31025641 14.97931034 17.70540541
18 
19 24.64421053 20.90823529 25.83960396 17.08095238 24.58931298 21.43571429
20 
21 19.31617647 16.33733333 46.04888889 21.25076923 17.08095238 25.83960396
22 
23 24.64421053 11.81470588 17.80322581 27.63636364 23.59731183 17.94444444
24 
25 17.66333333 27.7253886  20.21465517 46.04888889 14.97931034  9.975
26 
27 17.08095238 24.13131313 21.03404255 13.4        11.859375   26.19214286
28 
29 21.25076923 21.03404255 47.11395349 16.33733333 43.21111111 31.65730337
30 
31 30.12777778 20.10555556 17.8372093  18.40833333 14.97931034 33.31025641
32 
33 24.58931298 22.88813559 18.27179487 17.80322581 14.63820225 21.16882129
34 
35 26.91538462 24.64421053 13.05       14.97931034  9.975      26.19217391
36 
37 12.81666667 26.19214286 49.46511628 13.27619048 17.70540541 25.83960396
38 
39 31.09142857 24.13131313 21.25076923 21.03404255 26.91538462 21.03404255
40 
41 21.16882129 17.8372093  12.81666667 21.03404255 21.03404255 17.08095238
42 
43 45.16666667]
44 
45 均方誤差 =  18.05

這個數據集是比較規范的,我們並不需要在數據清洗,數據規范化上花太多精力,代碼編寫起來比較簡單。

同樣,我們可以使用不同的回歸分析模型分析這個數據集,比如使用決策樹回歸和 KNN 回歸。

編寫代碼如下:

 1 # 使用決策樹回歸模型
 2 
 3 dec_regressor=DecisionTreeRegressor()
 4 
 5 dec_regressor.fit(train_x,train_y)
 6 
 7 pred_y = dec_regressor.predict(test_x)
 8 
 9 mse = mean_squared_error(test_y, pred_y)
10 
11 print(" 決策樹均方誤差 = ",round(mse,2))
12 
13 # 使用 KNN 回歸模型
14 
15 knn_regressor=KNeighborsRegressor()
16 
17 knn_regressor.fit(train_x,train_y)
18 
19 pred_y = knn_regressor.predict(test_x)
20 
21 mse = mean_squared_error(test_y, pred_y)
22 
23 print("KNN 均方誤差 = ",round(mse,2))

運行結果:

1 決策樹均方誤差 =  23.84
2 
3 KNN 均方誤差 =  27.87

你能看到相比之下,AdaBoost 的均方誤差更小,也就是結果更優。雖然 AdaBoost 使用了弱分類器,但是通過 50 個甚至更多的弱分類器組合起來而形成的強分類器,在很多情況下結果都優於其他算法。因此 AdaBoost 也是常用的分類和回歸算法之一。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM