集成算法的目的是將幾個(gè)基估計(jì)器的預(yù)測與給定的學(xué)習(xí)算法結(jié)合起來,以提高單個(gè)估計(jì)器的通用性和魯棒性。
集成方法一般分為兩種:
在平均法(averaging methods)中,該方法的原理是構(gòu)建多個(gè)獨(dú)立的估計(jì)器,然后取它們的預(yù)測結(jié)果的平均。一般來說,組合之后的估計(jì)器是會比單個(gè)估計(jì)器要好的,因?yàn)樗姆讲顪p小了。
相反,在提升法(boosting methods)中,基估計(jì)器是按順序建立的,并且試圖減小組合估計(jì)器的偏差。其動機(jī)是將幾個(gè)弱模型結(jié)合起來,形成一個(gè)強(qiáng)大的整體。
示例: AdaBoost, Gradient Tree Boosting, …
在集成算法中, bagging方法形成了一類算法,它在原始訓(xùn)練集的隨機(jī)子集上建立幾個(gè)黑箱估計(jì)器的實(shí)例,然后將它們的個(gè)體預(yù)測聚合起來,形成最終的預(yù)測。這些方法通過在基本估計(jì)器(例如決策樹)的構(gòu)造過程中引入隨機(jī)化,然后將其集成起來,從而降低單個(gè)基本估計(jì)器(如決策樹)的方差。在許多情況下,bagging方法是一個(gè)非常簡單的方法可以用來改進(jìn)相對單一模型,而不需要調(diào)整底層。由于bagging方法提供了一種減少過度擬合的途徑,因此對強(qiáng)大模型和復(fù)雜模型(例如,充分生長的決策樹)最有效,與之對比的提升法在弱模型(例如淺層決策樹)上表現(xiàn)最好。
Bagging方法有許多不同的變種(flavours),但主要是因?yàn)樗鼈兲崛∮?xùn)練集的隨機(jī)子集的方式不同:
在 scikit-learn中, bagging方法都是BaggingClassifier
元估計(jì)器(Resp)提供的。(或者BaggingRegressor
),基估計(jì)器和隨機(jī)子集的抽取策略作為參數(shù)由用戶指定。特別是, max_samples
和max_features
控制子集的大小(就樣本和特征而言),而 bootstrap
和bootstrap_features
控制的是樣本和特征是否是有放回。當(dāng)使用可用樣本的子集時(shí),可以通過設(shè)置 oob_score=True
來估計(jì)袋外(out-of-bag)樣本的泛化精度。舉一個(gè)例子,下面的片段說明了如何實(shí)例化KNeighborsClassifier
基估計(jì)器的bagging集成,每個(gè)估計(jì)器都建立在50%的樣本和50%的特征的隨機(jī)子集上。
>>> from sklearn.ensemble import BaggingClassifier
>>> from sklearn.neighbors import KNeighborsClassifier
>>> bagging = BaggingClassifier(KNeighborsClassifier(),
... max_samples=0.5, max_features=0.5)
示例 |
---|
單個(gè)估計(jì)器 vs bagging:偏差-方差分解 |
參考
[B1999] L. Breiman, “Pasting small votes for classification in large databases and on-line”, Machine Learning, 36(1), 85-103, 1999.
[B1996] L. Breiman, “Bagging predictors”, Machine Learning, 24(2), 123-140, 1996.
[H1998] T. Ho, “The random subspace method for constructing decision forests”, Pattern Analysis and Machine Intelligence, 20(8), 832-844, 1998.
[LG2012] G. Louppe and P. Geurts, “Ensembles on Random Patches”, Machine Learning and Knowledge Discovery in Databases, 346-361, 2012.
sklearn.ensemble
集成模塊包括兩種基于隨機(jī)決策樹的平均算法:RandomForest算法和Extra-Trees算法。這兩種算法都是專門為樹設(shè)計(jì)的擾動和組合技術(shù)(perturb-and-combine techniques)[B1998] 。這意味著在分類器構(gòu)造過程中引入隨機(jī)性來創(chuàng)建一組不同的分類器的集合。集成之后的預(yù)測是每個(gè)分類器的平均。
與其他分類器一樣,森林分類器(forest classifiers)必須擬合兩個(gè)數(shù)組:一個(gè)稀疏或密集的X數(shù)組, 包含訓(xùn)練樣本, 形狀是[n_samples, n_features]
, 還有數(shù)組Y, 形狀是 [n_samples]
, 包含訓(xùn)練樣本的目標(biāo)值(類標(biāo)簽):
>>> from sklearn.ensemble import RandomForestClassifier
>>> X = [[0, 0], [1, 1]]
>>> Y = [0, 1]
>>> clf = RandomForestClassifier(n_estimators=10)
>>> clf = clf.fit(X, Y)
和決策樹 decision trees一樣,樹的森林也擴(kuò)展到多輸出問題 multi-output problems(如果Y是一個(gè)形狀為([n_samples, n_outputs]
)的數(shù)組。
在隨機(jī)森林中(請參閱 RandomForestClassifier
和 RandomForestRegressor
類), 集成模型中的每棵樹構(gòu)建時(shí)的樣本都是由訓(xùn)練集經(jīng)過有放回抽樣(比如a bootstrap sample 自助式采樣法)得來的。
另外,在構(gòu)建樹的過程中進(jìn)行結(jié)點(diǎn)分割時(shí),選擇的分割點(diǎn)是所有特征的最佳分割點(diǎn),或特征的大小為 max_features
的隨機(jī)子集的最佳分割。(更多細(xì)節(jié)請看parameter tuning guidelines )。
這兩種隨機(jī)的目的是降低森林估計(jì)器的方差。事實(shí)上,單個(gè)決策樹通常表現(xiàn)出很高的方差,并且往往會過擬合。在森林中注入隨機(jī)性產(chǎn)生的決策樹具有一定的解耦預(yù)測誤差(decoupled prediction errors)。通過取這些預(yù)測的平均值,可以抵消掉一些誤差。隨機(jī)森林通過組合不同的樹來減少方差,有時(shí)以增加一點(diǎn)點(diǎn)偏差為代價(jià)。在實(shí)踐中,方差減少通常是值得關(guān)注的,因此產(chǎn)生了一個(gè)整體更好的模型。
與最初的出版物 [B2001]相比,scikit-learn實(shí)現(xiàn)通過平均它們的概率預(yù)測來組合分類器,而不是讓每個(gè)分類器為單個(gè)類別進(jìn)行投票。
在極端隨機(jī)樹(參見 ExtraTreesClassifier
和 ExtraTreesRegressor
類)中,計(jì)算分割點(diǎn)方法中的隨機(jī)性進(jìn)一步增強(qiáng)。與隨機(jī)森林中一樣,使用了候選特征的隨機(jī)子集,但不像隨機(jī)森林中是尋找最具區(qū)分度的閾值,而是對每個(gè)候選特征隨機(jī)繪制閾值,并選擇這些隨機(jī)生成的閾值中最佳的作為作為分割規(guī)則。這種做法通常能夠減少一點(diǎn)模型的方差,代價(jià)則是略微地增大偏差:
>>> from sklearn.model_selection import cross_val_score
>>> from sklearn.datasets import make_blobs
>>> from sklearn.ensemble import RandomForestClassifier
>>> from sklearn.ensemble import ExtraTreesClassifier
>>> from sklearn.tree import DecisionTreeClassifier
>>> X, y = make_blobs(n_samples=10000, n_features=10, centers=100,
... random_state=0)
>>> clf = DecisionTreeClassifier(max_depth=None, min_samples_split=2,
... random_state=0)
>>> scores = cross_val_score(clf, X, y, cv=5)
>>> scores.mean()
0.98...
>>> clf = RandomForestClassifier(n_estimators=10, max_depth=None,
... min_samples_split=2, random_state=0)
>>> scores = cross_val_score(clf, X, y, cv=5)
>>> scores.mean()
0.999...
>>> clf = ExtraTreesClassifier(n_estimators=10, max_depth=None,
... min_samples_split=2, random_state=0)
>>> scores = cross_val_score(clf, X, y, cv=5)
>>> scores.mean() > 0.999
True
使用這些方法時(shí)要調(diào)整的參數(shù)主要是 n_estimators
和 max_features
。前者(n_estimators)是森林里樹的數(shù)量,通常數(shù)量越大,效果越好,但是計(jì)算時(shí)間也會隨之增加。此外要注意,當(dāng)樹的數(shù)量超過一個(gè)臨界值之后,算法的效果并不會很顯著地變好。后者(max_features)是分割節(jié)點(diǎn)時(shí)考慮的特征的隨機(jī)子集的大小。 這個(gè)值越低,方差減小得越多,但是偏差的增大也越多。 根據(jù)經(jīng)驗(yàn),回歸問題中使用 max_features = None
(總是考慮所有的特征而不是一個(gè)子集), 分類問題使用 max_features = "sqrt"
(隨機(jī)考慮 sqrt(n_features)
特征,其中 n_features
是數(shù)據(jù)中特征的個(gè)數(shù))是比較好的默認(rèn)值。 max_depth = None
和 min_samples_split = 2
結(jié)合通常會有不錯的效果(即完全生長的樹)。 請記住,這些(默認(rèn))值通常不是最佳的,同時(shí)還可能消耗大量的內(nèi)存,最佳參數(shù)值應(yīng)由交叉驗(yàn)證獲得。 另外,請注意,在隨機(jī)森林中,默認(rèn)使用自助采樣法(bootstrap = True
), 然而 extra-trees 的默認(rèn)策略是使用整個(gè)數(shù)據(jù)集(bootstrap = False
)。 當(dāng)使用自助采樣法方法抽樣時(shí),泛化精度是可以通過剩余的或者袋外(out-of-bag) 的樣本來評估的,設(shè)置 oob_score = True
即可實(shí)現(xiàn)。
注意:默認(rèn)參數(shù)下模型復(fù)雜度是:
O(M*N*log(N))
, 其中M
是樹的數(shù)目,N
是樣本數(shù)。 可以通過設(shè)置以下參數(shù)來降低模型復(fù)雜度:min_samples_split
,?max_leaf_nodes
,?max_depth
和min_samples_leaf
。
最后,這個(gè)模塊還支持樹的并行構(gòu)建和預(yù)測結(jié)果的并行計(jì)算,這可以通過 n_jobs
參數(shù)實(shí)現(xiàn)。 如果設(shè)置 n_jobs = k
,則計(jì)算被劃分為 k
個(gè)作業(yè),并運(yùn)行在機(jī)器的 k
個(gè)核上。 如果設(shè)置 n_jobs = -1
,則使用機(jī)器的所有核。 注意由于進(jìn)程間通信具有一定的開銷,這里的提速并不是線性的(即,使用 k
個(gè)作業(yè)不會快 k
倍)。 當(dāng)然,在建立大量的樹,或者構(gòu)建單個(gè)樹需要相當(dāng)長的時(shí)間(例如,在大數(shù)據(jù)集上)時(shí),(通過并行化)仍然可以實(shí)現(xiàn)顯著的加速。
示例 |
---|
在iris數(shù)據(jù)集上繪制決策樹的決策面 基于平行樹的森林的像素重要性 Face completion with a multi-output estimators |
參考
[B2001] Breiman, “Random Forests”, Machine Learning, 45(1), 5-32, 2001.
[B1998] Breiman, “Arcing Classifiers”, Annals of Statistics 1998.
P. Geurts, D. Ernst., and L. Wehenkel, “Extremely randomized trees”, Machine Learning, 63(1), 3-42, 2006.
特征對目標(biāo)變量預(yù)測的相對重要性可以通過(樹中的決策節(jié)點(diǎn)的)特征使用的相對順序(即深度)來進(jìn)行評估。 決策樹頂部使用的特征對輸入的大部分樣本的最終預(yù)測決策做出貢獻(xiàn);因此,可以使用接受每個(gè)特征對最終預(yù)測的貢獻(xiàn)的樣本比例來評估該 特征的相對重要性 。scikit-learn通過將特征貢獻(xiàn)的樣本比例與分割時(shí)產(chǎn)生的不純度減少相結(jié)合, 從而創(chuàng)建了對該特征的預(yù)測能力的標(biāo)準(zhǔn)化估計(jì)。
通過對多個(gè)隨機(jī)樹中的 預(yù)期貢獻(xiàn)率 (expected activity rates) 取平均,可以減少這種估計(jì)的 方差 ,并將其用于特征選擇。這被稱作平均純度減少,或MDI。關(guān)于MDI以及隨機(jī)森林特征重要性的更多信息,請參考[L2014]。
警告:在基于樹的模型上計(jì)算的基于不存度的特征重要性存在兩個(gè)缺陷,可能導(dǎo)致誤導(dǎo)性結(jié)論。首先,它們是根據(jù)從訓(xùn)練數(shù)據(jù)集派生出來的統(tǒng)計(jì)數(shù)據(jù)來計(jì)算的,因此不一定能告訴我們對于更好的預(yù)測保留的數(shù)據(jù)(held-out dataset), 到底哪些特征才是最重要的。其次,他們傾向于高基數(shù)特征,即具有許多不同值的特征。置換特征重要性Permutation feature importance是不受這些缺陷影響的基于不存度計(jì)算特征重要性的替代選項(xiàng)。這里兩種方法對獲取特征重要性進(jìn)行了探討::置換重要性與隨機(jī)森林特征重要性(MDI)。
下面的示例顯示了使用 ExtraTreesClassifier
模型對人臉識別任務(wù)的單個(gè)像素的相對重要性的顏色編碼表示。
實(shí)際上,這些估計(jì)值存儲在一個(gè)已經(jīng)擬合的模型的屬性
feature_importances_
上。這是一個(gè)大小為(n_features,)
的數(shù)組,其值為正,總和為1.0。值越高,匹配特征對預(yù)測函數(shù)的貢獻(xiàn)就越重要。
示例 |
---|
基于平行樹的森林的像素重要性 樹森林的特征重要性 |
參考
[L2014] G. Louppe, “Understanding Random Forests: From Theory to Practice”, PhD Thesis, U. of Liege, 2014.
RandomTreesEmbedding
實(shí)現(xiàn)了一個(gè)無監(jiān)督的數(shù)據(jù)轉(zhuǎn)換。 通過由完全隨機(jī)樹構(gòu)成的森林,RandomTreesEmbedding
使用數(shù)據(jù)最終歸屬的葉子節(jié)點(diǎn)的索引值對數(shù)據(jù)進(jìn)行編碼。 該索引以 one-of-K 方式編碼,最終形成一個(gè)高維的稀疏二值化編碼。 這種編碼可以被非常高效地計(jì)算出來,并且可以作為其他學(xué)習(xí)任務(wù)的基礎(chǔ)。 編碼的大小和稀疏度可以通過選擇樹的數(shù)量和每棵樹的最大深度來確定。對于集成中的每棵樹的,每個(gè)樣本對應(yīng)其中的一個(gè)葉節(jié)點(diǎn)。 編碼的大?。ňS度)最多為 n_estimators * 2 ** max_depth
,即森林中的葉子節(jié)點(diǎn)的最大數(shù)。
由于相鄰數(shù)據(jù)點(diǎn)更可能位于一顆樹的同一葉子中,該變換可以作為一種隱式地非參數(shù)密度估計(jì)。
示例 |
---|
基于完全隨機(jī)樹的哈希特征變換 手寫數(shù)字上的流形學(xué)習(xí):局部線性嵌入,Isomap… 比較了手寫體數(shù)字的非線性降維技術(shù)。 樹集成的特征轉(zhuǎn)換 比較了基于樹的有監(jiān)督和無監(jiān)督特征變換. |
也可以看這里:流形學(xué)習(xí)技術(shù)也可以用來導(dǎo)出特征空間的非線性表示,這些方法也側(cè)重于維數(shù)約簡。
sklearn.ensemble
模塊包含了流行的提升算法 AdaBoost, 這個(gè)算法是由 Freund 和 Schapire 在 1995 年提出來的[FS1995]。
AdaBoost 的核心思想是用反復(fù)調(diào)整的數(shù)據(jù)來訓(xùn)練一系列的弱學(xué)習(xí)器(一個(gè)弱學(xué)習(xí)器模型僅僅比隨機(jī)猜測好一點(diǎn), 比如一個(gè)簡單的決策樹),由這些弱學(xué)習(xí)器的預(yù)測結(jié)果通過加權(quán)投票(或加權(quán)求和)的方式組合, 產(chǎn)生最終的預(yù)測結(jié)果。在每一次所謂的提升(boosting)迭代中,數(shù)據(jù)的修改由應(yīng)用于每一個(gè)訓(xùn)練樣本的(新) 的權(quán)重 組成。 初始化時(shí),將所有弱學(xué)習(xí)器的權(quán)重都設(shè)置為 ,因此第一次迭代僅僅是通過原始數(shù)據(jù)訓(xùn)練出一個(gè)弱學(xué)習(xí)器。在接下來的連續(xù)迭代中,樣本的權(quán)重逐個(gè)地被修改,學(xué)習(xí)算法也因此要重新應(yīng)用這些已經(jīng)修改的權(quán)重的數(shù)據(jù)。在給定的一個(gè)迭代中, 那些在上一輪迭代中被預(yù)測為錯誤結(jié)果的樣本的權(quán)重將會被增加,而那些被預(yù)測為正確結(jié)果的樣本的權(quán)重將會被降低。隨著迭代次數(shù)的增加,那些難以預(yù)測的樣例的影響將會越來越大,每一個(gè)隨后的弱學(xué)習(xí)器都將會被強(qiáng)迫更加關(guān)注那些在之前被錯誤預(yù)測的樣例[HTF]。
AdaBoost可以用于分類和回歸問題:
AdaBoostClassifier
實(shí)現(xiàn)了AdaBoost-Samme和AdaBoost-SAMME.R[ZRH 2009]。AdaBoostRegressor
實(shí)現(xiàn)了AdaBoost.R2[D 1997]。下面的示例演示如何為100個(gè)弱學(xué)習(xí)器擬合AdaBoost分類器:
>>> from sklearn.model_selection import cross_val_score
>>> from sklearn.datasets import load_iris
>>> from sklearn.ensemble import AdaBoostClassifier
>>> X, y = load_iris(return_X_y=True)
>>> clf = AdaBoostClassifier(n_estimators=100)
>>> scores = cross_val_score(clf, X, y, cv=5)
>>> scores.mean()
0.9...
弱學(xué)習(xí)器的數(shù)量由參數(shù)n_estimators
控制。learning_rate
參數(shù)控制著弱學(xué)習(xí)者在最終組合中的貢獻(xiàn)。默認(rèn)情況下,弱學(xué)習(xí)器是決策樹。通過 base_estimator
參數(shù)可以指定不同的弱學(xué)習(xí)器。要獲得良好結(jié)果的主要參數(shù)是n_estimators
和基估計(jì)器的復(fù)雜度(例如,它的深度 max_depth
或考慮分裂的最小樣本數(shù)min_samples_split
)。
示例 |
---|
離散型與真實(shí)型AdaBoost 使用 AdaBoost-SAMME 和 AdaBoost-SAMME.R 比較 decision stump, decision tree(決策樹)和 boosted decision stump(增強(qiáng)決策樹)的分類錯誤 多類AdaBoost決策樹 展示了 AdaBoost-SAMME 和 AdaBoost-SAMME.R 在 multi-class (多類)問題上的性能。 兩類AdaBoost 展示了使用 AdaBoost-SAMME 的非線性可分兩類問題的決策邊界和決策函數(shù)值。 基于AdaBoost的決策樹回歸 使用 AdaBoost.R2 算法證明了回歸。 |
參考
[FS1995] Y. Freund, and R. Schapire, “A Decision-Theoretic Generalization of On-Line Learning and an Application to Boosting”, 1997. [ZZRH2009] J. Zhu, H. Zou, S. Rosset, T. Hastie. “Multi-class AdaBoost”, 2009. [D1997] Drucker. “Improving Regressors using Boosting Techniques”, 1997. HTF(1,2,3) T. Hastie, R. Tibshirani and J. Friedman, “Elements of Statistical Learning Ed. 2”, Springer, 2009.
梯度樹提升Gradient Tree Boosting或梯度提升樹(Gradient Boosted Decision Trees,GBDT)是Booting對任意可微損失函數(shù)的推廣。GBDT是一種準(zhǔn)確有效的現(xiàn)成程序,可用于各種領(lǐng)域的回歸和分類問題,包括Web搜索、排名和生態(tài)領(lǐng)域。
集成模塊 sklearn.ensemble
通過梯度提升樹提供了分類和回歸的方法。
注意:在LightGBM (參看 [LightGBM])的啟發(fā)下,Scikit-learn 0.21引入了兩種新的梯度提升樹的實(shí)驗(yàn)實(shí)現(xiàn),即 HistGradientBoostingClassifier和 HistGradientBoostingRegressor。當(dāng)樣本數(shù)大于數(shù)萬個(gè)樣本時(shí),這些基于直方圖的估計(jì)可以比
GradientBoostingClassifier
和GradientBoostingRegressor
快幾個(gè)數(shù)量級。他們還內(nèi)置了對缺失值的支持,從而避免了計(jì)算的需要。這些估計(jì)器將在下面基于直方圖的梯度提升Histogram-Based Gradient Boosting中更詳細(xì)地描述。下面的指南重點(diǎn)介紹
GradientBoostingClassifier
和GradientBoostingRegressor
,它們可能是小樣本大小的首選,因?yàn)樵谶@個(gè)設(shè)置中,裝箱可能會導(dǎo)致分割點(diǎn)過于接近。
下面介紹了 GradientBoostingClassifier
和 GradientBoostingRegressor
的用法和參數(shù)。這些估計(jì)器最重要的兩個(gè)參數(shù)是n_estimators
和learning_rate
。
GradientBoostingClassifier
既支持二分類,也支持多類分類。下面的示例說明了如何將梯度提升分類器與100個(gè)決策樹作為弱學(xué)習(xí)者進(jìn)行匹配:
>>> from sklearn.datasets import make_hastie_10_2
>>> from sklearn.ensemble import GradientBoostingClassifier
>>> X, y = make_hastie_10_2(random_state=0)
>>> X_train, X_test = X[:2000], X[2000:]
>>> y_train, y_test = y[:2000], y[2000:]
>>> clf = GradientBoostingClassifier(n_estimators=100, learning_rate=1.0,
... max_depth=1, random_state=0).fit(X_train, y_train)
>>> clf.score(X_test, y_test)
0.913...
弱學(xué)習(xí)器的數(shù)量(即回歸樹)由參數(shù)n_estimators
控制,每棵樹的大小The size of each tree可以通過設(shè)置樹的深度max_depth
來控制,也可以通過通過最大葉節(jié)點(diǎn)樹max_leaf_nodes
數(shù)來控制。學(xué)習(xí)速率 learning_rate
是一個(gè)范圍是(0.0,1.0]的一個(gè)超參數(shù),它通過shrinkage 來控制過擬合。
注意:超過兩類的分類問題需要在每一次迭代時(shí)推導(dǎo)
n_classes
個(gè)回歸樹。因此,所有的需要推導(dǎo)的樹數(shù)量等于n_classes * n_estimators
。對于擁有大量類別的數(shù)據(jù)集我們強(qiáng)烈推薦使用HistGradientBoostingClassifier
來代替GradientBoostingClassifier
。
對于回歸問題 GradientBoostingRegressor
支持一系列損失函數(shù),這些損失函數(shù)可以通過參數(shù) loss
來指定;對于回歸問題默認(rèn)的損失函數(shù)是最小二乘損失( 'ls'
)。
>>> import numpy as np
>>> from sklearn.metrics import mean_squared_error
>>> from sklearn.datasets import make_friedman1
>>> from sklearn.ensemble import GradientBoostingRegressor
>>> X, y = make_friedman1(n_samples=1200, random_state=0, noise=1.0)
>>> X_train, X_test = X[:200], X[200:]
>>> y_train, y_test = y[:200], y[200:]
>>> est = GradientBoostingRegressor(n_estimators=100, learning_rate=0.1,
... max_depth=1, random_state=0, loss='ls').fit(X_train, y_train)
>>> mean_squared_error(y_test, est.predict(X_test))
5.00...
下圖顯示了將最小二乘損失和500個(gè)基學(xué)習(xí)器的GradientBoostingRegressor
應(yīng)用于波士頓房價(jià)數(shù)據(jù)集(sklearn.datasets.load_boston
)的結(jié)果。左邊的圖顯示了每次迭代時(shí)的訓(xùn)練和測試誤差。每一次迭代時(shí)的訓(xùn)練誤差都存儲在梯度提升模型的train_score_
屬性中。每次迭代時(shí)的測試誤差可以通過staged_predict
方法獲得,該方法返回在每個(gè)階段生成預(yù)測的生成器。這樣畫圖可以通過早期停止來確定樹的最優(yōu)數(shù)目(即 n_estimators
)。右邊的圖顯示了基于不存度的特征重要性,它可以通過feature_importances_
屬性獲得。
示例 |
---|
梯度提升回歸 梯度提升袋外估計(jì) |
GradientBoostingRegressor
和 GradientBoostingClassifier
都支持 warm_start=True
,這允許您在已經(jīng)擬合的模型中添加更多的估計(jì)器
>>> _ = est.set_params(n_estimators=200, warm_start=True)
# set warm_start and new nr of trees
>>> _ = est.fit(X_train, y_train) # fit additional 100 trees to est
>>> mean_squared_error(y_test, est.predict(X_test))
3.84...
回歸樹基學(xué)習(xí)器的大小定義了梯度提升模型可以捕捉到的變量交互的水平。一般來說,深度h
的樹可以捕捉h
階的相互作用。有兩種方法可以控制單個(gè)回歸樹的大小。
如果你指定 max_depth=h
,那么將會產(chǎn)生一個(gè)深度為 h
的完全二叉樹。這棵樹將會有(至多) 2**h
個(gè)葉子節(jié)點(diǎn)和 2**h - 1
個(gè)分割節(jié)點(diǎn)。
或者,您還可以通過參數(shù)max_leaf_nodes
指定葉節(jié)點(diǎn)的數(shù)目來控制樹的大小。在這種情況下,樹將使用最佳優(yōu)先搜索來生長,這種搜索方式是通過每次選取對不純度提升最大的節(jié)點(diǎn)來首先展開。一棵 max_leaf_nodes=k
的樹擁有 k - 1
個(gè)切分節(jié)點(diǎn),因此可以模擬max_leaf_nodes - 1
階的交互作用。
我們發(fā)現(xiàn) max_leaf_nodes=k
可以給出與 max_depth=k-1
品質(zhì)相當(dāng)?shù)慕Y(jié)果,但是其訓(xùn)練速度明顯更快,同時(shí)也會以多一點(diǎn)的訓(xùn)練誤差作為代價(jià)。參數(shù) max_leaf_nodes
對應(yīng)于文章 [F2001]中梯度提升章節(jié)中的變量 J
,同時(shí)與 R 語言的 gbm 包的參數(shù) interaction.depth
相關(guān),兩者間的關(guān)系是 max_leaf_nodes == interaction.depth + 1
。
我們首先說GBRT的回歸,然后詳細(xì)介紹分類案例。
GBRT回歸器是一種加法模型,其對給定輸入的預(yù)測由以下形式給出:
其中,是在boosting中被稱為弱學(xué)習(xí)器的估計(jì)器。梯度樹提升采用固定大小的決策樹回歸器作為弱學(xué)習(xí)器。常數(shù)對應(yīng)n_estimators
參數(shù)。
與其他提升算法類似,GBRT是以貪婪的方式構(gòu)建的:
其中新添加的樹中的是為了最小化損失的總和而擬合的,給定前面的集成器為:
其中由loss
參數(shù)定義,詳見下一節(jié)。
默認(rèn)情況下,初始模型選擇使損失最小化的常數(shù):對于最小二乘損失,這是目標(biāo)值的經(jīng)驗(yàn)平均值。初始模型也可以通過init
參數(shù)指定。
使用一階泰勒(Taylor)近似,的值可以近似為如下:
注意:簡要地說, 一階泰勒近似是:, 這里對應(yīng), 對應(yīng)。
是損失相對于第二個(gè)參數(shù)的導(dǎo)數(shù), 這里按計(jì)算。對于任何給定的,由于損失都是可微的,因此很容易計(jì)算出它的閉合形式。我們用表示。
除去常數(shù)項(xiàng),我們有:
如果被擬合來預(yù)測的值與負(fù)梯度成正比,則這是最小化的。因此,在每次迭代時(shí),被擬合的估計(jì)器用來預(yù)測樣本的負(fù)梯度。梯度在每次迭代中都會被更新。這可以看作是函數(shù)空間中的某種梯度下降。
注意:注意,對于一些損失,例如最小絕對偏差(LAD),其梯度為±1,擬合的預(yù)測的值不夠精確:這樣樹只能輸出整數(shù)值。因此,一旦樹被擬合,樹的葉子上的值就會被修改,使葉子上的能能最小化損失。更新是依賴于損失的:對于LAD損失,葉子的值將被更新為該葉中樣本的中值。
梯度提升的分類非常類似于回歸的情況。然而,樹的總和 與預(yù)測不是同質(zhì)的:它不能是一個(gè)類,因?yàn)闃漕A(yù)測的是連續(xù)值。
從到類或概率的映射依賴于損失。對于偏差(或?qū)?shù)損失), 屬于正類的概率被建模為,其中是sigmoid函數(shù)。
對于多類分類,K樹(對于K類)是在每一個(gè)迭代中構(gòu)建的。屬于k類的概率被建模為值的一個(gè)Softmax。
請注意,即使對于分類任務(wù),基估計(jì)器仍然是一個(gè)回歸器,而不是分類器。這是因?yàn)榛烙?jì)器被訓(xùn)練來預(yù)測(負(fù))梯度,這些梯度總是連續(xù)的。
支持下面這些損失函數(shù),并可以使用參數(shù) loss
指定這些函數(shù):
'ls'
):回歸的自然選擇,因?yàn)樗哂袃?yōu)越的計(jì)算特性。用目標(biāo)值的平均值給出了初始模型。'lad'
):一個(gè)穩(wěn)健的回歸損失函數(shù)。初始模型由目標(biāo)值的中值給出。‘Huber’
):另一個(gè)結(jié)合最小二乘和最小絕對偏差的穩(wěn)健損失函數(shù);使用alpha
控制異常值的靈敏度(詳見[F2001])。'quantile'
):分位數(shù)回歸的損失函數(shù)。使用 0 < alpha < 1
指定分位數(shù)。此損失函數(shù)可用于創(chuàng)建預(yù)測間隔 (參見梯度提升回歸的預(yù)測間隔 Prediction Intervals for Gradient Boosting Regression)'deviance'
):二分類的負(fù)二項(xiàng)式對數(shù)似然損失函數(shù)(提供概率估計(jì))。用對數(shù)比率給出了初始模型。'deviance'
):對于多分類問題的負(fù)的多項(xiàng)對數(shù)似然損失函數(shù)具有 n_classes
個(gè)互斥的類。提供概率估計(jì)。 初始模型由每個(gè)類的先驗(yàn)概率給出.在每一次迭代中 n_classes
回歸樹被構(gòu)建,這使得 GBRT 在處理多類別數(shù)據(jù)集時(shí)相當(dāng)?shù)托А?/section>'exponential'
):與 AdaBoostClassifier
具有相同的損失函數(shù)。與 'deviance'
相比,對被錯誤標(biāo)記的樣本的魯棒性較差,僅用于在二分類問題。[F2001] 提出了一種簡單的正則化策略,通過常數(shù)因子 來衡量每個(gè)弱學(xué)習(xí)器的貢獻(xiàn):
參數(shù)也稱為學(xué)習(xí)速率,因?yàn)樗梢钥s放步長、梯度下降過程;它可以通過 learning_rate
參數(shù)來設(shè)置。
參數(shù)learning_rate
與 n_estimators
(弱學(xué)習(xí)器的個(gè)數(shù))有很強(qiáng)的相互作用。較小的learning_rate
值要求較多的弱學(xué)習(xí)者以保持一個(gè)恒定的訓(xùn)練誤差。經(jīng)驗(yàn)證據(jù)表明,較小的learning_rate
有利于更好的測試誤差。[HTF]建議將學(xué)習(xí)速率設(shè)置為一個(gè)小常數(shù)(例如,learning_rate <= 0.1
),并通過早期的停止選擇n_estimators
。關(guān)于learning_rate
和 n_estimators
之間相互作用的更詳細(xì)的討論,見 [R2007]。
[F1999] 提出了隨機(jī)梯度提升,這種方法將梯度提升(gradient boosting)和 bootstrap averaging(bagging) 相結(jié)合。在每次迭代中,基分類器是通過抽取所有可利用訓(xùn)練集中一小部分的 subsample
訓(xùn)練得到的子樣本采用無放回的方式采樣。 subsample
參數(shù)的值一般設(shè)置為 0.5 。
下圖表明了收縮與否和子采樣對于模型擬合好壞的影響。我們可以明顯看到指定收縮率比沒有收縮擁有更好的表現(xiàn)。而將子采樣和收縮率相結(jié)合能進(jìn)一步的提高模型的準(zhǔn)確率。相反,使用子采樣而不使用收縮的結(jié)果十分糟糕。
另一種降低方差的策略是對隨機(jī)森林分類器中類似隨機(jī)分裂的特征進(jìn)行二次采樣。通過
max_features
參數(shù)可以控制子采樣特征的數(shù)量。
注意:使用一個(gè)較小的
max_Feature
值可以顯著減少運(yùn)行時(shí)。
隨機(jī)梯度提升允許計(jì)算測試偏差的袋外估計(jì)(Out-of-bag),方法是計(jì)算那些不在自助采樣之內(nèi)的樣本(比如袋外數(shù)據(jù))偏差的改進(jìn)。這些改進(jìn)存儲在屬性oob_improvement_
中。如果將第階段添加到當(dāng)前的預(yù)測中,則 oob_improvement_[i]
保存了在OOB樣本損失方面的改進(jìn)。袋外估計(jì)可以使用在模型選擇中,例如決定最優(yōu)迭代次數(shù)。 OOB 估計(jì)通常都很悲觀,因此我們推薦使用交叉驗(yàn)證來代替它,而當(dāng)交叉驗(yàn)證太耗時(shí)時(shí)我們就只能使用 OOB 了。
例子 |
---|
梯度提升正則 梯度提升袋外估計(jì) 隨機(jī)森林的OOB |
通過簡單的可視化樹結(jié)構(gòu),可以很容易地解釋單個(gè)決策樹。然而,梯度提升模型包含了數(shù)百棵回歸樹,因此它們很難通過對單個(gè)樹的可視化來進(jìn)行解釋。幸運(yùn)的是,已經(jīng)提出了一些技術(shù)來總結(jié)和解釋梯度提升模型。
通常,特性對預(yù)測目標(biāo)響應(yīng)的貢獻(xiàn)并不相同;在許多情況下,大多數(shù)特征實(shí)際上是無關(guān)的。在解釋模型時(shí),第一個(gè)問題通常是:重要的特征是什么,并且它們在預(yù)測目標(biāo)響應(yīng)方面有何貢獻(xiàn)?
單個(gè)決策樹本質(zhì)上通過選擇合適的分割點(diǎn)來進(jìn)行特征選擇。這些信息可以用來度量每個(gè)特征的重要性;基本思想是:在樹的分割點(diǎn)中使用某特征越頻繁,該特性就越重要。這種重要性的概念可以通過簡單地平均每個(gè)樹的基于不存度的特征重要性來擴(kuò)展到?jīng)Q策樹集成器上(更多細(xì)節(jié)請參見特征重要性評估Feature importance evaluation)。
一個(gè)擬合的梯度提升模型的特征重要性分?jǐn)?shù)可以通過feature_importances_
屬性訪問:
>>> from sklearn.datasets import make_hastie_10_2
>>> from sklearn.ensemble import GradientBoostingClassifier
>>> X, y = make_hastie_10_2(random_state=0)
>>> clf = GradientBoostingClassifier(n_estimators=100, learning_rate=1.0,
... max_depth=1, random_state=0).fit(X, y)
>>> clf.feature_importances_
array([0.10..., 0.10..., 0.11..., ...
請注意,這種特征重要性的計(jì)算是基于熵的,并且它不同于sklearn.inspection.permutation_importance
,后者是基于特征的排列。
示例 |
---|
梯度提升回歸 |
Scikit-Leard0.21介紹了兩種新的梯度提升樹的實(shí)驗(yàn)實(shí)現(xiàn),即基于LightGBM(見[LightGBM])的HistGradientBoostingClassifier
和 HistGradientBoostingRegressor
。
當(dāng)樣本數(shù)大于數(shù)萬個(gè)樣本時(shí),這些基于直方圖的估計(jì)器可以比 GradientBoostingClassifier
和GradientBoostingRegressor
快幾個(gè)數(shù)量級。
他們還內(nèi)置了對缺失值的支持,從而避免了計(jì)算機(jī)的需要。
這些快速估計(jì)器首先將輸入樣本X
放入整數(shù)值箱(通常為256個(gè)),這極大地減少了要考慮的分裂點(diǎn)數(shù),并允許算法在構(gòu)建樹時(shí)利用基于整數(shù)的數(shù)據(jù)結(jié)構(gòu)(直方圖)而不是依賴排序的連續(xù)值。這些估計(jì)器的API略有不同,對一些損失函數(shù)的 GradientBoostingClassifier
和 GradientBoostingRegressor
的實(shí)例將不再支持一些特性。
這些估計(jì)器仍然是實(shí)驗(yàn)性的:它們的預(yù)測和API可能在沒有任何反對周期的情況下發(fā)生變化。要使用它們,您需要顯式地導(dǎo)入enable_hist_gradient_boosting
:
>>> # explicitly require this experimental feature
>>> from sklearn.experimental import enable_hist_gradient_boosting # noqa
>>> # now you can import normally from ensemble
>>> from sklearn.ensemble import HistGradientBoostingClassifier
示例 |
---|
部分依賴圖 |
大多數(shù)參數(shù)來自 GradientBoostingClassifier
和GradientBoostingRegressor
。一個(gè)例外是max_iter
參數(shù),該參數(shù)取代 n_estimators
,并控制提升過程的迭代次數(shù):
>>> from sklearn.experimental import enable_hist_gradient_boosting
>>> from sklearn.ensemble import HistGradientBoostingClassifier
>>> from sklearn.datasets import make_hastie_10_2
>>> X, y = make_hastie_10_2(random_state=0)
>>> X_train, X_test = X[:2000], X[2000:]
>>> y_train, y_test = y[:2000], y[2000:]
>>> clf = HistGradientBoostingClassifier(max_iter=100).fit(X_train, y_train)
>>> clf.score(X_test, y_test)
0.8965
可用的回歸損失有‘least_squares’, ‘least_absolute_deviation’(對異常值不太敏感)和 ‘poisson’(非常適合模型計(jì)數(shù)和頻率)。在分類方面,‘binary_crossentropy’ 用于二分類, ‘categorical_crossentropy’用于多分類。默認(rèn)情況下,損失函數(shù)是 ‘a(chǎn)uto’,并將更具傳入的y選擇合適的損失函數(shù)進(jìn)行fit。
樹的大小可以通過 max_leaf_nodes
, max_depth
, 和 min_samples_leaf
參數(shù)來控制。
用于存儲數(shù)據(jù)的回收箱數(shù)量由max_bins參數(shù)控制。使用較少的垃圾箱作為一種形式的正規(guī)化。通常建議使用盡可能多的回收箱,這是默認(rèn)的。
用于裝數(shù)據(jù)的箱子數(shù)量由max_bins
參數(shù)控制。使用較少的箱子可以作為一種正則化的形式。通常建議使用盡可能多的箱子,這是默認(rèn)的。
l2_regularization
參數(shù)是損失函數(shù)上的正則化參數(shù),對應(yīng)于[XGBoost]方程(2)中的。
注意,如果樣本數(shù)大于10,000,則默認(rèn)啟用早期停止。早期停止行為通過 early-stopping
, scoring
, validation_fraction
, n_iter_no_change
, and tol
參數(shù)來控制.使用一個(gè)隨意的scorer,或僅僅是訓(xùn)練或驗(yàn)證的損失是有可能早期停止的。注意,由于技術(shù)原因,使用 scorer比使用損失要慢得多。默認(rèn)情況下,如果訓(xùn)練集中至少有10,000個(gè)樣本,則使用驗(yàn)證損失執(zhí)行早期停止。
HistGradientBoostingClassifier
和 HistGradientBoostingRegressor
內(nèi)建了缺失值支持。
在訓(xùn)練過程中,生長的樹根據(jù)潛在的增益,在每次分割時(shí)無論樣本是否含有缺失值都應(yīng)該被劃分到右邊或者左邊。因此,因此, 在預(yù)測時(shí),有缺失值的樣本也會被分配給左或右的子節(jié)點(diǎn):
>>> from sklearn.experimental import enable_hist_gradient_boosting # noqa
>>> from sklearn.ensemble import HistGradientBoostingClassifier
>>> import numpy as np
>>> X = np.array([0, 1, 2, np.nan]).reshape(-1, 1)
>>> y = [0, 0, 1, 1]
>>> gbdt = HistGradientBoostingClassifier(min_samples_leaf=1).fit(X, y)
>>> gbdt.predict(X)
array([0, 0, 1, 1])
當(dāng)缺失模式具有預(yù)測性時(shí),可以根據(jù)特征值是否缺失進(jìn)行分割:
>>> X = np.array([0, np.nan, 1, 2, np.nan]).reshape(-1, 1)
>>> y = [0, 1, 0, 0, 1]
>>> gbdt = HistGradientBoostingClassifier(min_samples_leaf=1,
... max_depth=2,
... learning_rate=1,
... max_iter=1).fit(X, y)
>>> gbdt.predict(X)
array([0, 1, 0, 0, 1])
如果在訓(xùn)練期間給定特征下沒有碰見缺失值,則會將有缺少值的樣本映射到具有最多樣本的那個(gè)子節(jié)點(diǎn)上。
HistGradientBoostingClassifier
和 HistGradientBoostingRegressor
在fit的時(shí)候可以對樣本進(jìn)行加權(quán)。
下面的小示例演示了模型如何忽略樣本權(quán)重為零的樣本:
>>> X = [[1, 0],
... [1, 0],
... [1, 0],
... [0, 1]]
>>> y = [0, 0, 1, 0]
>>> # ignore the first 2 training samples by setting their weight to 0
>>> sample_weight = [0, 0, 1, 1]
>>> gb = HistGradientBoostingClassifier(min_samples_leaf=1)
>>> gb.fit(X, y, sample_weight=sample_weight)
HistGradientBoostingClassifier(...)
>>> gb.predict([[1, 0]])
array([1])
>>> gb.predict_proba([[1, 0]])[0, 1]
0.99...
正如您所看到的,[1, 0]
被輕松地歸為1
,因?yàn)榍皟蓚€(gè)樣本由于其樣本權(quán)重而被忽略。
實(shí)現(xiàn)細(xì)節(jié):考慮樣本權(quán)重等于將梯度(和Hessians)乘以樣本權(quán)重。注意,二進(jìn)制階段(特別是分位數(shù)計(jì)算)沒有考慮權(quán)重。
根據(jù)手頭的問題,您可能事先了解到,給定的特征通常會對目標(biāo)值產(chǎn)生積極(或負(fù)面)影響。例如,在其他條件相同的情況下,較高的信用評分應(yīng)該會增加獲得貸款批準(zhǔn)的可能性。單調(diào)約束允許您將這些先驗(yàn)知識集成到模型中。
正單調(diào)約束是形式的約束:
, 其中是具有兩個(gè)特征的預(yù)測器。
同樣,負(fù)單調(diào)約束的形式如下:
請注意,單調(diào)約束只約束輸出“所有其他條件相同”。事實(shí)上,下列關(guān)系并不是通過積極的約束而得到加強(qiáng)的:
您可以使用 monotonic_cst
參數(shù)為每個(gè)特征指定一個(gè)單調(diào)約束。對于每個(gè)特征,值0表示沒有約束,而-1和1分別表示負(fù)約束和正約束:
>>> from sklearn.experimental import enable_hist_gradient_boosting # noqa
>>> from sklearn.ensemble import HistGradientBoostingRegressor
... # positive, negative, and no constraint on the 3 features
>>> gbdt = HistGradientBoostingRegressor(monotonic_cst=[1, -1, 0])
在二分類中,施加單調(diào)約束意味著特征對屬于正類的概率有正/負(fù)的影響。對于多類分類,不支持單調(diào)約束。
示例 |
---|
單調(diào)約束 |
HistGradientBoostingClassifier
and HistGradientBoostingRegressor
通過Cython使用使用OpenMP并行化。有關(guān)如何控制線程數(shù)量的詳細(xì)信息,請參閱我們的 Parallelism說明。
以下部分并行化:
梯度提升過程的瓶頸是決策樹的建立。構(gòu)建一個(gè)傳統(tǒng)的決策樹(如在其他GBDTs、GradientBoostingClassifier
和 GradientBoostingRegressor
中)需要在每個(gè)節(jié)點(diǎn)(針對每個(gè)特征)對樣本進(jìn)行排序。排序是必要的,以便能夠有效地計(jì)算一個(gè)分裂點(diǎn)的潛在增益。因此,分割單個(gè)節(jié)點(diǎn)的復(fù)雜度為,其中是節(jié)點(diǎn)上的樣本數(shù)。
相反,HistGradientBoostingClassifier
和 HistGradientBoostingRegressor
不需要對特征值進(jìn)行排序,而是使用名為histogram的數(shù)據(jù)結(jié)構(gòu),其中樣本是隱式排序的。構(gòu)造histogram的復(fù)雜度為,因此節(jié)點(diǎn)分裂過程的復(fù)雜度為,遠(yuǎn)遠(yuǎn)小于以前的算法。另外,我們不考慮個(gè)分裂點(diǎn),而是只考慮max_bins
分裂點(diǎn),它要小得多。
為了建立histograms,輸入數(shù)據(jù)X
需要被綁定到整數(shù)值的箱子中。這個(gè)裝箱過程確實(shí)需要對特征值進(jìn)行排序,但它只在提升過程開始時(shí)發(fā)生一次(而不是在每個(gè)節(jié)點(diǎn),不像GradientBoostingClassifier
和 GradientBoostingRegressor
。
最后,HistGradientBoostingClassifier
和 HistGradientBoostingRegressor
的實(shí)現(xiàn)了許多并行化。
參考
[F1999] Friedmann, Jerome H., 2007, “Stochastic Gradient Boosting”
[R2007] G. Ridgeway, “Generalized Boosted Models: A guide to the gbm package”, 2007
[XGBoost] Tianqi Chen, Carlos Guestrin, “XGBoost: A Scalable Tree Boosting System”
LightGBM(1,2) Ke et. al. “LightGBM: A Highly Efficient Gradient BoostingDecision Tree”
VotingClassifier
(投票分類器)的原理是結(jié)合了多個(gè)不同的機(jī)器學(xué)習(xí)分類器,并且采用多數(shù)表決(majority vote)(硬投票) 或者平均預(yù)測概率(軟投票)的方式來預(yù)測分類標(biāo)簽。 這樣的分類器可以用于一組同樣表現(xiàn)良好的模型,以便平衡它們各自的弱點(diǎn)。
在多數(shù)投票中,對于每個(gè)特定樣本的預(yù)測類別標(biāo)簽是所有單獨(dú)分類器預(yù)測的類別標(biāo)簽中票數(shù)占據(jù)多數(shù)(模式)的類別標(biāo)簽。
例如,如果給定樣本的預(yù)測是
VotingClassifier( voting='hard'
)將根據(jù)多數(shù)類標(biāo)簽將示例分類為 “class 1”。
在平局的情況下, VotingClassifier
將根據(jù)升序排序順序選擇類。例如,在下面的場景中
這種情況下, class 1 將會被指定為該樣本的類標(biāo)簽。
下面的示例演示如何擬合多數(shù)規(guī)則分類器:
>>> from sklearn import datasets
>>> from sklearn.model_selection import cross_val_score
>>> from sklearn.linear_model import LogisticRegression
>>> from sklearn.naive_bayes import GaussianNB
>>> from sklearn.ensemble import RandomForestClassifier
>>> from sklearn.ensemble import VotingClassifier
>>> iris = datasets.load_iris()
>>> X, y = iris.data[:, 1:3], iris.target
>>> clf1 = LogisticRegression(random_state=1)
>>> clf2 = RandomForestClassifier(n_estimators=50, random_state=1)
>>> clf3 = GaussianNB()
>>> eclf = VotingClassifier(
... estimators=[('lr', clf1), ('rf', clf2), ('gnb', clf3)],
... voting='hard')
>>> for clf, label in zip([clf1, clf2, clf3, eclf], ['Logistic Regression', 'Random Forest', 'naive Bayes', 'Ensemble']):
... scores = cross_val_score(clf, X, y, scoring='accuracy', cv=5)
... print("Accuracy: %0.2f (+/- %0.2f) [%s]" % (scores.mean(), scores.std(), label))
Accuracy: 0.95 (+/- 0.04) [Logistic Regression]
Accuracy: 0.94 (+/- 0.04) [Random Forest]
Accuracy: 0.91 (+/- 0.04) [naive Bayes]
Accuracy: 0.95 (+/- 0.04) [Ensemble]
與多數(shù)投票(硬投票)相比,軟投票將類別標(biāo)簽返回為預(yù)測概率之和的 argmax 。
通過weights
參數(shù),可以為每個(gè)分類器分配特定的權(quán)重。當(dāng)提供權(quán)值時(shí),收集每個(gè)分類器的預(yù)測類概率,乘以分類器權(quán)重,然后進(jìn)行平均。然后將具有最高平均概率的類別標(biāo)簽確定為最終類別標(biāo)簽。
為了用一個(gè)簡單的例子來說明這一點(diǎn),讓我們假設(shè)我們有3個(gè)分類器和一個(gè)3類分類問題,其中我們?yōu)樗蟹诸惼鞣峙湎嗟鹊臋?quán)重:w1=1, w2=1, w3=1。
然后計(jì)算樣本的加權(quán)平均概率如下:
這里,預(yù)測的類標(biāo)簽是2,因?yàn)樗哂凶罡叩钠骄怕省?/p>
下面的示例說明了在基于線性支持向量機(jī)、決策樹和K-最近鄰分類器的基礎(chǔ)上使用軟 VotingClassifier
時(shí),決策區(qū)域可能如何變化:
>>> from sklearn import datasets
>>> from sklearn.tree import DecisionTreeClassifier
>>> from sklearn.neighbors import KNeighborsClassifier
>>> from sklearn.svm import SVC
>>> from itertools import product
>>> from sklearn.ensemble import VotingClassifier
>>> # Loading some example data
>>> iris = datasets.load_iris()
>>> X = iris.data[:, [0, 2]]
>>> y = iris.target
>>> # Training classifiers
>>> clf1 = DecisionTreeClassifier(max_depth=4)
>>> clf2 = KNeighborsClassifier(n_neighbors=7)
>>> clf3 = SVC(kernel='rbf', probability=True)
>>> eclf = VotingClassifier(estimators=[('dt', clf1), ('knn', clf2), ('svc', clf3)],
... voting='soft', weights=[2, 1, 2])
>>> clf1 = clf1.fit(X, y)
>>> clf2 = clf2.fit(X, y)
>>> clf3 = clf3.fit(X, y)
>>> eclf = eclf.fit(X, y)
VotingClassifier
還可以與 GridSearchCV
一起使用,以調(diào)整單個(gè)估計(jì)器的超參數(shù):
>>> from sklearn.model_selection import GridSearchCV
>>> clf1 = LogisticRegression(random_state=1)
>>> clf2 = RandomForestClassifier(random_state=1)
>>> clf3 = GaussianNB()
>>> eclf = VotingClassifier(
... estimators=[('lr', clf1), ('rf', clf2), ('gnb', clf3)],
... voting='soft'
... )
>>> params = {'lr__C': [1.0, 100.0], 'rf__n_estimators': [20, 200]}
>>> grid = GridSearchCV(estimator=eclf, param_grid=params, cv=5)
>>> grid = grid.fit(iris.data, iris.target)
為了通過預(yù)測的類別概率來預(yù)測類別標(biāo)簽(投票分類器中的 scikit-learn estimators 必須支持 predict_proba
方法):
>>> eclf = VotingClassifier(
... estimators=[('lr', clf1), ('rf', clf2), ('gnb', clf3)],
... voting='soft'
... )
可選地,可以為各個(gè)分類器提供權(quán)重:
>>> eclf = VotingClassifier(
... estimators=[('lr', clf1), ('rf', clf2), ('gnb', clf3)],
... voting='soft', weights=[2,5,1]
... )
VotingRegressor
的思想是將上不同的機(jī)器學(xué)習(xí)回歸器組合起來,并返回平均預(yù)測值。這樣的回歸器對于一組同樣表現(xiàn)良好的模型是有用的,以平衡它們各自的弱點(diǎn)。
下面的示例演示如何擬合VotingRegressor:
>>> from sklearn.datasets import load_boston
>>> from sklearn.ensemble import GradientBoostingRegressor
>>> from sklearn.ensemble import RandomForestRegressor
>>> from sklearn.linear_model import LinearRegression
>>> from sklearn.ensemble import VotingRegressor
>>> # Loading some example data
>>> X, y = load_boston(return_X_y=True)
>>> # Training classifiers
>>> reg1 = GradientBoostingRegressor(random_state=1, n_estimators=10)
>>> reg2 = RandomForestRegressor(random_state=1, n_estimators=10)
>>> reg3 = LinearRegression()
>>> ereg = VotingRegressor(estimators=[('gb', reg1), ('rf', reg2), ('lr', reg3)])
>>> ereg = ereg.fit(X, y)
示例 |
---|
繪制單獨(dú)與投票回歸預(yù)測 |
疊加泛化是一種組合估計(jì)器減少偏差的方法 [W1992] [HTF]。更準(zhǔn)確地說,每一個(gè)估計(jì)器的預(yù)測被堆疊在一起,并作為最終估計(jì)器的輸入來計(jì)算預(yù)測。這個(gè)最終的估計(jì)器是通過交叉驗(yàn)證來訓(xùn)練的。
StackingClassifier
and StackingRegressor
提供了適用于分類和回歸問題的策略。
estimators
對應(yīng)于在估計(jì)器的列表, 它們在輸入數(shù)據(jù)上并行地堆疊在一起。它應(yīng)該是給出名字和估計(jì)器的列表:
>>> from sklearn.linear_model import RidgeCV, LassoCV
>>> from sklearn.svm import SVR
>>> estimators = [('ridge', RidgeCV()),
... ('lasso', LassoCV(random_state=42)),
... ('svr', SVR(C=1, gamma=1e-6))]
final_estimator
將使用 estimators
的預(yù)測作為輸入。當(dāng)使用StackingClassifier
或者StackingRegressor
, 時(shí),它需要是一個(gè)分類器或回歸器:
>>> from sklearn.ensemble import GradientBoostingRegressor
>>> from sklearn.ensemble import StackingRegressor
>>> reg = StackingRegressor(
... estimators=estimators,
... final_estimator=GradientBoostingRegressor(random_state=42))
為了訓(xùn)練estimators
和final_estimator
,需要對訓(xùn)練數(shù)據(jù)調(diào)用fit
方法:
>>> from sklearn.datasets import load_boston
>>> X, y = load_boston(return_X_y=True)
>>> from sklearn.model_selection import train_test_split
>>> X_train, X_test, y_train, y_test = train_test_split(X, y,
... random_state=42)
>>> reg.fit(X_train, y_train)
StackingRegressor(...)
在訓(xùn)練過程中,estimators
對整個(gè)訓(xùn)練數(shù)據(jù)X_train
進(jìn)行擬合。它們將在調(diào)用 predict
或“預(yù)測 predict_proba
時(shí)被調(diào)用。為了推廣和避免過擬合,final_estimator
在out-samples上被訓(xùn)練, 內(nèi)部使用 sklearn.model_selection.cross_val_predict
。
對于 StackingClassifier
,請注意, estimators
的輸出由參數(shù)stack_method
控制,并由每個(gè)估計(jì)器調(diào)用。該參數(shù)要么是字符串,即估計(jì)器方法名稱,要么是'auto'
,它將根據(jù)可用性自動識別可用的方法,并按偏好順序進(jìn)行測試:predict_proba
, decision_function
and predict
。
StackingRegressor
and StackingClassifier
可以用作任何其他的回歸者或分類器,通用方法predict
, predict_proba
, 和 decision_function
,例如:
>>> y_pred = reg.predict(X_test)
>>> from sklearn.metrics import r2_score
>>> print('R2 score: {:.2f}'.format(r2_score(y_test, y_pred)))
R2 score: 0.81
請注意,還可以使用 transform
方法獲得堆疊 estimators
的輸出:
>>> reg.transform(X_test[:5])
array([[28.78..., 28.43... , 22.62...],
[35.96..., 32.58..., 23.68...],
[14.97..., 14.05..., 16.45...],
[25.19..., 25.54..., 22.92...],
[18.93..., 19.26..., 17.03... ]])
在實(shí)際應(yīng)用中,堆疊預(yù)測器預(yù)測的效果與基本層的最佳預(yù)測器一樣好,有時(shí)甚至通過將這些預(yù)測器的不同強(qiáng)度組合在一起而優(yōu)于這些預(yù)測器。然而,訓(xùn)練堆疊預(yù)測器在計(jì)算上是昂貴的。
注意:
StackingClassifier
,當(dāng)使用stack_method_='predict_proba'
時(shí),當(dāng)問題是二分類問題時(shí),將刪除第一列。實(shí)際上,每個(gè)估計(jì)器預(yù)測的兩個(gè)概率列都是完全共線的。
注意:可以通過向
StackingClassifier
或者StackingRegressor
分配final_estimator
來實(shí)現(xiàn)多個(gè)堆疊層:>>> final_layer = StackingRegressor(
... estimators=[('rf', RandomForestRegressor(random_state=42)),
... ('gbrt', GradientBoostingRegressor(random_state=42))],
... final_estimator=RidgeCV()
... )
>>> multi_layer_regressor = StackingRegressor(
... estimators=[('ridge', RidgeCV()),
... ('lasso', LassoCV(random_state=42)),
... ('svr', SVR(C=1, gamma=1e-6, kernel='rbf'))],
... final_estimator=final_layer
... )
>>> multi_layer_regressor.fit(X_train, y_train)
StackingRegressor(...)
>>> print('R2 score: {:.2f}'
... .format(multi_layer_regressor.score(X_test, y_test)))
R2 score: 0.83
參考:
[W1992] Wolpert, David H. “Stacked generalization.” Neural networks 5.2 (1992): 241-259.
更多建議: