《基於Scikit-Learn、Keras和TensorFlow的機器學習實戰》:集成學習和隨機森林

2021-01-14 智能航空發動機

本文講解Aurélien Géron所著的《Hands-On Machine Learning with Scikit-Learn, Keras, and TensorFlow》的第一部分(機器學習基礎)的第七章《集成學習和隨機森林》。

該書的總目錄如下,分為兩部分:第一部分介紹機器學習的基礎,第二部分介紹神經網絡及深度學習。


假設你隨機問很多人一個很複雜的問題,然後把它們的答案合併起來。通常情況下你會發現這個合併的答案比一個專家的答案要好。這就叫做群體智慧。同樣的,如果你合併了一組預測器(分類器或回歸器)的預測結果,你也會得到一個比單一預測器更好的預測結果。這一組預測器就叫做一個集成體。因此,這種技術就叫做集成學習,一個集成學習算法就叫做集成方法。

例如,你可以訓練一組決策樹分類器,每一個都是在訓練集不同的隨機子集上訓練的。為了去做預測,你獲得了所有決策樹的預測結果,然後預測樣本屬於投票數最多的那個類別。這樣的一種決策樹的集成就叫做隨機森林,它除了簡單之外,也是現今存在的最強大的機器學習算法之一。

我們會在一個項目快結束的時候使用集成算法,一旦你建立了一些性能優良的分類器,就把他們合併為一個更好的分類器。事實上,在機器學習競賽中獲得勝利的算法經常會包含一些集成方法。

在本章中我們會討論一下特別著名的集成方法,包括bagging, boosting和stacking。我們也會討論隨機森林。


1)Voting Classifiers —— 投票分類

假設你已經訓練了一些分類器,每一個都有 80% 的準確率。你可能有一個邏輯斯蒂回歸分類器、或一個 SVM分類器、或一個隨機森林分類器,或者一個 KNN分類器等等,如下所示。

一個非常簡單的去創建一個更好的分類器的方法就是去整合每一個分類器的預測結果,然後預測樣本屬於投票數最多的那個類別。這種基於投票數最多的分類器就叫做硬投票分類器。

令人驚奇的是,這種集成分類器經常會比單個分類器的精度更高。事實上,即使每一個分類器都是一個弱學習器(意味著它們也就比瞎猜好點),集成後仍然是一個強學習器(高準確率),只要有足夠數量的弱學習器且足夠多樣化。

這怎麼可能呢?接下來的類比將會幫助你解決這個疑問。假設你有一個有偏差的硬幣,他有 51% 的機率為正面,49% 的機率為背面。如果你實驗 1000 次,你會得到差不多 510 次正面,490 次背面,因此大多數都是正面。如果你用數學計算,你會發現在實驗 1000 次後,正面為 51% 這個事情的概率為 75%。你實驗的次數越多,正面為 51% 這個事情的概率越大(例如你試驗了 10000 次,概率就會達到 97%)。這是因為大數定律 :當你一直用硬幣實驗時,正面的比例會越來越接近 51%。下圖展示了10次有偏差的硬幣實驗。你可以看到當實驗次數上升時,正面的概率接近於 51%。最終所有 10 次實驗都會收斂到 51%。 

同樣的,假設你創建了一個包含 1000 個分類器的集成模型,其中每個分類器的正確率只有 51%(僅比瞎猜好一點點)。如果你用最多投票機制去預測類別,你可能得到 75% 的準確率!然而,這僅僅在所有的分類器都獨立、不會發生有相關性的錯誤的情況下才會這樣。然而,在拋硬幣這個例子裡,每一個分類器都在同一個數據集上訓練,就導致分類器是相關的。他們可能會犯同一種錯誤,所以也會有很多票投給了錯誤類別,從而導致集成準確率下降。

如果每一個分類器都儘可能得獨立,那麼集成模型會工作的很好。去得到多樣的分類器的方法之一就是用完全不同的算法,這會使它們會做出不同種類的錯誤,這會提高集成的正確率。

接下來的代碼創建和訓練了sklearn 中的投票分類器。這個分類器由三個不同的子分類器組成(訓練集是第五章中的 moons 數據集):

from sklearn.ensemble import RandomForestClassifierfrom sklearn.ensemble import VotingClassifierfrom sklearn.linear_model import LogisticRegressionfrom sklearn.svm import SVC
log_clf = LogisticRegression()rnd_clf = RandomForestClassifier()svm_clf = SVC()
voting_clf = VotingClassifier(             estimators=[('lr', log_clf), ('rf', rnd_clf), ('svc', svm_clf)], voting='hard')voting_clf.fit(X_train, y_train)

讓我們看一下每個子分類器在測試集上的準確率:

>>> from sklearn.metrics import accuracy_score>>> for clf in (log_clf, rnd_clf, svm_clf, voting_clf):...     clf.fit(X_train, y_train)...     y_pred = clf.predict(X_test)...     print(clf.__class__.__name__, accuracy_score(y_test, y_pred))
LogisticRegression 0.864RandomForestClassifier 0.896SVC 0.888VotingClassifier 0.904

你看!投票分類器比其他單個分類器表現的都要好。

如果所有的分類器都能夠預測類別的概率(也就是說他們都有predict_proba()方法),那麼你就可以讓 sklearn 以最高的類概率來預測類別,這個最高的類概率是對所有的子分類器進行平均後得到的。這種方式叫做軟投票。他經常比硬投票表現的更好,因為它給予高度自信的投票更大的權重。你可以通過把voting="hard"設置為voting="soft"來保證所有分類器可以預測類別概率。然而這不是 SVC 分類器默認的選項,所以你需要把它的probability 超參數設置為True(這會使 SVC 使用交叉驗證去預測類別概率,其降低了訓練速度,但會添加predict_proba()方法)。如果你修改了之前的代碼,使用軟投票機制分類,你會發現投票分類器正確率高達 91.2%。


就像之前講到的,可以通過使用不同的訓練算法得到一些不同的分類器。另一種方法就是使用相同的訓練算法,但是在訓練集不同的隨機子集上進行訓練。有放回採樣被稱為Bagging(Bagging,是 bootstrap aggregating 的縮寫)。無放回採樣稱為粘貼(pasting)。

換句話說,Bagging 和 Pasting 都允許在多個分類器上對訓練樣本進行多次採樣,但只有 Bagging 允許同一分類器對訓練樣本進行多次重複採樣。採樣和訓練過程如下圖所示。

當所有的分類器被訓練後,集成分類器可以通過對所有分類器預測結果的簡單聚合來對新的實例進行預測。通常對分類任務的聚合函數是統計模式(統計最常出現的類別,例如硬投票分類機制)或者對回歸任務是平均。相對於在整個訓練集上產生的模型,每一個在不同訓練子集上產生的子分類器偏差較高,但是聚合降低了偏差和方差。通常情況下,相對於在整個訓練集上產生的模型,集成的模型有一個相似的偏差,但是方差要更小。

正如你在上圖所看到的,分類器可以通過不同的 CPU 核或不同的伺服器並行地被訓練。相似的,可以並行地做出預測結果。這就是為什麼 Bagging 和 Pasting 是如此流行的原因之一:它們的可擴展性很好


2.1 Bagging and Pasting in Scikit-Learn —— 在 sklearn 中的 Bagging 和 Pastingsklearn 為 Bagging 和 Pasting 提供了一個簡單的API:BaggingClassifier類(對於回歸任務可以是BaggingRegressor)。接下來的代碼訓練了一個 500 個決策樹分類器的集成,每一個都是在整個數據集上有放回地採樣 100 個訓練實例進行訓練的(這是 Bagging 的一個例子,如果你想嘗試 Pasting,就設置bootstrap=False)。n_jobs參數告訴 sklearn 用於訓練和預測所需要 CPU 核的數量。(-1 代表著 sklearn 會使用所有空閒核):
from sklearn.ensemble import BaggingClassifierfrom sklearn.tree import DecisionTreeClassifierbag_clf = BaggingClassifier(    DecisionTreeClassifier(), n_estimators=500,    max_samples=100, bootstrap=True, n_jobs=-1)bag_clf.fit(X_train, y_train)y_pred = bag_clf.predict(X_test)

如果基分類器可以預測類別的概率(例如它擁有predict_proba()方法),那麼BaggingClassifier會自動的運行軟投票機制,決策樹分類器就是這樣的。

下圖對比了單一決策樹的決策邊界和 基於Bagging 機制集成 500 個決策樹的決策邊界,兩者都在 moons 數據集上訓練。正如你所看到的,集成分類器比起單一決策樹的泛化性能更好:與單一決策樹相比,集成分類器的偏差相似,但是有一個方差更小(換句話說,它們在訓練集上的誤分數目大約相同,但集成分類器的決策邊界較要更規則一些)。

Bootstrapping採樣(有放回的採樣) 為每個訓練子集中引入了更多的多樣性,所以 Bagging 的偏差比 Pasting 更高,但這也意味著分類器之間的相關性變弱,從而減少了集成分類器的方差。總體而言,Bagging 通常會導致更好的模型,這就解釋了為什麼它通常是首選的。然而,如果你有空閒時間和 CPU 資源,可以使用交叉驗證來評估 Bagging 和 Pasting 哪一個更好。


2.2 Out-of-Bag Evaluation —— Out-of-Bag 評估

對於 Bagging 來說,一些實例可能被重複採樣,但有些樣本有可能一次也不會被採到。默認情況下,BaggingClassifier是有放回的採樣m個實例 (bootstrap=True),其中m是訓練集的大小,這意味著平均下來只有63%的訓練實例被每個分類器採樣到,剩下的37%沒有被採樣的訓練實例就叫做 Out-of-Bag (oob)實例。注意對於每一個分類器,這些 37% 的樣本不是相同的。

因為在訓練過程中,各個分類器從來都沒有看到過 oob 實例,所以它可以在這些實例上進行評估,而不需要單獨設置驗證集或交叉驗證。你可以通過平均每個子分類器的oob評估結果來評估集成分類器。

在 sklearn 中,你可以設置oob_score=True來自動進行oob評估。接下來的代碼展示了這個操作。評估結果通過變量oob_score_這個變量來顯示:

>>> bag_clf = BaggingClassifier(...     DecisionTreeClassifier(), n_estimators=500,...     bootstrap=True, n_jobs=-1, oob_score=True)>>> bag_clf.fit(X_train, y_train)>>> bag_clf.oob_score_0.90133333333333332

根據這個 obb 評估,BaggingClassifier有可能在測試集上達到90.1%的準確率。讓我們確認一下:

>>> from sklearn.metrics import accuracy_score>>> y_pred = bag_clf.predict(X_test)>>> accuracy_score(y_test, y_pred)0.91200000000000003

我們在測試集上得到了 91.2% 的準確率!

對於每個訓練實例, oob 決策函數也可通過oob_decision_function_變量來獲得。在這種情況下(當基決策器有predict_proba()時),決策函數會對每個訓練實例返回類別概率。例如,oob 評估預測第一個訓練實例有 68.25% 的概率屬於正類(31.75% 屬於負類):

>>> bag_clf.oob_decision_function_array([[0.31746032, 0.68253968],[0.34117647, 0.65882353],[1. , 0. ],...[1. , 0. ],[0.03108808, 0.96891192],[0.57291667, 0.42708333]])


3)Random Patches and Random Subspaces——隨機貼片與隨機子空間

BaggingClassifier也支持對特徵進行採樣。採樣由兩個超參數max_features和bootstrap_features控制。他們的工作方式和max_samples和bootstrap一樣,但這是對於特徵採樣而不是實例採樣。因此,每一個分類器都會在隨機的輸入特徵子集上進行訓練。

當你在處理高維輸入時(例如圖片),此方法尤其有效。對訓練實例和特徵同時進行採樣也被叫做Random Patches 方法。保留所有的訓練實例(設置bootstrap=False和max_samples=1.0),但是對特徵進行採樣(bootstrap_features=True並且/或者max_features小於 1.0)叫做Random Subspaces 隨機子空間。

對特徵進行採樣導致分類器更大的多樣性,即用高偏差換低方差。


正如我們所討論的,隨機森林是決策樹的一種集成,通常是通過 bagging 方法(有時是 pasting 方法)進行訓練,且max_samples通常設置為訓練集的大小。與其先建立一個BaggingClassifier,然後傳遞一個DecisionTreeClassifier給它,你可以使用更方便的RandomForestClassifier,它對決策樹做了優化(對於回歸是RandomForestRegressor)。接下來的代碼訓練了帶有 500 個樹(每個被限制為最多有16個 葉子結點)的決策森林,使用所有空閒的 CPU 核:
from sklearn.ensemble import RandomForestClassifierrnd_clf = RandomForestClassifier(n_estimators=500, max_leaf_nodes=16, n_jobs=-1)rnd_clf.fit(X_train, y_train)y_pred_rf = rnd_clf.predict(X_test)

RandomForestClassifier具有DecisionTreeClassifier的所有超參數(這些超參數決定數怎麼生長),以及BaggingClassifier的超參數(用於控制集成本身)。

隨機森林算法在樹生長時引入了額外的隨機性:決策樹在分裂節點時需要確定最佳的特徵,而隨機森林是在一個隨機的特徵子集中確定最好的特徵。因此,隨機森林導致的樹的差異性更大,並且再一次用高偏差換取低方差,一般來說這樣會產生總體上更好的模型。以下是BaggingClassifier代碼,大致相當於上面的Randomforestclassifier:

bag_clf = BaggingClassifier(    DecisionTreeClassifier(splitter="random", max_leaf_nodes=16),    n_estimators=500, max_samples=1.0, bootstrap=True, n_jobs=-1)


當你在隨機森林中生成樹時,在每個結點分裂時只考慮隨機特徵子集上的特徵。相比於找到每個特徵的最佳閾值(像常規決策樹一樣),我們可以通過對每個特徵使用隨機閾值使樹更加隨機。

這種極端隨機的樹被簡稱為 Extremely Randomized Trees(極端隨機樹),或者更簡單的稱為 Extra-Tree。這種技術再一次用高偏差換低方差。它還使得 Extra-Tree 比常規的隨機森林訓練更快,因為在每個節點上找到每個特徵的最佳閾值是生成決策樹時最耗時的部分之一。

你可以使用 sklearn 的ExtraTreesClassifier來創建一個 Extra-Tree 分類器。它的 API 跟RandomForestClassifier是相同的。相似的, ExtraTreesRegressor 跟RandomForestRegressor也是相同的 API。

我們很難提前知道ExtraTreesClassifier和RandomForestClassifier到底哪個更好。通常情況下是通過交叉驗證來比較它們(使用網格搜索調整超參數)。


4.2 Feature Importance —— 特徵重要性

隨機森林的另一個重要特點是,它們易于衡量每個特徵的相對重要性。sklearn通過計算所有決策樹中使用了某個特徵的節點平均降低了多少不純度,來衡量特徵的重要性。更準確地說,這是一種加權平均,其中每個節點的權值等於與其相關的訓練樣本的數量。sklearn 在訓練後會自動計算每個特徵的重要性分數,然後對結果進行縮放,使得總和等於1。你可以通過feature_importances_變量來查看結果。例如,如下代碼在 iris 數據集上訓練了一個RandomForestClassifier模型。似乎最重要的特徵是花瓣長度(44%)和寬度(42%),而萼片長度和寬度相對而言是不重要的(分別為 11% 和 2%):

>>> from sklearn.datasets import load_iris>>> iris = load_iris()>>> rnd_clf = RandomForestClassifier(n_estimators=500, n_jobs=-1)>>> rnd_clf.fit(iris["data"], iris["target"])>>> for name, score in zip(iris["feature_names"], rnd_clf.feature_importances_):...     print(name, score)
sepal length (cm) 0.112492250999sepal width (cm) 0.0231192882825petal length (cm) 0.441030464364petal width (cm) 0.423357996355

相似的,如果你在 MNIST 數據集上訓練隨機森林分類器,然後畫出每個像素的重要性,你可以得到下面的圖片。

隨機森林可以非常方便快速地了解哪些特徵實際上是重要的,特別是你需要進行特徵選擇的時候。


提升(Boosting,最初稱為假設增強)指的是任何可以將幾個弱學習器組合成強學習器的集成方法。大多數提升方法的思想就是按順序去訓練分類器,每一個都要嘗試修正前面的分類器。現如今已經有很多的提升方法了,但最著名的就是 Adaboost(適應性提升,是 Adaptive Boosting 的簡稱) 和 Gradient Boosting(梯度提升)。讓我們先從 Adaboost 說起。

使一個新的分類器去修正之前分類結果的方法就是對之前分類結果不對的訓練實例多加關注。這導致新的分類器越來越多地聚焦於難以被正確分類的實例。這是 Adaboost 使用的技術。

舉個例子,當構建一個 Adaboost 分類器時,第一個基分類器(例如一個決策樹)被訓練,然後在訓練集上做預測。根據預測結果,Adaboost增加誤分類實例上的相對權重。第二個分類器使用更新過的權重進行訓練,然後權重得到更新,以此類推。

下圖顯示了在moons 數據集上,連續五個分類器的 的決策邊界(在本例中,每一個分類器都是高度正則化帶有 RBF 核的 SVM)。

第一個分類器誤分類了很多實例,所以被誤分的實例的權重被提升了。第二個分類器因此對這些誤分類的實例分類效果更好,以此類推。右邊的圖代表了除了學習率減半外(相對於左圖,誤分類實例權重在每次迭代中只增加了一半)相同的決策邊界。你可以看出,這種序列學習技術與梯度下降很相似。梯度下降是通過調整單個分類器的參數以最小化代價函數,而AdaBoost 則是不斷地將分類器增加到集成分類器中,逐漸使其變得更好。

一旦所有的子分類器都被訓練後,會根據在整個訓練集上的準確率賦予各個子分類器不同的權重。

序列學習技術的一個重要的缺點就是:它不能被並行化(只能按步驟),因為每個分類器只能在之前的分類器已經被訓練和預測後才能進行訓練。因此,它不像Bagging和Pasting一樣可以擴展到多個核上。

讓我們詳細看一下 Adaboost 算法。每一個實例的初始權重wi都被設為1/m。首先訓練第一個分類器,然後它在訓練集上的加權誤差率r1可以由下式計算。

分類器的權重隨後可以用下式計算出來。

其中η是學習率(默認為 1)。分類器準確率越高,它的權重就越高。如果它只是瞎猜,那麼它的權重會趨近於 0。然而,如果它總是出錯(比瞎猜的機率都低),它的權重會是負數。


接下來,實例的權重會按照下式更新:誤分類的實例權重會被提升。隨後所有實例的權重都被歸一化。

最後,一個新的分類器通過更新過的權重進行訓練,整個過程被重複(新的分類器權重被計算,實例的權重被更新,隨後另一個分類器被訓練,以此類推)。當規定的分類器數量達到或者最好的分類器被找到後,算法就會停止。

為了進行預測,Adaboost 會先計算每個子分類器的預測結果,然後用分類器的權重 alpha_j 對這些權重進行加權。預測的類別會是加權投票中獲得票數最多的那個類別。

sklearn 通常使用 Adaboost 的多分類版本 SAMME(Stagewise Additive Modeling using a Multiclass Exponential loss function)。如果只有兩類別,那麼 SAMME 與 Adaboost 是等價的。如果子分類器可以預測類別概率(例如有predict_proba()方法),sklearn 可以使用 SAMME 的一個變體,叫做SAMME.R(R 代表「REAL」),它依賴於類別概率而不是分類結果,並且通常比依賴於分類結果的更好。接下來的代碼訓練了sklearn 中的AdaBoostClassifier,包含200個決策樹樁(對於回歸也有AdaBoostRegressor)。一個決策樹樁是max_depth=1的決策樹。換句話說,一個決策樹樁就是一個單一的決策節點加上兩個葉子結點。這是AdaBoostClassifier默認的基分類器:
from sklearn.ensemble import AdaBoostClassifierada_clf = AdaBoostClassifier(    DecisionTreeClassifier(max_depth=1), n_estimators=200,    algorithm="SAMME.R", learning_rate=0.5)ada_clf.fit(X_train, y_train)

如果你的 Adaboost 集成分類器過擬合了訓練集,你可以嘗試減少基分類器的數量或者對基分類器使用更強的正則化。
5.2 Gradient Boosting —— 梯度提升
另一個非常著名的提升算法是梯度提升。與 Adaboost 一樣,梯度提升也是通過向集成分類器中逐步增加子分類器,每一個子分類器都修正之前的分類結果。然而,它並不像 Adaboost 那樣在每一次迭代中都更新實例的權重,梯度提升是使用新的分類器去擬合前面分類器預測的殘差 。
讓我們看一個使用決策樹當做基分類器的回歸例子(回歸當然也可以使用梯度提升)。這被叫做梯度提升回歸樹(GBRT,Gradient Tree Boosting 或者 Gradient Boosted Regression Trees)。首先我們用DecisionTreeRegressor去擬合訓練集(例如一個有噪二次訓練集):
from sklearn.tree import DecisionTreeRegressortree_reg1 = DecisionTreeRegressor(max_depth=2)tree_reg1.fit(X, y)

y2 = y - tree_reg1.predict(X)tree_reg2 = DecisionTreeRegressor(max_depth=2)tree_reg2.fit(X, y2)

隨後在第二個分類器的殘差上訓練第三個分類器:

y3 = y2 - tree_reg2.predict(X)tree_reg3 = DecisionTreeRegressor(max_depth=2)tree_reg3.fit(X, y3)

現在我們有了一個包含三個回歸器的集成。它可以通過累加所有樹的預測結果對一個新的實例進行預測。

y_pred = sum(tree.predict(X_new) for tree in (tree_reg1, tree_reg2, tree_reg3))

下圖在左欄展示了這三個樹的預測結果,在右欄展示了集成的預測結果。

在第一行,集成分類器中只有一棵樹,所以它與第一個樹的預測結果一樣。在第二行,一個新的樹在第一個樹的殘差上進行訓練。在右邊欄可以看出集成分類器的預測結果等於前兩個樹預測結果的和。相似地,在第三行,另一個樹在第二個樹的殘差上進行訓練。你可以看到集成的預測結果會變的更好。

我們可以使用 sklean 中的GradientBoostingRegressor來訓練 GBRT 集成分類器。與RandomForestClassifier相似,它也有超參數去控制決策樹的生長(例如max_depth,min_samples_leaf等等),也有超參數去控制集成訓練,例如基分類器的數量(n_estimators)。接下來的代碼創建了與之前相同的集成:

from sklearn.ensemble import GradientBoostingRegressorgbrt = GradientBoostingRegressor(max_depth=2, n_estimators=3, learning_rate=1.0)gbrt.fit(X, y)

超參數learning_rate 確立了每個樹的貢獻。如果你把它設置為一個很小的樹,例如 0.1,在集成分類器中就需要更多的樹去擬合訓練集,但預測結果的通常會有更好的泛化性能。這個正則化技術叫做 shrinkage。下圖展示了兩個在低學習率上訓練的 GBRT 集成體:其中左面是沒有足夠樹去擬合訓練集,右面則是有過多的樹過擬合訓練集。

為了找到樹的最優數量,你可以使用早停技術。使用這個技術的最簡單方法就使用staged_predict():它在訓練的每個階段(比如訓練第一棵樹,訓練第兩棵樹等等),都會針對集成分類器所做的預測結果返回一個迭代器。接下來的代碼訓練了一個 含有120棵樹的GBRT 集成分類器,然後計算在訓練的每個階段的驗證誤差以找到樹的最佳數量,最後使用最優數量訓練集成分類器:

import numpy as npfrom sklearn.model_selection import train_test_splitfrom sklearn.metrics import mean_squared_error
X_train, X_val, y_train, y_val = train_test_split(X, y)gbrt = GradientBoostingRegressor(max_depth=2, n_estimators=120)gbrt.fit(X_train, y_train)
errors = [mean_squared_error(y_val, y_pred) for y_pred in gbrt.staged_predict(X_val)]bst_n_estimators = np.argmin(errors) + 1
gbrt_best = GradientBoostingRegressor(max_depth=2,n_estimators=bst_n_estimators)gbrt_best.fit(X_train, y_train)

驗證誤差在下圖的左面展示,最優模型的預測結果被展示在右面。

你也可以早早的停止訓練來實現早停(與先訓練一大堆樹,然後再回頭去找最優數目相反)。你可以設置warm_start=True ,這使得當fit()方法被調用時 sklearn 會保留現有樹,並允許增量訓練。接下來的代碼在連續五次迭代後,驗證誤差沒有改善時停止訓練:

gbrt = GradientBoostingRegressor(max_depth=2, warm_start=True)
min_val_error = float("inf")error_going_up = 0for n_estimators in range(1, 120): gbrt.n_estimators = n_estimators gbrt.fit(X_train, y_train) y_pred = gbrt.predict(X_val) val_error = mean_squared_error(y_val, y_pred) if val_error < min_val_error: min_val_error = val_error error_going_up = 0 else: error_going_up += 1 if error_going_up == 5: break


本章討論的最後一個集成方法叫做 Stacking(stacked generalization 的縮寫)。這個算法基於一個簡單的想法:不使用繁瑣的函數(如硬投票機制)來聚合集成體中所有分類器的預測結果,我們為什麼不訓練一個模型來執行這個聚合操作呢?下圖展示了在一個新樣本上進行回歸任務的集成體。

底部的三個預測器每一個都輸出不同的值(3.1,2.7 和 2.9),然後最後一個預測器(叫做 blender 或者 meta learner )把這三個分類器的結果當做輸入,然後做出最終決策。

為了訓練這個 blender,一個通用的方法是採用保留集。讓我們看看是怎麼工作的:首先,訓練集被分為兩個子集,第一個子集被用作訓練第一層的預測器,如下圖所示。

然後,第一層的預測器被用來預測第二個子集(保留集),如下圖所示。

這確保了預測結果很「乾淨」,因為這些預測器在訓練的時候沒有使用過這些實例。現在對在保留集中的每一個實例都有三個預測值。我們現在可以使用這些預測結果作為輸入特徵來創建一個新的訓練集(這使得這個訓練集是三維的),並且保持目標值不變。隨後 blender 在這個新的訓練集上訓練,因此,它學會了用第一層預測結果來預測目標值。

顯然,我們可以用這種方法訓練不同的 blender (例如線性回歸、隨機森林等等):我們得到了一層 blender 。訣竅是將訓練集分成三個子集:第一個子集用來訓練第一層,第二個子集用來創建訓練第二層的訓練集(使用第一層分類器的預測值),第三個子集被用來創建訓練第三層的訓練集(使用第二層分類器的預測值)。以上步驟做完了,我們可以通過逐個遍歷每個層來對一個新的實例進行預測,如下圖所示。

然而不幸的是,sklearn 並不直接支持 stacking ,但是你自己是很容易實現的,或者你也可以使用開源的項目例如 brew (網址為 https://github.com/viisar/brew)。


給定一個大小為n的訓練集 D,Bagging算法從中均勻、有放回地選出 m個大小為 n 的子集Di,作為新的訓練集。在這 m個訓練集上使用分類、回歸等算法,則可得到 m個模型,再通過取平均值、取多數票等方法綜合產生預測結果,即可得到Bagging的結果。

在加入後續子預測器的過程中,通常根據上一輪的準確率給予樣本不同的權重,來強化對之前誤分樣本的關注,其中一個經典算法是AdaBoost。


將訓練好的所有基模型對整個訓練集進行預測,第j個基模型對第i個訓練樣本的預測值將作為新的訓練集中第i個樣本的第j個特徵值,最後基於新的訓練集進行訓練。同理,預測的過程也要先經過所有基模型的預測形成新的測試集,最後再對測試集進行預測。

相關焦點

  • Keras和TensorFlow究竟哪個會更好?
    我會使用基於 TensorFlow 的標準 keras 模塊和 tf.keras 模塊,來實現一個卷積神經網絡(CNN)。然後,基於一個示例數據集,來訓練這些 CNN,然後檢查所得結果,你會發現,Keras 和 TensorFlow 是可以和諧共處的。
  • WePay機器學習反欺詐實踐:Python+scikit-learn+隨機森林
    【編者按】將機器學習算法用於金融領域的一個很好的突破口是反欺詐,在這篇博文中,WePay介紹了支付行業構建機器學習模型應對很難發現的shell selling欺詐的實踐心得。WePay採用了流行的Python、scikit-learn開源學習機器學習工具以及隨機森林算法。
  • 拓撲機器學習的神聖三件套:Gudhi,Scikit-Learn和Tensorflow(附...
    今天,我想強調下在機器學習中拓撲數據分析(TDA,Topological Data Analysis)的力量,並展示如何配合三個Python庫:Gudhi,Scikit-Learn和Tensorflow進行實踐。拓撲數據分析?首先,讓我們談談TDA。它是數據科學中相對小眾的一個領域,尤其是當與機器學習和深度學習對比的時候。但是它正迅速成長,並引起了數據科學家的注意。
  • Python機器學習5:使用scikit-learn實現三種集成學習Bagging算法
    如果你在解決一個問題時實現了多種模型,但是每個模型的效果都差不多,但是你想要進一步提升最後預測效果,那麼本文將強烈建議你使用集成學習算法來實現!集成學習算法指的是將已有的多種模型綜合起來,實現最終分類或者回歸。一般而言,集成學習可以提高原有算法模型的準確性。
  • 【強化學習實戰】基於gym和tensorflow的強化學習算法實現
    1新智元推薦【新智元導讀】知乎專欄強化學習大講堂作者郭憲博士開講《強化學習從入門到進階》,我們為您節選了其中的第二節《基於gym和tensorflow的強化學習算法實現》,希望對您有所幫助。同時,由郭憲博士等擔任授課教師的深度強化學習國慶集訓營也將於 10 月 2 日— 6 日在北京舉辦。
  • 乾貨| 請收下這份2018學習清單:150個最好的機器學習,NLP和Python...
    在今年秋季開始準備博士項目的時候,我已經精選了一些有關機器學習和NLP的優質網絡資源。一般我會找一個有意思的教程或者視頻,再由此找到三四個,甚至更多的教程或者視頻。猛回頭,發現標收藏夾又多了20個資源待我學習(推薦提升效率工具Tab Bundler)。
  • ...請收下這份2018學習清單:150個最好的機器學習,NLP和Python教程
    在今年秋季開始準備博士項目的時候,我已經精選了一些有關機器學習和NLP的優質網絡資源。一般我會找一個有意思的教程或者視頻,再由此找到三四個,甚至更多的教程或者視頻。猛回頭,發現標收藏夾又多了20個資源待我學習(推薦提升效率工具Tab Bundler)。
  • 乾貨 | 請收下這份2018學習清單:150個最好的機器學習,NLP和Python教程
    在今年秋季開始準備博士項目的時候,我已經精選了一些有關機器學習和NLP的優質網絡資源。一般我會找一個有意思的教程或者視頻,再由此找到三四個,甚至更多的教程或者視頻。猛回頭,發現標收藏夾又多了20個資源待我學習(推薦提升效率工具Tab Bundler)。
  • 基於RTX2060構建TensorFlow-gpu(keras)學習平臺
    開始菜單運行anaconda navigator檢查是否安裝了notebook(默認有安裝)三、安裝tensorflow/keras在激活的環境中安裝:1. 如果機器上有gpu,則安裝gpu版本,沒有GPU就安裝cpu版。
  • 回歸、分類與聚類:三大方向剖解機器學習算法的優缺點(附Python和R...
    對機器學習算法進行分類不是一件容易的事情,總的來看,有如下幾種方式:生成與判別、參數與非參數、監督與非監督等等。然而,就實踐經驗來看,這些都不是實戰過程中最有效的分類算法的方式。因為對於應用機器學習而言,開發者一般會在腦海中有一個最終目標,比如預測一個結果或是對你的觀察進行分類。因此,我們想介紹另一種對算法進行分類的路數,其基於機器學習任務來分類。
  • 深度解讀TensorFlow,了解它的最新發展!
    ,並且支持GPU處理、python和C++語言,研發人員可以將它與docker等容器集成使用。Tensorboard是tensorflow內置的一個可視化工具,它通過將tensorflow程序輸出的日誌文件的信息可視化,使得tensorflow程序的理解、調試和優化更加簡單高效。Tensorboard的可視化依賴於tensorflow程序運行輸出的日誌文件,因而tensorboard和tensorflow程序在不同的進程中運行。
  • TensorFlow 中文資源全集,學習路徑推薦
    入門教程,簡單的模型學習和運行。實戰項目,根據自己的需求進行開發。>開始學習:https://tensorflow.google.cn/get_started/MNIST 針對初學者的字體識別:https://tensorflow.google.cn/get_started/mnist/beginnersMNIST 針對專業的深度字體識別:https://tensorflow.google.cn
  • 利用Spark 和 scikit-learn 將你的模型訓練加快 100 倍
    當我們使用 Spark 進行數據處理時,我們首選的機器學習框架是 scikit-learn。隨著計算機變得越來越便宜,機器學習解決方案的上市時間變得越來越關鍵,我們探索了加快模型訓練的各種方法。其中一個解決方案是將 Spark 和 scikit-learn 中的元素組合到我們自己的混合解決方案中。
  • TensorFlow 2.1指南:keras模式、渴望模式和圖形模式(附代碼)
    經過一些實驗後,我發現在TensorFlow 2.1中,有3種構建模型的方法:Keras模式(tf.keras):基於圖形定義,並在以後運行圖形。渴望模式:基於定義執行的所有迭代定義圖的操作。圖形模式(tf.function):之前兩種方法的混合。讓我們來看看代碼。
  • CDA承接的全球頂級機器學習Scikit-learn 中文社區上線啦!
    基於CDA全國教研團隊近5年的Scikit-learn課程研發經驗,為了響應越來越多的數據科學愛好者的學習需求,CDA通過一年多的Scikit-learn文檔的翻譯和認真校對,並在CDA研發部門的密切配合下,Scikit-learn中文社區終於上線了。
  • 10大機器學習算法,看懂你就是數據科學家
    今天我們就來聊聊,每一位數據科技家都應該了解的10大機器學習算法。下面是關於普遍機器學習算法和快速資源的風暴之旅,準好了嗎?燒腦挑戰開始: 1. 主成分分析(PCA)/奇異值分解(SVD)PCA是一種非監督學習,用來理解由向量組成的數據集的全局特性的方法。
  • 從星際2深度學習環境到神經機器翻譯,上手機器學習這些開源項目必...
    算法:如何處理和分析數據機器學習算法可利用數據執行特定的任務,最常見的機器學習算法有如下幾種:1.監督學習。監督學習使用以及標註過的和結構化的數據,通過制定一組輸入數據集合所需的輸出,機器可以學習如何識別目標並且映射到其他的學習任務上。
  • TensorFlow(Keras)中的正則化技術及其實現(附代碼)
    過度擬合:此問題涉及算法過於精確地預測在訓練過程中觀察和學習到的模式實例,從而預測向其呈現的模式的新實例。這可能導致機器學習算法無法準確地推廣到看不見的數據。如果訓練數據不能準確表示測試數據的分布,則可能會發生過度擬合。
  • TensorFlow 資源大全中文版
    ,請點擊 → 這裡了解詳情jtoy 發起整理的 TensorFlow 資源,包含一些很棒的 TensorFlow 工程、庫、項目等。生成手寫體 – 實現Alex Grave的論文中關於生成手寫體的部分TensorFlow實現神經圖靈機 – TensorFlow實現神經圖靈機基於物體搜索和過濾視頻 – 使用卷積神經網絡基於視頻中的物品、地點等來搜索、過濾和描述視頻使用TensorFlow來轉換莎士比亞作品和現代版本的英語 – 實現莎士比亞作品和現代版本的英語的單語轉換聊天機器人 – 一個
  • TensorFlow和Caffe、MXNet、Keras等其他深度學習框架的對比
    僅在數據挖據工具鏈上,Python 就有 NumPy、SciPy、Pandas、Scikit-learn、XGBoost 等組件,做數據採集和預處理都非常方便,並且之後的模型訓練階段可以和 TensorFlow 等基於 Python 的深度學習框架完美銜接。