假設(shè)你去隨機(jī)問(wèn)很多人一個(gè)很復(fù)雜的問(wèn)題,然后把它們的答案合并起來(lái)。通常情況下你會(huì)發(fā)現(xiàn)這個(gè)合并的答案比一個(gè)專(zhuān)家的答案要好。這就叫做群體智慧。同樣的,如果你合并了一組分類(lèi)器的預(yù)測(cè)(像分類(lèi)或者回歸),你也會(huì)得到一個(gè)比單一分類(lèi)器更好的預(yù)測(cè)結(jié)果。這一組分類(lèi)器就叫做集成;因此,這個(gè)技術(shù)就叫做集成學(xué)習(xí),一個(gè)集成學(xué)習(xí)算法就叫做集成方法。
例如,你可以訓(xùn)練一組決策樹(shù)分類(lèi)器,每一個(gè)都在一個(gè)隨機(jī)的訓(xùn)練集上。為了去做預(yù)測(cè),你必須得到所有單一樹(shù)的預(yù)測(cè)值,然后通過(guò)投票(例如第六章的練習(xí))來(lái)預(yù)測(cè)類(lèi)別。例如一種決策樹(shù)的集成就叫做隨機(jī)森林,它除了簡(jiǎn)單之外也是現(xiàn)今存在的最強(qiáng)大的機(jī)器學(xué)習(xí)算法之一。
向我們?cè)诘诙掠懻摰囊粯?,我們?huì)在一個(gè)項(xiàng)目快結(jié)束的時(shí)候使用集成算法,一旦你建立了一些好的分類(lèi)器,就把他們合并為一個(gè)更好的分類(lèi)器。事實(shí)上,在機(jī)器學(xué)習(xí)競(jìng)賽中獲得勝利的算法經(jīng)常會(huì)包含一些集成方法。
在本章中我們會(huì)討論一下特別著名的集成方法,包括bagging,boosting,stacking,和其他一些算法。我們也會(huì)討論隨機(jī)森林。
1 投票分類(lèi)
假設(shè)你已經(jīng)訓(xùn)練了一些分類(lèi)器,每一個(gè)都有 80% 的準(zhǔn)確率。你可能有了一個(gè)邏輯斯蒂回歸、或一個(gè) SVM、或一個(gè)隨機(jī)森林,或者一個(gè) KNN,或許還有更多(詳見(jiàn)圖 7-1)

一個(gè)非常簡(jiǎn)單去創(chuàng)建一個(gè)更好的分類(lèi)器的方法就是去整合每一個(gè)分類(lèi)器的預(yù)測(cè)然后經(jīng)過(guò)投票去預(yù)測(cè)分類(lèi)。這種分類(lèi)器就叫做硬投票分類(lèi)器(詳見(jiàn)圖 7-2)。

令人驚奇的是這種投票分類(lèi)器得出的結(jié)果經(jīng)常會(huì)比集成中最好的一個(gè)分類(lèi)器結(jié)果更好。事實(shí)上,即使每一個(gè)分類(lèi)器都是一個(gè)弱學(xué)習(xí)器(意味著它們也就比瞎猜好點(diǎn)),集成后仍然是一個(gè)強(qiáng)學(xué)習(xí)器(高準(zhǔn)確率),只要有足夠數(shù)量的弱學(xué)習(xí)者,他們就足夠多樣化。
這怎么可能?接下來(lái)的分析將幫助你解決這個(gè)疑問(wèn)。假設(shè)你有一個(gè)有偏差的硬幣,他有 51% 的幾率為正面,49% 的幾率為背面。如果你實(shí)驗(yàn) 1000 次,你會(huì)得到差不多 510 次正面,490 次背面,因此大多數(shù)都是正面。如果你用數(shù)學(xué)計(jì)算,你會(huì)發(fā)現(xiàn)在實(shí)驗(yàn) 1000 次后,正面概率為 51% 的人比例為 75%。你實(shí)驗(yàn)的次數(shù)越多,正面的比例越大(例如你試驗(yàn)了 10000 次,總體比例可能性就會(huì)達(dá)到 97%)。這是因?yàn)?b>大數(shù)定律:當(dāng)你一直用硬幣實(shí)驗(yàn)時(shí),正面的比例會(huì)越來(lái)越接近 51%。圖 7-3 展示了始終有偏差的硬幣實(shí)驗(yàn)。你可以看到當(dāng)實(shí)驗(yàn)次數(shù)上升時(shí),正面的概率接近于 51%。最終所有 10 種實(shí)驗(yàn)都會(huì)收斂到 51%,它們都大于 50%。
heads_proba = 0.51coin_tosses = (np.random.rand(10000, 10) < heads_proba).astype(np.int32)cumulative_heads_ratio = np.cumsum(coin_tosses, axis=0) / np.arange(1, 10001).reshape(-1, 1)# law_of_large_numbers_plotplt.figure(figsize=(8,3.5))plt.plot(cumulative_heads_ratio)plt.plot([0, 10000], [0.51, 0.51],"k--", linewidth=2, label="51%")plt.plot([0, 10000], [0.5, 0.5],"k-", label="50%")plt.xlabel("Number of coin tosses")plt.ylabel("Heads ratio")plt.legend(loc="lower right")plt.axis([0, 10000, 0.42, 0.58])plt.show()

同樣的,假設(shè)你創(chuàng)建了一個(gè)包含 1000 個(gè)分類(lèi)器的集成模型,
其中每個(gè)分類(lèi)器的正確率只有 51%(僅比瞎猜好一點(diǎn)點(diǎn))。如果你用投票去預(yù)測(cè)類(lèi)別,你可能得到 75% 的準(zhǔn)確率!
然而,這僅僅在所有的分類(lèi)器都獨(dú)立運(yùn)行的很好、不會(huì)發(fā)生有相關(guān)性的錯(cuò)誤的情況下才會(huì)這樣,然而每一個(gè)分類(lèi)器都在同一個(gè)數(shù)據(jù)集上訓(xùn)練,導(dǎo)致其很可能會(huì)發(fā)生這樣的錯(cuò)誤。
他們可能會(huì)犯同一種錯(cuò)誤,所以也會(huì)有很多票投給了錯(cuò)誤類(lèi)別導(dǎo)致集成的準(zhǔn)確率下降。
如果使每一個(gè)分類(lèi)器都獨(dú)立自主的分類(lèi),那么集成模型會(huì)工作的很好。去得到多樣的分類(lèi)器的方法之一就是用完全不同的算法,這會(huì)使它們會(huì)做出不同種類(lèi)的錯(cuò)誤,這會(huì)提高集成的正確率
接下來(lái)的代碼創(chuàng)建和訓(xùn)練了在sklearn中的投票分類(lèi)器。這個(gè)分類(lèi)器由三個(gè)不同的分類(lèi)器組成:
fromsklearn.model_selectionimporttrain_test_splitfromsklearn.datasetsimportmake_moonsX, y = make_moons(n_samples=500, noise=0.30, random_state=42)X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=42)
fromsklearn.ensembleimportRandomForestClassifierfromsklearn.ensembleimportVotingClassifierfromsklearn.linear_modelimportLogisticRegressionfromsklearn.svmimportSVClog_clf = LogisticRegression(random_state=42)rnd_clf = RandomForestClassifier(random_state=42)svm_clf = SVC(random_state=42)voting_clf = VotingClassifier(? ? estimators=[('lr', log_clf), ('rf', rnd_clf), ('svc', svm_clf)],? ? voting='hard')
讓我們看一下在測(cè)試集上的準(zhǔn)確率:
fromsklearn.metricsimportaccuracy_scoreforclfin(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))LogisticRegression0.864RandomForestClassifier0.872SVC0.888VotingClassifier0.896
你看!投票分類(lèi)器比其他單獨(dú)的分類(lèi)器表現(xiàn)的都要好。
# 軟投票log_clf = LogisticRegression(random_state=42)rnd_clf = RandomForestClassifier(random_state=42)svm_clf = SVC(probability=True, random_state=42)voting_clf = VotingClassifier(? ? estimators=[('lr', log_clf), ('rf', rnd_clf), ('svc', svm_clf)],? ? voting='soft')voting_clf.fit(X_train, y_train)VotingClassifier(estimators=[('lr', LogisticRegression(C=1.0, class_weight=None, dual=False, fit_intercept=True,? ? ? ? ? intercept_scaling=1, max_iter=100, multi_class='ovr', n_jobs=1,? ? ? ? ? penalty='l2', random_state=42, solver='liblinear', tol=0.0001,? ? ? ? ? verbose=0, warm_start=False)), ('rf', RandomFor...bf',
? max_iter=-1, probability=True, random_state=42, shrinking=True,
? tol=0.001, verbose=False))],
? ? ? ? flatten_transform=None, n_jobs=1, voting='soft', weights=None)
fromsklearn.metricsimportaccuracy_scoreforclfin(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))LogisticRegression0.864RandomForestClassifier0.872SVC0.888VotingClassifier0.912
如果所有的分類(lèi)器都能夠預(yù)測(cè)類(lèi)別的概率(例如他們有一個(gè)predict_proba()方法),那么你就可以讓sklearn以最高的類(lèi)概率來(lái)預(yù)測(cè)這個(gè)類(lèi),平均在所有的分類(lèi)器上。這種方式叫做軟投票。
他經(jīng)常比硬投票表現(xiàn)的更好,因?yàn)樗?b>給予高自信的投票更大的權(quán)重。你可以通過(guò)把voting="hard"設(shè)置為voting="soft"來(lái)保證分類(lèi)器可以預(yù)測(cè)類(lèi)別概率。然而這不是 SVC 類(lèi)的分類(lèi)器默認(rèn)的選項(xiàng),所以你需要把它的probability hyperparameter設(shè)置為T(mén)rue(這會(huì)使SVC使用交叉驗(yàn)證去預(yù)測(cè)類(lèi)別概率,其降低了訓(xùn)練速度,但會(huì)添加predict_proba()方法)。如果你修改了之前的代碼去使用軟投票,你會(huì)發(fā)現(xiàn)投票分類(lèi)器正確率高達(dá)91%
2 Bagging 和 Pasting
換句話(huà)說(shuō),Bagging和Pasting都允許在多個(gè)分類(lèi)器間對(duì)訓(xùn)練集進(jìn)行多次采樣。
Bagging可以通過(guò)使用不同的訓(xùn)練算法去得到一些不同的分類(lèi)器。
Pasting就是對(duì)每一個(gè)分類(lèi)器都使用相同的訓(xùn)練算法,但是在不同的訓(xùn)練集上去訓(xùn)練它們。
有放回采樣被稱(chēng)為裝袋(Bagging,是bootstrap aggregating的縮寫(xiě))。
無(wú)放回采樣稱(chēng)為粘貼(pasting)。
換句話(huà)說(shuō),Bagging和Pasting都允許在多個(gè)分類(lèi)器上對(duì)訓(xùn)練集進(jìn)行多次采樣,但只有Bagging允許對(duì)同一種分類(lèi)器上對(duì)訓(xùn)練集進(jìn)行進(jìn)行多次采樣。采樣和訓(xùn)練過(guò)程如圖7-4所示。

當(dāng)所有的分類(lèi)器被訓(xùn)練后,集成可以通過(guò)對(duì)所有分類(lèi)器結(jié)果的簡(jiǎn)單聚合來(lái)對(duì)新的實(shí)例進(jìn)行預(yù)測(cè)。聚合函數(shù)通常對(duì)分類(lèi)是*統(tǒng)計(jì)模式*(例如硬投票分類(lèi)器)或者對(duì)回歸是平均。每一個(gè)單獨(dú)的分類(lèi)器在如果在原始訓(xùn)練集上都是高偏差,但是聚合降低了偏差和方差。通常情況下,集成的結(jié)果是有一個(gè)相似的偏差,但是對(duì)比與在原始訓(xùn)練集上的單一分類(lèi)器來(lái)講有更小的方差。
正如你在圖 7-4 上所看到的,分類(lèi)器可以通過(guò)不同的CPU 核或其他的服務(wù)器一起被訓(xùn)練。相似的,分類(lèi)器也可以一起被制作。這就是為什么 Bagging 和 Pasting 是如此流行的原因之一:它們的可擴(kuò)展性很好。
2.1 在 sklearn 中的 Bagging 和 Pasting
sklearn為Bagging和Pasting提供了一個(gè)簡(jiǎn)單的API:BaggingClassifier類(lèi)(或者對(duì)于回歸可以是BaggingRegressor。接下來(lái)的代碼訓(xùn)練了一個(gè)500個(gè)決策樹(shù)分類(lèi)器的集成,每一個(gè)都是在數(shù)據(jù)集上有放回采樣100個(gè)訓(xùn)練實(shí)例下進(jìn)行訓(xùn)練(這是Bagging的例子,如果你想嘗試Pasting,就設(shè)置bootstrap=False)。n_jobs參數(shù)告訴sklearn用于訓(xùn)練和預(yù)測(cè)所需要CPU核的數(shù)量。(-1代表著sklearn會(huì)使用所有空閑核):
fromsklearn.ensembleimportBaggingClassifierfromsklearn.treeimportDecisionTreeClassifierfromsklearn.metricsimportaccuracy_scorebag_clf = BaggingClassifier(? ? DecisionTreeClassifier(random_state=42), n_estimators=500,? ? max_samples=100, bootstrap=True, n_jobs=-1, random_state=42)bag_clf.fit(X_train, y_train)y_pred = bag_clf.predict(X_test)print(accuracy_score(y_test, y_pred))tree_clf = DecisionTreeClassifier(random_state=42)tree_clf.fit(X_train, y_train)y_pred_tree = tree_clf.predict(X_test)print(accuracy_score(y_test, y_pred_tree))0.9040.856
如果基分類(lèi)器可以預(yù)測(cè)類(lèi)別概率(例如它擁有predict_proba()方法),那么BaggingClassifier會(huì)自動(dòng)的運(yùn)行軟投票,這是決策樹(shù)分類(lèi)器的情況。
圖 7-5 對(duì)比了單一決策樹(shù)的決策邊界和Bagging集成500個(gè)樹(shù)的決策邊界,兩者都在moons數(shù)據(jù)集上訓(xùn)練。正如你所看到的,集成的分類(lèi)比起單一決策樹(shù)的分類(lèi)產(chǎn)生情況更好:集成有一個(gè)可比較的偏差但是有一個(gè)較小的方差(它在訓(xùn)練集上的錯(cuò)誤數(shù)目大致相同,但決策邊界較不規(guī)則)。

Bootstrap在每個(gè)預(yù)測(cè)器被訓(xùn)練的子集中引入了更多的分集,所以Bagging結(jié)束時(shí)的偏差比Pasting更高,但這也意味著預(yù)測(cè)因子最終變得不相關(guān),從而減少了集合的方差。總體而言,Bagging通常會(huì)導(dǎo)致更好的模型,這就解釋了為什么它通常是首選的。然而,如果你有空閑時(shí)間和CPU功率,可以使用交叉驗(yàn)證來(lái)評(píng)估Bagging和Pasting哪一個(gè)更好。
2.2 Out-of-Bag 評(píng)價(jià)
對(duì)于Bagging來(lái)說(shuō),一些實(shí)例可能被一些分類(lèi)器重復(fù)采樣,但其他的有可能不會(huì)被采樣。BaggingClassifier默認(rèn)采樣。BaggingClassifier默認(rèn)是有放回的采樣m個(gè)實(shí)例 (bootstrap=True),其中m是訓(xùn)練集的大小,這意味著平均下來(lái)只有63%的訓(xùn)練實(shí)例被每個(gè)分類(lèi)器采樣,剩下的37%個(gè)沒(méi)有被采樣的訓(xùn)練實(shí)例就叫做Out-of-Bag實(shí)例。注意對(duì)于每一個(gè)的分類(lèi)器它們的37%不是相同的。
因?yàn)樵谟?xùn)練中分類(lèi)器從來(lái)沒(méi)有看到過(guò)oob實(shí)例,所以它可以在這些實(shí)例上進(jìn)行評(píng)估,而不需要單獨(dú)的驗(yàn)證集或交叉驗(yàn)證。你可以拿出每一個(gè)分類(lèi)器的oob來(lái)評(píng)估集成本身。
在sklearn中,你可以在訓(xùn)練后需要?jiǎng)?chuàng)建一個(gè)BaggingClassifier來(lái)自動(dòng)評(píng)估時(shí)設(shè)置oob_score=True來(lái)自動(dòng)評(píng)估。接下來(lái)的代碼展示了這個(gè)操作。評(píng)估結(jié)果通過(guò)變量oob_score_來(lái)顯示:
bag_clf = BaggingClassifier(? ? DecisionTreeClassifier(random_state=42), n_estimators=500,? ? bootstrap=True, n_jobs=-1, oob_score=True, random_state=40)bag_clf.fit(X_train, y_train)bag_clf.oob_score_0.90133333333333332
根據(jù)這個(gè)obb評(píng)估,BaggingClassifier可以再測(cè)試集上達(dá)到93.1%的準(zhǔn)確率,讓我們修改一下:
fromsklearn.metricsimportaccuracy_scorey_pred = bag_clf.predict(X_test)accuracy_score(y_test, y_pred)0.91200000000000003
我們?cè)跍y(cè)試集上得到了91.2%的準(zhǔn)確率,足夠接近了!
對(duì)于每個(gè)訓(xùn)練實(shí)例oob決策函數(shù)也可通過(guò)oob_decision_function_變量來(lái)展示。在這種情況下(當(dāng)基決策器有predict_proba()時(shí))決策函數(shù)會(huì)對(duì)每個(gè)訓(xùn)練實(shí)例返回類(lèi)別概率。例如,oob評(píng)估預(yù)測(cè)第二個(gè)訓(xùn)練實(shí)例有60.6%的概率屬于正類(lèi)(39.4%屬于負(fù)類(lèi)):
bag_clf.oob_decision_function_array([[0.31746032, 0.68253968],[0.34117647, 0.65882353],[1.? ? ? ? , 0.? ? ? ? ],[0.? ? ? ? , 1.? ? ? ? ],[0.? ? ? ? , 1.? ? ? ? ],[0.08379888, 0.91620112],[0.31693989, 0.68306011],[0.02923977, 0.97076023],[0.97687861, 0.02312139],[0.97765363, 0.02234637],
3 隨機(jī)貼片與隨機(jī)子空間
BaggingClassifier也支持采樣特征。它被兩個(gè)超參數(shù)max_features和bootstrap_features控制。他們的工作方式和max_samples和bootstrap一樣,但這是對(duì)于特征采樣而不是實(shí)例采樣。因此,每一個(gè)分類(lèi)器都會(huì)被在隨機(jī)的輸入特征內(nèi)進(jìn)行訓(xùn)練。
當(dāng)你在處理高維度輸入下(例如圖片)此方法尤其有效。對(duì)訓(xùn)練實(shí)例和特征的采樣被叫做隨機(jī)貼片。保留了所有的訓(xùn)練實(shí)例(例如bootstrap=False和max_samples=1.0),但是對(duì)特征采樣(bootstrap_features=True并且/或者max_features小于 1.0)叫做隨機(jī)子空間。
采樣特征導(dǎo)致更多的預(yù)測(cè)多樣性,用高偏差換低方差。
4 隨機(jī)森林
正如我們所討論的,隨機(jī)森林是決策樹(shù)的一種集成,通常是通過(guò)bagging方法(有時(shí)是pasting方法)進(jìn)行訓(xùn)練,通常用max_samples設(shè)置為訓(xùn)練集的大小。與建立一個(gè)BaggingClassifier然后把它放入DecisionTreeClassifier相反,你可以使用更方便的也是對(duì)決策樹(shù)優(yōu)化夠的RandomForestClassifier(對(duì)于回歸是RandomForestRegressor)。接下來(lái)的代碼訓(xùn)練了帶有500個(gè)樹(shù)(每個(gè)被限制為16葉子結(jié)點(diǎn))的決策森林,使用所有空閑的 CPU 核:
fromsklearn.ensembleimportRandomForestClassifierrnd_clf = RandomForestClassifier(n_estimators=500, max_leaf_nodes=16, n_jobs=-1, random_state=42)rnd_clf.fit(X_train, y_train)y_pred_rf = rnd_clf.predict(X_test)
除了一些例外,RandomForestClassifier使用DecisionTreeClassifier的所有超參數(shù)(決定數(shù)怎么生長(zhǎng)),把BaggingClassifier的超參數(shù)加起來(lái)來(lái)控制集成本身。
隨機(jī)森林算法在樹(shù)生長(zhǎng)時(shí)引入了額外的隨機(jī);與在節(jié)點(diǎn)分裂時(shí)需要找到最好分裂特征相反(詳見(jiàn)第六章),它在一個(gè)隨機(jī)的特征集中找最好的特征。它導(dǎo)致了樹(shù)的差異性,并且再一次用高偏差換低方差,總的來(lái)說(shuō)是一個(gè)更好的模型。以下是BaggingClassifier大致相當(dāng)于之前的randomforestclassifier:
bag_clf = BaggingClassifier(? ? DecisionTreeClassifier(splitter="random", max_leaf_nodes=16, random_state=42),? ? n_estimators=500, max_samples=1.0, bootstrap=True, n_jobs=-1, random_state=42)bag_clf.fit(X_train, y_train)y_pred = bag_clf.predict(X_test)
np.sum(y_pred == y_pred_rf) / len(y_pred)# almost identical predictions0.976
4.1 極端隨機(jī)樹(shù)
當(dāng)你在隨機(jī)森林上生長(zhǎng)樹(shù)時(shí),在每個(gè)結(jié)點(diǎn)分裂時(shí)只考慮隨機(jī)特征集上的特征(正如之前討論過(guò)的一樣)。相比于找到更好的特征我們可以通過(guò)使用對(duì)特征使用隨機(jī)閾值使樹(shù)更加隨機(jī)(像規(guī)則決策樹(shù)一樣)。
這種極端隨機(jī)的樹(shù)被簡(jiǎn)稱(chēng)為Extremely Randomized Trees(極端隨機(jī)樹(shù)),或者更簡(jiǎn)單的稱(chēng)為Extra-Tree。再一次用高偏差換低方差。它還使得Extra-Tree比規(guī)則的隨機(jī)森林更快地訓(xùn)練,因?yàn)樵?b>每個(gè)節(jié)點(diǎn)上找到每個(gè)特征的最佳閾值是生長(zhǎng)樹(shù)最耗時(shí)的任務(wù)之一。
你可以使用sklearn的ExtraTreesClassifier來(lái)創(chuàng)建一個(gè)Extra-Tree分類(lèi)器。他的API跟RandomForestClassifier是相同的,相似的,ExtraTreesRegressor跟RandomForestRegressor也是相同的 API。
我們很難去分辨ExtraTreesClassifier和RandomForestClassifier到底哪個(gè)更好。通常情況下是通過(guò)交叉驗(yàn)證來(lái)比較它們(使用網(wǎng)格搜索調(diào)整超參數(shù))。
4.2 特征重要度
最后,如果你觀察一個(gè)單一決策樹(shù),重要的特征會(huì)出現(xiàn)在更靠近根部的位置,而不重要的特征會(huì)經(jīng)常出現(xiàn)在靠近葉子的位置。因此我們可以通過(guò)計(jì)算一個(gè)特征在森林的全部樹(shù)中出現(xiàn)的平均深度來(lái)預(yù)測(cè)特征的重要性。sklearn 在訓(xùn)練后會(huì)自動(dòng)計(jì)算每個(gè)特征的重要度。你可以通過(guò)feature_importances_變量來(lái)查看結(jié)果。例如如下代碼在 iris 數(shù)據(jù)集(第四章介紹)上訓(xùn)練了一個(gè)RandomForestClassifier模型,然后輸出了每個(gè)特征的重要性??磥?lái),最重要的特征是花瓣長(zhǎng)度(44%)和寬度(42%),而萼片長(zhǎng)度和寬度相對(duì)比較是不重要的(分別為 11% 和 2%):
fromsklearn.datasetsimportload_irisiris = load_iris()rnd_clf = RandomForestClassifier(n_estimators=500, n_jobs=-1, random_state=42)rnd_clf.fit(iris["data"], iris["target"])forname, scoreinzip(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
rnd_clf.feature_importances_array([0.11249225, 0.02311929, 0.44103046, 0.423358? ])
相似的,如果你在 MNIST 數(shù)據(jù)及上訓(xùn)練隨機(jī)森林分類(lèi)器(在第三章上介紹),然后畫(huà)出每個(gè)像素的重要性,你可以得到圖 7-6 的圖片。
from scipy.io import loadmatmnist = loadmat('./datasets/mnist-original.mat')mnist{'__globals__': [],'__header__':b'MATLAB 5.0 MAT-file Platform: posix, Created on: Sun Mar 30 03:19:02 2014','__version__':'1.0','data':array([[0,0,0, ...,0,0,0],? ? ? ? [0,0,0, ...,0,0,0],? ? ? ? [0,0,0, ...,0,0,0],? ? ? ? ...,? ? ? ? [0,0,0, ...,0,0,0],? ? ? ? [0,0,0, ...,0,0,0],? ? ? ? [0,0,0, ...,0,0,0]], dtype=uint8),'label':array([[0.,0.,0., ...,9.,9.,9.]]),'mldata_descr_ordering':array([[array(['label'],? ? ? ? dtype='<U5'),array(['data'],? ? ? ? dtype='<U4')]], dtype=object)}
X,y = mnist['data'].T,mnist['label'].TX.shape(70000, 784)y.shape(70000, 1)
rnd_clf = RandomForestClassifier(random_state=42)rnd_clf.fit(X, y)RandomForestClassifier(bootstrap=True, class_weight=None, criterion='gini',? ? ? ? ? ? max_depth=None, max_features='auto', max_leaf_nodes=None,? ? ? ? ? ? min_impurity_decrease=0.0, min_impurity_split=None,? ? ? ? ? ? min_samples_leaf=1, min_samples_split=2,? ? ? ? ? ? min_weight_fraction_leaf=0.0, n_estimators=10, n_jobs=1,? ? ? ? ? ? oob_score=False, random_state=42, verbose=0, warm_start=False)
# mnist_feature_importance_plotdefplot_digit(data):image = data.reshape(28,28)? ? plt.imshow(image, cmap = matplotlib.cm.hot,? ? ? ? ? ? ? interpolation="nearest")? ? plt.axis("off")? ? plot_digit(rnd_clf.feature_importances_)cbar = plt.colorbar(ticks=[rnd_clf.feature_importances_.min(), rnd_clf.feature_importances_.max()])cbar.ax.set_yticklabels(['Not important','Very important'])plt.show()

隨機(jī)森林可以非常方便快速得了解哪些特征實(shí)際上是重要的,特別是你需要進(jìn)行特征選擇的時(shí)候。
5 提升
提升(Boosting,最初稱(chēng)為假設(shè)增強(qiáng))指的是可以將幾個(gè)弱學(xué)習(xí)者組合成強(qiáng)學(xué)習(xí)者的集成方法。對(duì)于大多數(shù)的提升方法的思想就是按順序去訓(xùn)練分類(lèi)器,每一個(gè)都要嘗試修正前面的分類(lèi)?,F(xiàn)如今已經(jīng)有很多的提升方法了,但最著名的就是Adaboost(適應(yīng)性提升,是Adaptive Boosting的簡(jiǎn)稱(chēng)) 和Gradient Boosting(梯度提升)。讓我們先從Adaboost說(shuō)起。
5.1 Adaboost
使一個(gè)新的分類(lèi)器去修正之前分類(lèi)結(jié)果的方法就是對(duì)之前分類(lèi)結(jié)果不對(duì)的訓(xùn)練實(shí)例多加關(guān)注。這導(dǎo)致新的預(yù)測(cè)因子越來(lái)越多地聚焦于這種情況。這是Adaboost使用的技術(shù)。
舉個(gè)例子,去構(gòu)建一個(gè)Adaboost分類(lèi)器,
第一個(gè)基分類(lèi)器(例如一個(gè)決策樹(shù))被訓(xùn)練然后在訓(xùn)練集上做預(yù)測(cè),在誤分類(lèi)訓(xùn)練實(shí)例上的權(quán)重就增加了;
第二個(gè)分類(lèi)機(jī)使用更新過(guò)的權(quán)重然后再一次訓(xùn)練,權(quán)重更新,以此類(lèi)推(詳見(jiàn)圖 7-7)

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

一旦所有的分類(lèi)器都被訓(xùn)練后,除了分類(lèi)器根據(jù)整個(gè)訓(xùn)練集上的準(zhǔn)確率被賦予的權(quán)重外,集成預(yù)測(cè)就非常像Bagging和Pasting了。
序列學(xué)習(xí)技術(shù)的一個(gè)重要的缺點(diǎn)就是:它不能被并行化(只能按步驟),因?yàn)槊總€(gè)分類(lèi)器只能在之前的分類(lèi)器已經(jīng)被訓(xùn)練和評(píng)價(jià)后再進(jìn)行訓(xùn)練。因此,它不像Bagging和Pasting一樣。
讓我們?cè)敿?xì)看一下Adaboost算法。每一個(gè)實(shí)例的權(quán)重wi初始都被設(shè)為1/m第一個(gè)分類(lèi)器被訓(xùn)練,然后他的權(quán)重誤差率r1在訓(xùn)練集上算出,詳見(jiàn)公式 7-1。


sklearn通常使用Adaboost的多分類(lèi)版本SAMME(這就代表了分段加建模使用多類(lèi)指數(shù)損失函數(shù))。如果只有兩類(lèi)別,那么SAMME是與Adaboost相同的。如果分類(lèi)器可以預(yù)測(cè)類(lèi)別概率(例如如果它們有predict_proba()),如果sklearn可以使用SAMME叫做SAMME.R的變量(R 代表“REAL”),這種依賴(lài)于類(lèi)別概率的通常比依賴(lài)于分類(lèi)器的更好。
接下來(lái)的代碼訓(xùn)練了使用sklearn的AdaBoostClassifier基于200個(gè)決策樹(shù)樁Adaboost分類(lèi)器(正如你說(shuō)期待的,對(duì)于回歸也有AdaBoostRegressor)。一個(gè)決策樹(shù)樁是max_depth=1的決策樹(shù)-換句話(huà)說(shuō),是一個(gè)單一的決策節(jié)點(diǎn)加上兩個(gè)葉子結(jié)點(diǎn)。這就是AdaBoostClassifier的默認(rèn)基分類(lèi)器:
fromsklearn.ensembleimportAdaBoostClassifierada_clf = AdaBoostClassifier(? ? DecisionTreeClassifier(max_depth=1), n_estimators=200,? ? algorithm="SAMME.R", learning_rate=0.5, random_state=42)ada_clf.fit(X_train, y_train)
如果你的Adaboost集成過(guò)擬合了訓(xùn)練集,你可以嘗試減少基分類(lèi)器的數(shù)量或者對(duì)基分類(lèi)器使用更強(qiáng)的正則化。
5.2 梯度提升
另一個(gè)非常著名的提升算法是梯度提升。與Adaboost一樣,梯度提升也是通過(guò)向集成中逐步增加分類(lèi)器運(yùn)行的,每一個(gè)分類(lèi)器都修正之前的分類(lèi)結(jié)果。然而,它并不像Adaboost那樣每一次迭代都更改實(shí)例的權(quán)重,這個(gè)方法是去使用新的分類(lèi)器去擬合前面分類(lèi)器預(yù)測(cè)的殘差。
讓我們通過(guò)一個(gè)使用決策樹(shù)當(dāng)做基分類(lèi)器的簡(jiǎn)單的回歸例子(回歸當(dāng)然也可以使用梯度提升)。這被叫做梯度提升回歸樹(shù)(GBRT,Gradient Tree Boosting或者Gradient Boosted Regression Trees)。
首先我們用DecisionTreeRegressor去擬合訓(xùn)練集(例如一個(gè)有噪二次訓(xùn)練集):
fromsklearn.treeimportDecisionTreeRegressor tree_reg1 = DecisionTreeRegressor(max_depth=2) tree_reg1.fit(X, y)
現(xiàn)在在第一個(gè)分類(lèi)器的殘差上訓(xùn)練第二個(gè)分類(lèi)器:
y2 = y - tree_reg1.predict(X)
tree_reg2 = DecisionTreeRegressor(max_depth=2, random_state=42)
tree_reg2.fit(X, y2)
隨后在第二個(gè)分類(lèi)器的殘差上訓(xùn)練第三個(gè)分類(lèi)器:
y3 = y2 - tree_reg2.predict(X)
tree_reg3 = DecisionTreeRegressor(max_depth=2, random_state=42)
tree_reg3.fit(X, y3)
現(xiàn)在我們有了一個(gè)包含三個(gè)回歸器的集成。它可以通過(guò)集成所有樹(shù)的預(yù)測(cè)來(lái)在一個(gè)新的實(shí)例上進(jìn)行預(yù)測(cè)。
X_new = np.array([[0.8]])y_pred = sum(tree.predict(X_new)fortreein(tree_reg1, tree_reg2, tree_reg3))y_pred
# gradient_boosting_plotdef plot_predictions(regressors, X, y, axes, label=None, style="r-", data_style="b.", data_label=None):? ? x1 = np.linspace(axes[0], axes[1], 500)? ? y_pred = sum(regressor.predict(x1.reshape(-1, 1))forregressorinregressors)? ? plt.plot(X[:, 0], y, data_style, label=data_label)? ? plt.plot(x1, y_pred, style, linewidth=2, label=label)iflabel or data_label:? ? ? ? plt.legend(loc="upper center", fontsize=16)? ? plt.axis(axes)plt.figure(figsize=(11,11))plt.subplot(321)plot_predictions([tree_reg1], X, y, axes=[-0.5, 0.5, -0.1, 0.8], label="$h_1(x_1)$", style="g-", data_label="Training set")plt.ylabel("$y$", fontsize=16, rotation=0)plt.title("Residuals and tree predictions", fontsize=16)plt.subplot(322)plot_predictions([tree_reg1], X, y, axes=[-0.5, 0.5, -0.1, 0.8], label="$h(x_1) = h_1(x_1)$", data_label="Training set")plt.ylabel("$y$", fontsize=16, rotation=0)plt.title("Ensemble predictions", fontsize=16)plt.subplot(323)plot_predictions([tree_reg2], X, y2, axes=[-0.5, 0.5, -0.5, 0.5], label="$h_2(x_1)$", style="g-", data_style="k+", data_label="Residuals")plt.ylabel("$y- h_1(x_1)$", fontsize=16)plt.subplot(324)plot_predictions([tree_reg1, tree_reg2], X, y, axes=[-0.5, 0.5, -0.1, 0.8], label="$h(x_1) = h_1(x_1) + h_2(x_1)$")plt.ylabel("$y$", fontsize=16, rotation=0)plt.subplot(325)plot_predictions([tree_reg3], X, y3, axes=[-0.5, 0.5, -0.5, 0.5], label="$h_3(x_1)$", style="g-", data_style="k+")plt.ylabel("$y- h_1(x_1) - h_2(x_1)$", fontsize=16)plt.xlabel("$x_1$", fontsize=16)plt.subplot(326)plot_predictions([tree_reg1, tree_reg2, tree_reg3], X, y, axes=[-0.5, 0.5, -0.1, 0.8], label="$h(x_1) = h_1(x_1) + h_2(x_1) + h_3(x_1)$")plt.xlabel("$x_1$", fontsize=16)plt.ylabel("$y$", fontsize=16, rotation=0)plt.show()
圖7-9在左欄展示了這三個(gè)樹(shù)的預(yù)測(cè),在右欄展示了集成的預(yù)測(cè)。
在第一行,集成只有一個(gè)樹(shù),所以它與第一個(gè)樹(shù)的預(yù)測(cè)相似。
在第二行,一個(gè)新的樹(shù)在第一個(gè)樹(shù)的殘差上進(jìn)行訓(xùn)練。在右邊欄可以看出集成的預(yù)測(cè)等于前兩個(gè)樹(shù)預(yù)測(cè)的和。
相同的,在第三行另一個(gè)樹(shù)在第二個(gè)數(shù)的殘差上訓(xùn)練。你可以看到集成的預(yù)測(cè)會(huì)變的更好。

我們可以使用sklean中的GradientBoostingRegressor來(lái)訓(xùn)練GBRT集成。與RandomForestClassifier相似,它也有超參數(shù)去控制決策樹(shù)的生長(zhǎng)(例如max_depth,min_samples_leaf等等),也有超參數(shù)去控制集成訓(xùn)練,例如基分類(lèi)器的數(shù)量(n_estimators)。接下來(lái)的代碼創(chuàng)建了與之前相同的集成:
fromsklearn.ensembleimportGradientBoostingRegressorgbrt = GradientBoostingRegressor(max_depth=2, n_estimators=3, learning_rate=1.0, random_state=42)gbrt.fit(X, y)gbrt_slow = GradientBoostingRegressor(max_depth=2, n_estimators=200, learning_rate=0.1, random_state=42)gbrt_slow.fit(X, y)
# gbrt_learning_rate_plotplt.figure(figsize=(11,4))plt.subplot(121)plot_predictions([gbrt], X, y, axes=[-0.5, 0.5, -0.1, 0.8], label="Ensemble predictions")plt.title("learning_rate={}, n_estimators={}".format(gbrt.learning_rate, gbrt.n_estimators), fontsize=14)plt.subplot(122)plot_predictions([gbrt_slow], X, y, axes=[-0.5, 0.5, -0.1, 0.8])plt.title("learning_rate={}, n_estimators={}".format(gbrt_slow.learning_rate, gbrt_slow.n_estimators), fontsize=14)plt.show()
超參數(shù)learning_rate確立了每個(gè)樹(shù)的貢獻(xiàn)。如果你把它設(shè)置為一個(gè)很小的樹(shù),例如0.1,在集成中就需要更多的樹(shù)去擬合訓(xùn)練集,但預(yù)測(cè)通常會(huì)更好。這個(gè)正則化技術(shù)叫做shrinkage。
圖 7-10 展示了兩個(gè)在低學(xué)習(xí)率上訓(xùn)練的GBRT集成:其中左面是一個(gè)沒(méi)有足夠樹(shù)去擬合訓(xùn)練集的樹(shù),右面是有過(guò)多的樹(shù)過(guò)擬合訓(xùn)練集的樹(shù)。

早停技術(shù)
為了找到樹(shù)的最優(yōu)數(shù)量,你可以使用早停技術(shù)(第四章討論)。
最簡(jiǎn)單使用這個(gè)技術(shù)的方法就是使用staged_predict():
它在訓(xùn)練的每個(gè)階段(用一棵樹(shù),兩棵樹(shù)等)返回一個(gè)迭代器。加下來(lái)的代碼用120個(gè)樹(shù)訓(xùn)練了一個(gè)GBRT集成,然后在訓(xùn)練的每個(gè)階段驗(yàn)證錯(cuò)誤以找到樹(shù)的最佳數(shù)量,最后使用GBRT樹(shù)的最優(yōu)數(shù)量訓(xùn)練另一個(gè)集成:
importnumpyasnpfromsklearn.model_selectionimporttrain_test_splitfromsklearn.metricsimportmean_squared_errorX_train, X_val, y_train, y_val = train_test_split(X, y, random_state=49)gbrt = GradientBoostingRegressor(max_depth=2, n_estimators=120, random_state=42)gbrt.fit(X_train, y_train)errors = [mean_squared_error(y_val, y_pred)fory_predingbrt.staged_predict(X_val)]bst_n_estimators = np.argmin(errors)gbrt_best = GradientBoostingRegressor(max_depth=2,n_estimators=bst_n_estimators, random_state=42)gbrt_best.fit(X_train, y_train)min_error = np.min(errors)# early_stopping_gbrt_plotplt.figure(figsize=(11,4))plt.subplot(121)plt.plot(errors,"b.-")plt.plot([bst_n_estimators, bst_n_estimators], [0, min_error],"k--")plt.plot([0,120], [min_error, min_error],"k--")plt.plot(bst_n_estimators, min_error,"ko")plt.text(bst_n_estimators, min_error*1.2,"Minimum", ha="center", fontsize=14)plt.axis([0,120,0,0.01])plt.xlabel("Number of trees")plt.title("Validation error", fontsize=14)plt.subplot(122)plot_predictions([gbrt_best], X, y, axes=[-0.5,0.5,-0.1,0.8])plt.title("Best model (%d trees)"% bst_n_estimators, fontsize=14)plt.show()
驗(yàn)證錯(cuò)誤在圖 7-11 的左面展示,最優(yōu)模型預(yù)測(cè)被展示在右面。

你也可以早早的停止訓(xùn)練來(lái)實(shí)現(xiàn)早停(與先在一大堆樹(shù)中訓(xùn)練,然后再回頭去找最優(yōu)數(shù)目相反)。你可以通過(guò)設(shè)置warm_start=True來(lái)實(shí)現(xiàn) ,這使得當(dāng)fit()方法被調(diào)用時(shí)sklearn保留現(xiàn)有樹(shù),并允許增量訓(xùn)練。接下來(lái)的代碼在當(dāng)一行中的五次迭代驗(yàn)證錯(cuò)誤沒(méi)有改善時(shí)會(huì)停止訓(xùn)練:
gbrt = GradientBoostingRegressor(max_depth=2, warm_start=True, random_state=42)min_val_error =float("inf")error_going_up = 0forn_estimatorsinrange(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)ifval_error < min_val_error:? ? ? ? min_val_error = val_error? ? ? ? error_going_up = 0else:? ? ? ? error_going_up += 1iferror_going_up == 5:break# early stoppingprint(gbrt.n_estimators)print("Minimum validation MSE:", min_val_error)61Minimum validation MSE: 0.00271285332524
GradientBoostingRegressor也支持指定用于訓(xùn)練每棵樹(shù)的訓(xùn)練實(shí)例比例的超參數(shù)subsample。例如如果subsample=0.25,那么每個(gè)樹(shù)都會(huì)在25%隨機(jī)選擇的訓(xùn)練實(shí)例上訓(xùn)練。你現(xiàn)在也能猜出來(lái),這也是個(gè)高偏差換低方差的作用。它同樣也加速了訓(xùn)練。這個(gè)技術(shù)叫做隨機(jī)梯度提升。
也可能對(duì)其他損失函數(shù)使用梯度提升。這是由損失超參數(shù)控制(見(jiàn)sklearn文檔)。
6 Stacking
本章討論的最后一個(gè)集成方法叫做Stacking(stacked generalization的縮寫(xiě))。這個(gè)算法基于一個(gè)簡(jiǎn)單的想法:不使用瑣碎的函數(shù)(如硬投票)來(lái)聚合集合中所有分類(lèi)器的預(yù)測(cè),我們?yōu)槭裁床挥?xùn)練一個(gè)模型來(lái)執(zhí)行這個(gè)聚合?
圖 7-12 展示了這樣一個(gè)在新的回歸實(shí)例上預(yù)測(cè)的集成。底部三個(gè)分類(lèi)器每一個(gè)都有不同的值(3.1,2.7 和 2.9),然后最后一個(gè)分類(lèi)器(叫做blender或者meta learner)把這三個(gè)分類(lèi)器的結(jié)果當(dāng)做輸入然后做出最終決策(3.0)。

為了訓(xùn)練這個(gè)blender,一個(gè)通用的方法是采用保持集。讓我們看看它怎么工作。
首先,訓(xùn)練集被分為兩個(gè)子集,第一個(gè)子集被用作訓(xùn)練第一層(詳見(jiàn)圖 7-13).

接下來(lái),第一層的分類(lèi)器被用來(lái)預(yù)測(cè)第二個(gè)子集(保持集)(詳見(jiàn) 7-14)。這確保了預(yù)測(cè)結(jié)果很“干凈”,因?yàn)檫@些分類(lèi)器在訓(xùn)練的時(shí)候沒(méi)有使用過(guò)這些事例。現(xiàn)在對(duì)在保持集中的每一個(gè)實(shí)例都有三個(gè)預(yù)測(cè)值。我們現(xiàn)在可以使用這些預(yù)測(cè)結(jié)果作為輸入特征來(lái)創(chuàng)建一個(gè)新的訓(xùn)練集(這使得這個(gè)訓(xùn)練集是三維的),并且保持目標(biāo)數(shù)值不變。隨后blender在這個(gè)新的訓(xùn)練集上訓(xùn)練,因此,它學(xué)會(huì)了預(yù)測(cè)第一層預(yù)測(cè)的目標(biāo)值。

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

然而不幸的是,sklearn并不直接支持stacking,但是你自己組建是很容易的(看接下來(lái)的練習(xí))?;蛘吣阋部梢允褂瞄_(kāi)源的項(xiàng)目例如brew(網(wǎng)址為https://github.com/viisar/brew)
安裝brew
pip install git+https://github.com/viisar/brew.git
importnumpyasnpimportmatplotlib.pyplotaspltimportmatplotlib.gridspecasgridspecimportitertoolsimportsklearnfromsklearn.linear_modelimportLogisticRegressionfromsklearn.svmimportSVCfromsklearn.ensembleimportRandomForestClassifierfrombrew.baseimportEnsemble, EnsembleClassifierfrombrew.stacking.stackerimportEnsembleStack, EnsembleStackClassifierfrombrew.combination.combinerimportCombinerfrommlxtend.dataimportiris_datafrommlxtend.plottingimportplot_decision_regions# Initializing Classifiersclf1 = LogisticRegression(random_state=0)clf2 = RandomForestClassifier(random_state=0)clf3 = SVC(random_state=0, probability=True)# Creating Ensembleensemble = Ensemble([clf1, clf2, clf3])eclf = EnsembleClassifier(ensemble=ensemble, combiner=Combiner('mean'))# Creating Stackinglayer_1 = Ensemble([clf1, clf2, clf3])layer_2 = Ensemble([sklearn.clone(clf1)])stack = EnsembleStack(cv=3)stack.add_layer(layer_1)stack.add_layer(layer_2)sclf = EnsembleStackClassifier(stack)clf_list = [clf1, clf2, clf3, eclf, sclf]lbl_list = ['Logistic Regression','Random Forest','RBF kernel SVM','Ensemble','Stacking']# Loading some example dataX, y = iris_data()X = X[:,[0,2]]# WARNING, WARNING, WARNING# brew requires classes from 0 to N, no skipping allowedd = {yi : ifori, yiinenumerate(set(y))}y = np.array([d[yi]foryiiny])# Plotting Decision Regionsgs = gridspec.GridSpec(2,3)fig = plt.figure(figsize=(10,8))itt = itertools.product([0,1,2], repeat=2)forclf, lab, grdinzip(clf_list, lbl_list, itt):? ? clf.fit(X, y)? ? ax = plt.subplot(gs[grd[0], grd[1]])? ? fig = plot_decision_regions(X=X, y=y, clf=clf, legend=2)? ? plt.title(lab)plt.show()

7 思考題
如果你在相同訓(xùn)練集上訓(xùn)練 5 個(gè)不同的模型,它們都有 95% 的準(zhǔn)確率,那么你是否可以通過(guò)組合這個(gè)模型來(lái)得到更好的結(jié)果?如果可以那怎么做呢?如果不可以請(qǐng)給出理由。
軟投票和硬投票分類(lèi)器之間有什么區(qū)別?
是否有可能通過(guò)分配多個(gè)服務(wù)器來(lái)加速 bagging 集成系統(tǒng)的訓(xùn)練?pasting 集成,boosting 集成,隨機(jī)森林,或 stacking 集成怎么樣?
out-of-bag 評(píng)價(jià)的好處是什么?
是什么使 Extra-Tree 比規(guī)則隨機(jī)森林更隨機(jī)呢?這個(gè)額外的隨機(jī)有什么幫助呢?那這個(gè) Extra-Tree 比規(guī)則隨機(jī)森林誰(shuí)更快呢?
如果你的 Adaboost 模型欠擬合,那么你需要怎么調(diào)整超參數(shù)?
如果你的梯度提升過(guò)擬合,那么你應(yīng)該調(diào)高還是調(diào)低學(xué)習(xí)率呢?
導(dǎo)入 MNIST 數(shù)據(jù)(第三章中介紹),把它切分進(jìn)一個(gè)訓(xùn)練集,一個(gè)驗(yàn)證集,和一個(gè)測(cè)試集(例如 40000 個(gè)實(shí)例進(jìn)行訓(xùn)練,10000 個(gè)進(jìn)行驗(yàn)證,10000 個(gè)進(jìn)行測(cè)試)。然后訓(xùn)練多個(gè)分類(lèi)器,例如一個(gè)隨機(jī)森林分類(lèi)器,一個(gè) Extra-Tree 分類(lèi)器和一個(gè) SVM。接下來(lái),嘗試將它們組合成集成,使用軟或硬投票分類(lèi)器來(lái)勝過(guò)驗(yàn)證集上的所有集合。一旦找到了,就在測(cè)試集上實(shí)驗(yàn)。與單個(gè)分類(lèi)器相比,它的性能有多好?
從練習(xí) 8 中運(yùn)行個(gè)體分類(lèi)器來(lái)對(duì)驗(yàn)證集進(jìn)行預(yù)測(cè),并創(chuàng)建一個(gè)新的訓(xùn)練集并生成預(yù)測(cè):每個(gè)訓(xùn)練實(shí)例是一個(gè)向量,包含來(lái)自所有分類(lèi)器的圖像的預(yù)測(cè)集,目標(biāo)是圖像類(lèi)別。祝賀你,你剛剛訓(xùn)練了一個(gè)blender,和分類(lèi)器一起組成了一個(gè)疊加組合!現(xiàn)在讓我們來(lái)評(píng)估測(cè)試集上的集合。對(duì)于測(cè)試集中的每個(gè)圖像,用所有分類(lèi)器進(jìn)行預(yù)測(cè),然后將預(yù)測(cè)饋送到blender以獲得集合的預(yù)測(cè)。它與你早期訓(xùn)練過(guò)的投票分類(lèi)器相比如何?
作者:7125messi
鏈接:http://www.itdecent.cn/p/7ea1b77ecb51
來(lái)源:簡(jiǎn)書(shū)
簡(jiǎn)書(shū)著作權(quán)歸作者所有,任何形式的轉(zhuǎn)載都請(qǐng)聯(lián)系作者獲得授權(quán)并注明出處。