《Scikit-Learn與TensorFlow機器學習實用指南》 第07章 集成學習和隨機森林


(第一部分 機器學習基礎(chǔ))
第01章 機器學習概覽
第02章 一個完整的機器學習項目(上)
第02章 一個完整的機器學習項目(下)
第03章 分類
第04章 訓練模型
第05章 支持向量機
第06章 決策樹
第07章 集成學習和隨機森林
第08章 降維
(第二部分 神經(jīng)網(wǎng)絡(luò)和深度學習)
第9章 啟動和運行TensorFlow
第10章 人工神經(jīng)網(wǎng)絡(luò)
第11章 訓練深度神經(jīng)網(wǎng)絡(luò)(上)
第11章 訓練深度神經(jīng)網(wǎng)絡(luò)(下)
第12章 設(shè)備和服務(wù)器上的分布式 TensorFlow
第13章 卷積神經(jīng)網(wǎng)絡(luò)
第14章 循環(huán)神經(jīng)網(wǎng)絡(luò)
第15章 自編碼器
第16章 強化學習(上)
第16章 強化學習(下)


假設(shè)你去隨機問很多人一個很復雜的問題,然后把它們的答案合并起來为居。通常情況下你會發(fā)現(xiàn)這個合并的答案比一個專家的答案要好。這就叫做群體智慧。同樣的,如果你合并了一組分類器的預(yù)測(像分類或者回歸),你也會得到一個比單一分類器更好的預(yù)測結(jié)果。這一組分類器就叫做集成;因此埠褪,這個技術(shù)就叫做集成學習,一個集成學習算法就叫做集成方法挤庇。

例如钞速,你可以訓練一組決策樹分類器,每一個都在一個隨機的訓練集上嫡秕。為了去做預(yù)測渴语,你必須得到所有單一樹的預(yù)測值,然后通過投票(例如第六章的練習)來預(yù)測類別昆咽。例如一種決策樹的集成就叫做隨機森林驾凶,它除了簡單之外也是現(xiàn)今存在的最強大的機器學習算法之一。

向我們在第二章討論的一樣掷酗,我們會在一個項目快結(jié)束的時候使用集成算法调违,一旦你建立了一些好的分類器,就把他們合并為一個更好的分類器泻轰。事實上技肩,在機器學習競賽中獲得勝利的算法經(jīng)常會包含一些集成方法。

在本章中我們會討論一下特別著名的集成方法浮声,包括 bagging, boosting, stacking虚婿,和其他一些算法。我們也會討論隨機森林泳挥。

投票分類

假設(shè)你已經(jīng)訓練了一些分類器然痊,每一個都有 80% 的準確率。你可能有了一個邏輯回歸屉符、或一個 SVM剧浸、或一個隨機森林,或者一個 KNN分類器筑煮,或許還有更多(詳見圖 7-1)

圖7-1. 訓練多種分類器

一個非常簡單的創(chuàng)建一個更好的分類器的方法就是去整合每一個分類器的預(yù)測然后經(jīng)過投票預(yù)測分類辛蚊。這種分類器叫做硬投票分類器(詳見圖 7-2)粤蝎。

圖7-2. 硬投票分類器

令人驚奇的是這種投票分類器得出的結(jié)果經(jīng)常會比集成中最好的一個分類器結(jié)果更好真仲。事實上,即使每一個分類器都是一個弱學習器(意味著它們也就比瞎猜好點)初澎,集成后仍然是一個強學習器(高準確率)秸应,只要有足夠數(shù)量的弱學習者虑凛,他們就足夠多樣化。

這怎么可能软啼?接下來的分析將幫助你解決這個疑問桑谍。假設(shè)你有一個有偏差的硬幣,他有 51% 的幾率為正面祸挪,49% 的幾率為背面锣披。如果你實驗 1000 次,你會得到差不多 510 次正面贿条,490 次背面雹仿,因此大多數(shù)都是正面。如果你用數(shù)學計算整以,你會發(fā)現(xiàn)在實驗 1000 次后胧辽,正面為多數(shù)的概率接近 75%。實驗的次數(shù)越多公黑,正面為多數(shù)的比例越大(例如你試驗了 10000 次邑商,總體比例可能性就會達到 97%)。這是因為大數(shù)定律 :當你一直用硬幣實驗時凡蚜,正面的比例會越來越接近 51%人断。圖 7-3 展示了始終有偏差的硬幣實驗。你可以看到當實驗次數(shù)上升時朝蜘,正面的概率接近于 51%含鳞。最終所有 10 種實驗都會收斂到 51%,它們都大于 50%芹务。

圖7-3. 大數(shù)定律

同樣的蝉绷,假設(shè)你創(chuàng)建了一個包含 1000 個分類器的集成模型,其中每個分類器的正確率只有 51%(僅比瞎猜好一點點)枣抱。如果你用投票去預(yù)測類別熔吗,你可能得到 75% 的準確率!然而佳晶,這僅僅在所有的分類器都獨立運行的很好桅狠、不會發(fā)生有相關(guān)性的錯誤的情況下才會這樣,然而每一個分類器都在同一個數(shù)據(jù)集上訓練轿秧,導致其很可能會發(fā)生這樣的錯誤中跌。他們可能會犯同一種錯誤,所以也會有很多票投給了錯誤類別導致集成的準確率下降菇篡。

如果使每一個分類器都獨立自主的分類漩符,那么集成模型會工作的很好。得到多樣的分類器的方法之一就是用完全不同的算法驱还,這會使它們會做出不同種類的錯誤嗜暴,但會提高集成的正確率凸克。

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

>>> from sklearn.ensemble import RandomForestClassifier 
>>> from sklearn.ensemble import VotingClassifier 
>>> from sklearn.linear_model import LogisticRegression 
>>> from 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.864 
RandomForestClassifier 0.872 
SVC 0.888 
VotingClassifier 0.896 

你看闷沥!投票分類器比其他單獨的分類器表現(xiàn)的都要好萎战。

如果所有的分類器都能夠預(yù)測類別的概率(例如他們有一個predict_proba()方法),那么你就可以讓 sklearn 以最高的類概率來預(yù)測這個類舆逃,平均在所有的分類器上蚂维。這種方式叫做軟投票。他經(jīng)常比硬投票表現(xiàn)的更好路狮,因為它給予高自信的投票更大的權(quán)重鸟雏。你可以通過把voting="hard"設(shè)置為voting="soft"來保證分類器可以預(yù)測類別概率。然而這不是 SVC 類的分類器默認的選項孝鹊,所以你需要把它的probability hyperparameter設(shè)置為True(這會使 SVC 使用交叉驗證去預(yù)測類別概率,其降低了訓練速度柳骄,但會添加predict_proba()方法)耐薯。如果你修改了之前的代碼去使用軟投票丝里,你會發(fā)現(xiàn)投票分類器正確率高達 91%

Bagging 和 Pasting

就像之前講到的曲初,可以通過使用不同的訓練算法去得到一些不同的分類器。另一種方法就是對每一個分類器都使用相同的訓練算法杯聚,但是在不同的訓練集上去訓練它們臼婆。有放回采樣被稱為裝袋(Bagging,是 bootstrap aggregating 的縮寫)幌绍。無放回采樣稱為粘貼(pasting)颁褂。

換句話說,Bagging 和 Pasting 都允許在多個分類器上對訓練集進行多次采樣傀广,但只有 Bagging 允許對同一種分類器上對訓練集進行進行多次采樣颁独。采樣和訓練過程如圖7-4所示。

圖7-4. 粘貼/裝袋訓練集采樣和訓練

當所有的分類器被訓練后誓酒,集成可以通過對所有分類器結(jié)果的簡單聚合來對新的實例進行預(yù)測病往。聚合函數(shù)通常對分類是統(tǒng)計模式(例如硬投票分類器)或者對回歸是平均榕栏。每一個單獨的分類器在如果在原始訓練集上都是高偏差妨托,但是聚合降低了偏差和方差敦腔。通常情況下判族,集成的結(jié)果是有一個相似的偏差沃缘,但是對比與在原始訓練集上的單一分類器來講有更小的方差。

正如你在圖 7-4 上所看到的敬扛,分類器可以通過不同的 CPU 核或其他的服務(wù)器一起被訓練急侥。相似的铝宵,分類器也可以一起被制作拼岳。這就是為什么 Bagging 和 Pasting 是如此流行的原因之一:它們的可擴展性很好耐版。

在 sklearn 中的 Bagging 和 Pasting

sklearn 為 Bagging 和 Pasting 提供了一個簡單的API:BaggingClassifier類(或者對于回歸可以是BaggingRegressor腺阳。接下來的代碼訓練了一個 500 個決策樹分類器的集成焙蚓,每一個都是在數(shù)據(jù)集上有放回采樣 100 個訓練實例下進行訓練(這是 Bagging 的例子知残,如果你想嘗試 Pasting印蔗,就設(shè)置bootstrap=False)耙厚。n_jobs參數(shù)告訴 sklearn 用于訓練和預(yù)測所需要 CPU 核的數(shù)量型宝。(-1 代表著 sklearn 會使用所有空閑核):

>>>from sklearn.ensemble import BaggingClassifier 
>>>from sklearn.tree import DecisionTreeClassifier
>>>bag_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)

筆記
如果基分類器可以預(yù)測類別概率(例如它擁有predict_proba()方法),那么BaggingClassifier會自動的運行軟投票,這是決策樹分類器的情況。

圖 7-5 對比了單一決策樹的決策邊界和 Bagging 集成 500 個樹的決策邊界岁疼,兩者都在 moons 數(shù)據(jù)集上訓練椭住。正如你所看到的葫掉,集成的分類比起單一決策樹的分類產(chǎn)生情況更好:集成有一個可比較的偏差但是有一個較小的方差(它在訓練集上的錯誤數(shù)目大致相同挪挤,但決策邊界較不規(guī)則)星立。

圖7-5. 單一決策樹vs500棵樹的bagging集成

Bootstrap 在每個預(yù)測器被訓練的子集中引入了更多的分集辕坝,所以 Bagging 結(jié)束時的偏差比 Pasting 更高纺酸,但這也意味著預(yù)測因子最終變得不相關(guān)樊诺,從而減少了集合的方差顿膨。總體而言取劫,Bagging 通常會導致更好的模型,這就解釋了為什么它通常是首選的扯俱。然而为流,如果你有空閑時間和 CPU 功率莲祸,可以使用交叉驗證來評估 Bagging 和 Pasting 哪一個更好抹估。

Out-of-Bag 評價

對于 Bagging 來說语泽,一些實例可能被一些分類器重復采樣妒挎,但其他的有可能不會被采樣期虾。BaggingClassifier默認采樣。BaggingClassifier默認是有放回的采樣m個實例 (bootstrap=True)驯嘱,其中m是訓練集的大小镶苞,這意味著平均下來只有63%的訓練實例被每個分類器采樣,剩下的37%個沒有被采樣的訓練實例就叫做 Out-of-Bag 實例。注意對于每一個的分類器它們的 37% 不是相同的。

因為在訓練中分類器從來沒有看到過 oob 實例,所以它可以在這些實例上進行評估晨汹,而不需要單獨的驗證集或交叉驗證。你可以拿出每一個分類器的 oob 來評估集成本身仙畦。

在 sklearn 中瓮具,你可以在訓練后需要創(chuàng)建一個BaggingClassifier時設(shè)置oob_score=True來自動評估。接下來的代碼展示了這個操作盹牧。評估結(jié)果通過變量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.93066666666666664 

根據(jù)這個 oob 評估啡莉,BaggingClassifier可以再測試集上達到93.1%的準確率右遭,讓我們修改一下:

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

我們在測試集上得到了 93.6% 的準確率彬向,足夠接近了眯娱!

對于每個訓練實例 oob 決策函數(shù)也可通過oob_decision_function_變量來展示句柠。在這種情況下(當基決策器有predict_proba()時)決策函數(shù)會對每個訓練實例返回類別概率亭珍。例如电爹,oob 評估預(yù)測第二個訓練實例有 60.6% 的概率屬于正類(39.4% 屬于負類):

>>> bag_clf.oob_decision_function_ 
array([[ 0.,  1.], [ 0.60588235,  0.39411765],[ 1., 0. ], 
...  [ 1. ,  0. ],[ 0.,  1.],[ 0.48958333,  0.51041667]]) 

隨機貼片與隨機子空間

BaggingClassifier也支持采樣特征。它被兩個超參數(shù)max_featuresbootstrap_features控制苔货。他們的工作方式和max_samplesbootstrap一樣犀概,但這是對于特征采樣而不是實例采樣。因此夜惭,每一個分類器都會被在隨機的輸入特征內(nèi)進行訓練姻灶。

當你在處理高維度輸入下(例如圖片)此方法尤其有效。對訓練實例和特征的采樣被叫做隨機貼片诈茧。保留了所有的訓練實例(例如bootstrap=Falsemax_samples=1.0)产喉,但是對特征采樣(bootstrap_features=True并且/或者max_features小于 1.0)叫做隨機子空間。

采樣特征導致更多的預(yù)測多樣性,用高偏差換低方差曾沈。

隨機森林

正如我們所討論的这嚣,隨機森林是決策樹的一種集成,通常是通過 bagging 方法(有時是 pasting 方法)進行訓練塞俱,通常用max_samples設(shè)置為訓練集的大小姐帚。建立一個BaggingClassifier,然后把它放入 DecisionTreeClassifier 障涯」奁欤或者,你可以使用更方便的也是對決策樹優(yōu)化過的RandomForestClassifier(對于回歸是RandomForestRegressor)唯蝶。接下來的代碼訓練了帶有 500 個樹(每個被限制為 16 葉子結(jié)點)的決策森林九秀,使用所有空閑的 CPU 核:

>>>from sklearn.ensemble import RandomForestClassifier
>>>rnd_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的所有超參數(shù)(決定樹怎么生長)生棍,把BaggingClassifier的超參數(shù)加起來來控制集成本身颤霎。

隨機森林算法在樹生長時引入了額外的隨機;與在節(jié)點分裂時需要找到最好分裂特征相反(詳見第六章)涂滴,它在一個隨機的特征集中找最好的特征友酱。它導致了樹的差異性,并且再一次用高偏差換低方差柔纵,總的來說是一個更好的模型缔杉。以下是BaggingClassifier,大致相當于之前的randomforestclassifier

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

極端隨機樹

當你在隨機森林上生長樹時搁料,在每個結(jié)點分裂時只考慮隨機特征集上的特征(正如之前討論過的一樣)或详。相比于找到更好的特征我們可以通過使用對特征使用隨機閾值使樹更加隨機(像規(guī)則決策樹一樣)。

這種極端隨機的樹被簡稱為 Extremely Randomized Trees(極端隨機樹)郭计,或者更簡單的稱為 Extra-Tree霸琴。再一次用高偏差換低方差。它還使得 Extra-Tree 比規(guī)則的隨機森林更快地訓練昭伸,因為在每個節(jié)點上找到每個特征的最佳閾值是生長樹最耗時的任務(wù)之一梧乘。

你可以使用 sklearn 的ExtraTreesClassifier來創(chuàng)建一個 Extra-Tree 分類器。他的 API 跟RandomForestClassifier是相同的庐杨,相似的选调, ExtraTreesRegressorRandomForestRegressor也是相同的 API。

我們很難去分辨ExtraTreesClassifierRandomForestClassifier到底哪個更好灵份。通常情況下是通過交叉驗證來比較它們(使用網(wǎng)格搜索調(diào)整超參數(shù))仁堪。

特征重要度

最后,如果你觀察一個單一決策樹填渠,重要的特征會出現(xiàn)在更靠近根部的位置弦聂,而不重要的特征會經(jīng)常出現(xiàn)在靠近葉子的位置鸟辅。因此我們可以通過計算一個特征在森林的全部樹中出現(xiàn)的平均深度來預(yù)測特征的重要性。sklearn 在訓練后會自動計算每個特征的重要度横浑。你可以通過feature_importances_變量來查看結(jié)果剔桨。例如如下代碼在 iris 數(shù)據(jù)集(第四章介紹)上訓練了一個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.112492250999
sepal width (cm) 0.0231192882825 
petal length (cm) 0.441030464364 
petal width (cm) 0.423357996355 

相似的,如果你在 MNIST 數(shù)據(jù)及上訓練隨機森林分類器(在第三章上介紹)萨脑,然后畫出每個像素的重要性隐轩,你可以得到圖 7-6 的圖片。

圖7-6. MNIST數(shù)據(jù)集像素的重要性(根據(jù)隨機森林分類器)

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

提升

提升(Boosting,最初稱為假設(shè)增強)指的是可以將幾個弱學習者組合成強學習者的集成方法鹊杖。對于大多數(shù)的提升方法的思想就是按順序去訓練分類器悴灵,每一個都要嘗試修正前面的分類。現(xiàn)如今已經(jīng)有很多的提升方法了骂蓖,但最著名的就是 Adaboost(適應(yīng)性提升积瞒,是 Adaptive Boosting 的簡稱) 和 Gradient Boosting(梯度提升)。讓我們先從 Adaboost 說起登下。

Adaboost

使一個新的分類器去修正之前分類結(jié)果的方法就是對之前分類結(jié)果不對的訓練實例多加關(guān)注茫孔。這導致新的預(yù)測因子越來越多地聚焦于這種情況。這是 Adaboost 使用的技術(shù)被芳。

舉個例子缰贝,去構(gòu)建一個 Adaboost 分類器,第一個基分類器(例如一個決策樹)被訓練然后在訓練集上做預(yù)測畔濒,在誤分類訓練實例上的權(quán)重就增加了剩晴。第二個分類機使用更新過的權(quán)重然后再一次訓練,權(quán)重更新篓冲,以此類推(詳見圖 7-7)

圖7-7. 用實例權(quán)重更新進行AdaBoost順序訓練

圖 7-8 顯示連續(xù)五次預(yù)測的 moons 數(shù)據(jù)集的決策邊界(在本例中李破,每一個分類器都是高度正則化帶有 RBF 核的 SVM)。第一個分類器誤分類了很多實例壹将,所以它們的權(quán)重被提升了嗤攻。第二個分類器因此對這些誤分類的實例分類效果更好,以此類推诽俯。右邊的圖代表了除了學習率減半外(誤分類實例權(quán)重每次迭代上升一半)相同的預(yù)測序列妇菱。你可以看出承粤,序列學習技術(shù)與梯度下降很相似,除了調(diào)整單個預(yù)測因子的參數(shù)以最小化代價函數(shù)之外闯团,AdaBoost 增加了集合的預(yù)測器辛臊,逐漸使其更好。

圖7-8. 連續(xù)預(yù)測的決策邊界

一旦所有的分類器都被訓練后房交,除了分類器根據(jù)整個訓練集上的準確率被賦予的權(quán)重外彻舰,集成預(yù)測就非常像Bagging和Pasting了。

警告
序列學習技術(shù)的一個重要的缺點就是:它不能被并行化(只能按步驟)候味,因為每個分類器只能在之前的分類器已經(jīng)被訓練和評價后再進行訓練刃唤。因此,它不像Bagging和Pasting一樣白群。

讓我們詳細看一下 Adaboost 算法尚胞。每一個實例的權(quán)重wi初始都被設(shè)為1/m。第一個分類器被訓練帜慢,然后他的權(quán)重誤差率r1在訓練集上算出笼裳,詳見公式 7-1。

公式7-1:第`j`個分類器的權(quán)重誤差率

其中 \hat{y_{j}}^{(i)} 是第j個分類器對于第i實例的預(yù)測粱玲。

分類器的權(quán)重 α_{j} 隨后用公式 7-2 計算出來躬柬。其中η是超參數(shù)學習率(默認為 1)。分類器準確率越高密幔,它的權(quán)重就越高楔脯。如果它只是瞎猜,那么它的權(quán)重會趨近于 0胯甩。然而昧廷,如果它總是出錯(比瞎猜的幾率都低),它的權(quán)重會變?yōu)樨摂?shù)偎箫。

公式 7-2. 預(yù)測器權(quán)重

接下來實例的權(quán)重會按照公式 7-3 更新:誤分類的實例權(quán)重會被提升木柬。

公式7-3 權(quán)重更新規(guī)則

公式7-3. 權(quán)重更新規(guī)則

隨后所有實例的權(quán)重都被歸一化(例如被 \sum_{i=1}^{m}w^{i} 整除)。

最后淹办,一個新的分類器通過更新過的權(quán)重訓練眉枕,整個過程被重復(新的分類器權(quán)重被計算,實例的權(quán)重被更新怜森,隨后另一個分類器被訓練速挑,以此類推)。當規(guī)定的分類器數(shù)量達到或者最好的分類器被找到后算法就會停止副硅。

為了進行預(yù)測姥宝,Adaboost 通過分類器權(quán)重 α_{j} 簡單計算了所有的分類器和權(quán)重。預(yù)測類別會是權(quán)重投票中主要的類別恐疲。(詳見公式 7-4)

公式7-4. Adaboost 分類器

其中N是分類器的數(shù)量腊满。

sklearn 通常使用 Adaboost 的多分類版本 SAMME(這就代表了 分段加建模使用多類指數(shù)損失函數(shù))套么。如果只有兩類別,那么 SAMME 是與 Adaboost 相同的碳蛋。如果分類器可以預(yù)測類別概率(例如如果它們有predict_proba())胚泌,如果 sklearn 可以使用 SAMME 叫做SAMME.R的變量(R 代表“REAL”),這種依賴于類別概率的通常比依賴于分類器的更好肃弟。

接下來的代碼訓練了使用 sklearn 的AdaBoostClassifier基于 200 個決策樹樁的Adaboost 分類器(正如你說期待的玷室,對于回歸也有AdaBoostRegressor)。一個決策樹樁是max_depth=1的決策樹-換句話說愕乎,是一個單一的決策節(jié)點加上兩個葉子結(jié)點阵苇。這就是AdaBoostClassifier的默認基分類器:

>>>from sklearn.ensemble import AdaBoostClassifier
>>>ada_clf = AdaBoostClassifier(DecisionTreeClassifier(max_depth=1), n_estimators=200,algorithm="SAMME.R", learning_rate=0.5) 
>>>ada_clf.fit(X_train, y_train)

如果你的 Adaboost 集成過擬合了訓練集,你可以嘗試減少基分類器的數(shù)量或者對基分類器使用更強的正則化感论。

梯度提升

另一個非常著名的提升算法是梯度提升。與 Adaboost 一樣紊册,梯度提升也是通過向集成中逐步增加分類器運行的比肄,每一個分類器都修正之前的分類結(jié)果。然而囊陡,它并不像 Adaboost 那樣每一次迭代都更改實例的權(quán)重芳绩,這個方法是去使用新的分類器去擬合前面分類器預(yù)測的殘差

讓我們通過一個使用決策樹當做基分類器的簡單的回歸例子(回歸當然也可以使用梯度提升)學習撞反。這叫做梯度提升回歸樹(GBRT妥色,Gradient Tree Boosting 或者 Gradient Boosted Regression Trees)。首先我們用DecisionTreeRegressor去擬合訓練集(例如一個有噪二次訓練集):

>>>from sklearn.tree import DecisionTreeRegressor 
>>>tree_reg1 = DecisionTreeRegressor(max_depth=2) 
>>>tree_reg1.fit(X, y) 

現(xiàn)在在第一個分類器的殘差上訓練第二個分類器:

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

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

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

現(xiàn)在我們有了一個包含三個回歸器的集成遏片。它可以通過集成所有樹的預(yù)測來在一個新的實例上進行預(yù)測嘹害。

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

圖7-9在左欄展示了這三個樹的預(yù)測,在右欄展示了集成的預(yù)測吮便。在第一行笔呀,集成只有一個樹,所以它與第一個樹的預(yù)測相似髓需。在第二行许师,一個新的樹在第一個樹的殘差上進行訓練。在右邊欄可以看出集成的預(yù)測等于前兩個樹預(yù)測的和僚匆。相同的微渠,在第三行另一個樹在第二個數(shù)的殘差上訓練。你可以看到集成的預(yù)測會變的更好咧擂。

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

>>>from sklearn.ensemble import GradientBoostingRegressor
>>>gbrt = GradientBoostingRegressor(max_depth=2, n_estimators=3, learning_rate=1.0) 
>>>gbrt.fit(X, y)
圖7-9. 梯度提升

超參數(shù)learning_rate 確立了每個樹的貢獻。如果你把它設(shè)置為一個很小的樹善已,例如 0.1,在集成中就需要更多的樹去擬合訓練集,但預(yù)測通常會更好的猛。這個正則化技術(shù)叫做 shrinkage。圖 7-10 展示了兩個在低學習率上訓練的 GBRT 集成:其中左側(cè)是一個沒有足夠樹去擬合訓練集的樹岂却,右側(cè)是有過多的樹過擬合訓練集的樹。

圖7-10. 沒有足夠預(yù)測器(左)和有過多預(yù)測器(右)的GBRT集成

為了找到樹的最優(yōu)數(shù)量,你可以使用早停技術(shù)(第四章討論過)。最簡單使用這個技術(shù)的方法就是使用staged_predict():它在訓練的每個階段(用一棵樹,兩棵樹等)返回一個迭代器渣磷。加下來的代碼用 120 個樹訓練了一個 GBRT 集成竟宋,然后在訓練的每個階段驗證錯誤以找到樹的最佳數(shù)量逐样,最后使用 GBRT 樹的最優(yōu)數(shù)量訓練另一個集成:

>>>import numpy as np 
>>>from sklearn.model_selection import train_test_split
>>>from 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)
>>>gbrt_best = GradientBoostingRegressor(max_depth=2,n_estimators=bst_n_estimators) 
>>>gbrt_best.fit(X_train, y_train) 

驗證錯誤在圖 7-11 的左側(cè)展示挪捕,最優(yōu)模型預(yù)測被展示在右側(cè)滞乙。

圖7-11. 用早停調(diào)節(jié)樹的數(shù)量

你也可以早早的停止訓練來實現(xiàn)早停(而不是先在一大堆樹中訓練,然后再回頭去找最佳數(shù)量)。你可以通過設(shè)置warm_start=True來實現(xiàn) ,這使得當fit()方法被調(diào)用時 sklearn 保留現(xiàn)有樹此虑,并允許增量訓練。接下來的代碼在當一行中的五次迭代驗證錯誤沒有改善時會停止訓練:

>>>gbrt = GradientBoostingRegressor(max_depth=2, warm_start=True)
min_val_error = float("inf") 
error_going_up = 0 
for 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  # early stopping 

GradientBoostingRegressor也支持指定用于訓練每棵樹的訓練實例比例的超參數(shù)subsample荆隘。例如如果subsample=0.25晶渠,那么每個樹都會在 25% 隨機選擇的訓練實例上訓練。你現(xiàn)在也能猜出來胳徽,這也是個高偏差換低方差的作用。它同樣也加速了訓練。這個技術(shù)叫做隨機梯度提升

也可能對其他損失函數(shù)使用梯度提升衩婚。這是由損失超參數(shù)控制(見 sklearn 文檔)缓屠。

Stacking

本章討論的最后一個集成方法叫做 Stackingstacked generalization 的縮寫)储耐。這個算法基于一個簡單的想法:不使用瑣碎的函數(shù)(如硬投票)來聚合集合中所有分類器的預(yù)測,我們?yōu)槭裁床挥柧氁粋€模型來執(zhí)行這個聚合?圖 7-12 展示了這樣一個在新的回歸實例上預(yù)測的集成。底部三個分類器每一個都有不同的值(3.1热幔,2.7 和 2.9),然后最后一個分類器(叫做 blender 或者 meta learner )把這三個分類器的結(jié)果當做輸入然后做出最終決策(3.0)戈锻。

圖7-12 使用混合預(yù)測期合并預(yù)測

為了訓練這個 blender 留瞳,一個通用的方法是采用保持集璧微。讓我們看看它怎么工作荧止。首先,訓練集被分為兩個子集,第一個子集被用作訓練第一層(詳見圖 7-13).

圖7-13. 訓練第一層

接下來,第一層的分類器被用來預(yù)測第二個子集(保持集)(詳見 7-14)。這確保了預(yù)測結(jié)果很“干凈”,因為這些分類器在訓練的時候沒有使用過這些實例≌甸埽現(xiàn)在對在保持集中的每一個實例都有三個預(yù)測值。我們現(xiàn)在可以使用這些預(yù)測結(jié)果作為輸入特征來創(chuàng)建一個新的訓練集(這使得這個訓練集是三維的),并且保持目標數(shù)值不變旨别。隨后 blender 在這個新的訓練集上訓練剔难,因此非迹,它學會了預(yù)測第一層預(yù)測的目標值吵冒。

圖7-14. 訓練混合器

顯然我們可以用這種方法訓練不同的 blender (例如一個線性回歸,另一個是隨機森林等等):我們得到了一層 blender 。訣竅是將訓練集分成三個子集:第一個子集用來訓練第一層吴裤,第二個子集用來創(chuàng)建訓練第二層的訓練集(使用第一層分類器的預(yù)測值),第三個子集被用來創(chuàng)建訓練第三層的訓練集(使用第二層分類器的預(yù)測值)。以上步驟做完了,我們可以通過逐個遍歷每個層來預(yù)測一個新的實例柜候。詳見圖 7-15.

圖7-15. 錯層stacking集成的預(yù)測

不幸的是渣刷,sklearn 并不直接支持 stacking 瞭吃,但是你自己組建是很容易的(看接下來的練習)股冗≡芘或者你也可以使用開源的項目例如 brewhttps://github.com/viisar/brew)。

練習

  1. 如果你在相同訓練集上訓練 5 個不同的模型,它們都有 95% 的準確率,那么你是否可以通過組合這個模型來得到更好的結(jié)果?如果可以那怎么做呢烘跺?如果不可以請給出理由砌左。
  2. 軟投票和硬投票分類器之間有什么區(qū)別屁擅?
  3. 是否有可能通過分配多個服務(wù)器來加速 bagging 集成系統(tǒng)的訓練痰哨?pasting 集成作谭,boosting 集成贝或,隨機森林酱床,或 stacking 集成怎么樣?
  4. out-of-bag 評價的好處是什么?
  5. 是什么使 Extra-Tree 比規(guī)則隨機森林更隨機呢簸淀?這個額外的隨機有什么幫助呢拧簸?那這個 Extra-Tree 比規(guī)則隨機森林誰更快呢?
  6. 如果你的 Adaboost 模型欠擬合,那么你需要怎么調(diào)整超參數(shù)?
  7. 如果你的梯度提升過擬合,那么你應(yīng)該調(diào)高還是調(diào)低學習率呢?
  8. 導入 MNIST 數(shù)據(jù)(第三章中介紹),把它切分進一個訓練集屈糊,一個驗證集雕薪,和一個測試集(例如 40000 個實例進行訓練,10000 個進行驗證,10000 個進行測試)。然后訓練多個分類器,例如一個隨機森林分類器,一個 Extra-Tree 分類器和一個 SVM。接下來,嘗試將它們組合成集成,使用軟或硬投票分類器來勝過驗證集上的所有集合。一旦找到了蚓土,就在測試集上實驗蜀漆。與單個分類器相比谅河,它的性能有多好?
  9. 從練習 8 中運行個體分類器來對驗證集進行預(yù)測确丢,并創(chuàng)建一個新的訓練集并生成預(yù)測:每個訓練實例是一個向量绷耍,包含來自所有分類器的圖像的預(yù)測集鲜侥,目標是圖像類別褂始。祝賀你,你剛剛訓練了一個 blender 描函,和分類器一起組成了一個疊加組合崎苗!現(xiàn)在讓我們來評估測試集上的集合狐粱。對于測試集中的每個圖像,用所有分類器進行預(yù)測胆数,然后將預(yù)測饋送到 blender 以獲得集合的預(yù)測肌蜻。它與你早期訓練過的投票分類器相比如何?

練習答案見附錄 A 必尼。


(第一部分 機器學習基礎(chǔ))
第01章 機器學習概覽
第02章 一個完整的機器學習項目(上)
第02章 一個完整的機器學習項目(下)
第03章 分類
第04章 訓練模型
第05章 支持向量機
第06章 決策樹
第07章 集成學習和隨機森林
第08章 降維
(第二部分 神經(jīng)網(wǎng)絡(luò)和深度學習)
第9章 啟動和運行TensorFlow
第10章 人工神經(jīng)網(wǎng)絡(luò)
第11章 訓練深度神經(jīng)網(wǎng)絡(luò)(上)
第11章 訓練深度神經(jīng)網(wǎng)絡(luò)(下)
第12章 設(shè)備和服務(wù)器上的分布式 TensorFlow
第13章 卷積神經(jīng)網(wǎng)絡(luò)
第14章 循環(huán)神經(jīng)網(wǎng)絡(luò)
第15章 自編碼器
第16章 強化學習(上)
第16章 強化學習(下)


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末蒋搜,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子判莉,更是在濱河造成了極大的恐慌豆挽,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,311評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件券盅,死亡現(xiàn)場離奇詭異帮哈,居然都是意外死亡,警方通過查閱死者的電腦和手機渗饮,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評論 2 382
  • 文/潘曉璐 我一進店門但汞,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人互站,你說我怎么就攤上這事私蕾。” “怎么了胡桃?”我有些...
    開封第一講書人閱讀 152,671評論 0 342
  • 文/不壞的土叔 我叫張陵踩叭,是天一觀的道長。 經(jīng)常有香客問我翠胰,道長容贝,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,252評論 1 279
  • 正文 為了忘掉前任之景,我火速辦了婚禮斤富,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘锻狗。我一直安慰自己满力,他們只是感情好,可當我...
    茶點故事閱讀 64,253評論 5 371
  • 文/花漫 我一把揭開白布轻纪。 她就那樣靜靜地躺著油额,像睡著了一般。 火紅的嫁衣襯著肌膚如雪刻帚。 梳的紋絲不亂的頭發(fā)上潦嘶,一...
    開封第一講書人閱讀 49,031評論 1 285
  • 那天,我揣著相機與錄音崇众,去河邊找鬼掂僵。 笑死航厚,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的锰蓬。 我是一名探鬼主播阶淘,決...
    沈念sama閱讀 38,340評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼互妓!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起坤塞,我...
    開封第一講書人閱讀 36,973評論 0 259
  • 序言:老撾萬榮一對情侶失蹤冯勉,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后摹芙,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體灼狰,經(jīng)...
    沈念sama閱讀 43,466評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,937評論 2 323
  • 正文 我和宋清朗相戀三年浮禾,在試婚紗的時候發(fā)現(xiàn)自己被綠了交胚。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,039評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡盈电,死狀恐怖蝴簇,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情匆帚,我是刑警寧澤熬词,帶...
    沈念sama閱讀 33,701評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站吸重,受9級特大地震影響互拾,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜嚎幸,卻給世界環(huán)境...
    茶點故事閱讀 39,254評論 3 307
  • 文/蒙蒙 一颜矿、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧嫉晶,春花似錦骑疆、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至舶担,卻和暖如春坡疼,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背衣陶。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工柄瑰, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留闸氮,地道東北人。 一個月前我還...
    沈念sama閱讀 45,497評論 2 354
  • 正文 我出身青樓教沾,卻偏偏與公主長得像蒲跨,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子授翻,可洞房花燭夜當晚...
    茶點故事閱讀 42,786評論 2 345

推薦閱讀更多精彩內(nèi)容