本文是sklearn官網文檔中集成模型一文的翻譯,加入了自己的理解,翻譯中難免有誤,僅作參考。
集成學習的目標是結合一組基學習器的預測構建學習算法來提高單個學習器的普遍性和健壯性。
通常有兩種方法:
- averaging:構建一組相互獨立的學習器求預測的均值。由于方差的減小,組合學習器的性能比任何單個學習器都好。(eg:bagging,隨機森林)
- boosting:基學習器串行組合,試圖減小組合學習器的偏差,把幾個弱學習器組合成一個強力的集成模型。(eg:adaboost,Gradient Tree Boosting)
1. bagging
集成算法中,bagging在原始訓練集的隨機子集上構建了幾個黑盒學習器,聚合各自的預測形成最終的預測。通過在構建過程中引入隨機化然后集成的方法來減小基學習器的方差(例如決策樹)。由于提供了一種減少過擬合的方法,bagging更適用于強學習器(eg,developed decision tree),而boosting更適用于弱學習器(eg,shallow decision tree)。
bagging有很多種類,但由于劃分隨機子集方法的不同,不同的模型也都不一樣:
- 當數據集的隨機子集被劃分為樣本的隨機子集時,則該算法被稱為Pasting。
- 當抽取樣品時,該方法稱為Bagging 。
- 當數據集的隨機子集被劃分為特征的隨機子集時,則該方法被稱為random subspaces。
- 當基本估計器建立在樣本和特征的子集上時,該方法被稱為random patches。
在sklearn中,bagging用統一的BaggingClassifier元分類器提供。以用戶指定的基學習器及制定劃分隨機子集的策略的參數作為輸入,特別地,max_samples 和 max_features控制子集的尺寸,bootstrap和bootstrap_features控制是否抽出樣本和特征。當使用可用樣本的子集時,可以通過設置是否用包外樣本來估計準確率oob_score=Ture,下面的代碼說明了怎樣用K近鄰分類器的集成模型,每個基學習器建立在50%樣本和50%特征的隨機子集上。
from sklearn.ensemble import BaggingClassifier
from sklearn.neighbors import KNeighborsClassifier
bagging = BaggingClassifier(KNeighborsClassifier(),
max_samples=0.5, max_features=0.5)
note:回歸問題上,學習器的均方誤差可以分為偏差(bias)、方差(variance)、噪音(noise)三項。偏差刻畫了不同學習器的預測能力,即模型本身的精確度,方差刻畫了學習器在數據擾動時的多樣性,即模型的穩定性,噪音刻畫了數據變化帶來的不可避免的誤差。想要一個小的偏差,需要復雜化模型,增加模型參數,此時方差增大,且容易過擬合,想要小的方差,需要簡化模型,減少模型參數,此時偏差增大,且容易欠擬合。由此,bias和variance往往是不能兼得的,造成這種現象的根本原因是,我們總是希望試圖用有限訓練樣本去估計無限的真實數據。Bias與Variance兩者之間的trade-off是機器學習的基本主題之一,可以在各種機器模型中發現它的影子。
2.決策樹的bagging
sklearn.ensemble模塊包括了兩個基于隨機決策樹的averaging算法:randomForest和Extra-Trees。這兩種算法都是專門為樹設計的擾動組合技術。通過在分類器構造中引入隨機性來創建一組不同的分類器。集成模型的預測是每個分類器的平均輸出。
forest分類器必須配備兩個矩陣:大小為[n_samples,n_features]的稀疏或密集矩陣X保存訓練樣本,大小為[n_samples]的矩陣Y保存訓練樣本的目標值
from sklearn.ensemble import RandomForestClassifier
X = [[0, 0], [1, 1]]
Y = [0, 1]
clf = RandomForestClassifier(n_estimators=10)
clf = clf.fit(X, Y)
和決策樹一樣,forest也可以擴展到多輸出問題,(Y是大小為[n_samples,n_outputs]的數組)
2.1 隨機森林
在隨機森林中,(RandomForestClassifier和RandomForestRegressor類),集成模型中的每個樹都是從訓練集中替換抽取的樣本構建的(自主采樣)。另外,在樹的構建期間分割節點時,選擇的分割不再是所有特征的最佳分割,而是特征的隨機子集的最佳分割。由于這種隨機性,forest的偏差通常會略微增加(相對于單個隨機樹的偏差),但由于平均,方差也減小了,通常大于補償的偏差增加,從而產生更好的模型。
與原始模型相反,sklearn實現通過對分類器的概率預測進行平均而不是讓每個分類器對但各類進行投票組合。
2.2 極端隨機森林
極端隨機森林中(ExtraTreesClassifier和ExtraTreesRegressor類),隨機性被進一步分離計算。與隨機森林一樣,使用候選特征的隨機子集,但不是尋找最優判別屬性,而是為每個候選特征隨機選擇閾值,并將隨機生成的閾值的最佳值作為分割原則。這通常會更多地減少模型的方差,犧牲偏差,讓偏差增加:
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)
scores.mean()
clf = RandomForestClassifier(n_estimators=10, max_depth=None,
min_samples_split=2, random_state=0)
scores = cross_val_score(clf, X, y)
scores.mean()
clf = ExtraTreesClassifier(n_estimators=10, max_depth=None,
min_samples_split=2, random_state=0)
scores = cross_val_score(clf, X, y)
scores.mean() > 0.999
2.3 參數
使用這些模型時需要調節的主要參數是n_estimators和max_features.前者是森林的樹木數量,越大越好,但計算時間也會越長。另外注意,超過關鍵數量的樹木,結果將會停止顯著改善。后者是分割節點時要考慮的特征的隨機子集的大小。方差減小更小更好,而偏差增加更好。對于回歸問題,經驗默認max_features=n_features,對于分類問題,max_features=sqrt(n_features),n_features是數據特征數目。通常max_depth=None,min_samples_spilt=1。這些值通常不是最佳的,并且可能導致消耗大量RAM,最好的參數值應該是始終交叉驗證的,另外注意,在隨機森林中,默認使用抽樣樣本bootstrap=True,而極端隨機森林中默認是使用整個數據集bootstrap=False。當使用抽樣樣本時,可以在包外樣本上估計泛化精度,設置oob_score=True.
2.4 并行化
最后,該模塊還可以通過設置n_jobs進行樹的并行構建和預測的并行計算。如果n_jobs=k,計算被劃分為k個作業,在計算機的k個線程運行。如果n_jobs=1,可以使用所有線程。請注意,由于進程間通信開銷,加速可能不是線性的,使用k個線程并不會k倍那么快。建立大量的樹或構建耗時長的單個樹時,仍可以實現顯著的加速。
2.5 特征重要性評估
用樹中決策節點的特征的相對等級(即深度)可用于評估該特征相對于目標變量的可預測性的相對重要性。樹上端的特征給最終預測決策貢獻了更大的分數。因此,他們貢獻的樣本的預測分數可以用作對特征的相對重要性的評估。
通過在幾個隨機樹中平均化這些期望活動率可以 減少估計的方差,并將其用作特征選擇。
實踐中,這些估計值作為feature_importances_屬性.正值,總和為1.值越高,匹配特征對預測函數的貢獻越重要。
RandomForestClassifier方法
Parameter:
- n_estimators :默認為10,森林中樹的數量
- criterion:默認 為‘gini’,分割屬性的標定函數,gini基尼不純度或entropy信息增益
- max_features:尋找最佳分割的特征數目,默認‘auto’
- int:每次分割時考慮int個特征
- float:百分比,int(max_features * n_features)
- auto:max_features=sqrt(n_features)
- sqrt:和auto一樣
- log2:max_features=log2(n_features)
- None:max_features=n_features
- max_depth:默認None,樹的最大深度,如果為None,則節點擴展直至葉子節點劃分完或小于min_samples_split ,樣本量少時可以不管
- min_samples_split:默認為2,分割內部節點時要求的最小樣本數目,樣本量少時可以不管
- min_samples_leaf:默認為1,葉子節點要求的最小樣本數目,樣本量少時可以不管
- min_weight_fraction_leaf :默認0,葉子節點所有樣本權重和的最小值。為0表示不考慮權重問題,樣本有相同權重。
- max_leaf_nodes:默認為0,最大葉子節點數,加了限制會在最大數內用最佳搜索方式展開樹,防止過擬合
- min_impurity_split:節點最小不純度,大于該值則繼續分裂,否則成為葉子節點
- bootstrap:自主采樣,默認True,極端隨機森林默認為false
- oob_score:默認false,是否采用包外樣本估計泛化精度
- n_jobs:計算的線程數
- warm_start:默認false,true表示復用之前的方法添加更多的學習器到集成模型中
3.Adaboost
sklearn.ensemble模塊包括了流行的提升算法,Adaboost。
Adaboost的核心原則是在數據的反復修改版本上適應一系列弱學習器(僅比隨機猜測略好的模型,如小決策樹),然后將所有這些預測通過加權多數表決(或總和)合并產生最終預測。在每一個提升迭代的數據修改由每個訓練樣本施加權重的W1,W2,。。。Wn組成。最初,這些權重都被設置為1/N,所以第一步只是訓練弱學習器的原始數據。對于每個連續的迭代,樣本權重被單獨修改,并將學習算法重新應用于重新加權的數據。在給定的步驟,那些在前一步驟導致提升模型不正確預測的訓練樣本的權重增加,而正確預測的訓練樣本的權重則會降低。隨著迭代的進行,難以預測的示例將會受到越來越大的影響。因此,每個隨后的弱學習器強制關注先前的錯誤樣本。
3.1 用法
下面的例子展示了怎樣配置100個弱學習器的Adaboost分類器
from sklearn.model_selection import cross_val_score
from sklearn.datasets import load_iris
from sklearn.ensemble import AdaBoostClassifier
iris = load_iris()
clf = AdaBoostClassifier(n_estimators=100)
scores = cross_val_score(clf, iris.data, iris.target)
scores.mean()
弱學習器的數量由參數n_estimators控制,參數learning_rate控制弱學習器最后結合的貢獻率。默認下,弱學習器是決策樹。可以通過base_estimator參數制定不同的弱學習器。導致性能好壞的主要參數是n_estimators和基學習器的復雜度(比如它的深度max_depth和最小所需樣本數min_samples_leaf)
AdaBoostClassifier方法
Parameter:
- base_estimator :default=DecisionTreeClassifier,梯度集成的基學習器
- n_estimators :default=50,學習器的最大數量,為了完美擬合,學習進程可能會早停
- learning_rate :default=1. ,學習率收縮每個學習器的貢獻,learning_rate和n_estimators之間有一個平衡
- algorithm :{'SAMME', 'SAMME.R'}, optional (default='SAMME.R') real boosting algorithm.SAMME,discrete boosting algorithm.SAMME.R具有更快的收斂速度,用更少的迭代實現更小的誤差
4. Gradient Tree Boosting
Gradient Tree Boosting或Gradient Boosted Regression Trees(GBRT)是任意可導損失函數提升模型的歸納。GBRT是一個準確有效的現成程序,可用于回歸和分類問題。Gradient Tree Boosting模型可用于各種領域,包括web搜索排名和生態學。
GBRT的優點:
? 混合型數據的自然處理(異構特征)
? 預測強力
? 輸出空間異常值的魯棒性(強大的損失函數)
缺點:
? 由于boosting的本質而很難并行化
sklearn.ensemble模塊提供了GBRT分類和回歸的方法。
4.1 分類
GradientBoostingClassifier支持二分類和多分類。下面的例子展示了怎樣配置100個決策樹弱學習器的梯度提升分類器。
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)
弱學習器的數量由參數n_estimators控制,每個樹的尺寸由設定樹的深度max_depth和最大葉子節點數max_leaf_nodes控制,learning_rate是0到1的超參數,通過收縮控制過擬合。
note:超過二分類的分類問題需要在每次迭代上歸納n_classes個回歸樹,由此,歸納樹的總數是n_classes*n_estimators.所以,對于大量類別的數據集更推薦使用隨機森林而非GBDT。
4.2 回歸
GradientBoostingRegressor支持不同的損失函數用與回歸,可以通過參數loss來指定,默認損失函數為最小二乘‘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))
下圖展示了在在波士頓房價預測數據集上應用最小二乘誤差和500個基學習器上的GradientBoostingRegressor的結果,每次迭代的訓練誤差儲存在梯度集成模型中的train_score_屬性中,staged_predict方法可以返回每個階段的預測值,利用預測值可以得到每次迭代的測試誤差。這樣的圖可以通過早停來決定n_estimators的數量。
通過feature_importances_屬性顯示特征的重要性。

程序代碼:
params = {'n_estimators': 500, 'max_depth': 4, 'min_samples_split': 2, 'learning_rate': 0.01, 'loss': 'ls'}
clf = ensemble.GradientBoostingRegressor(**params)
clf.fit(X_train, y_train)
mse = mean_squared_error(y_test, clf.predict(X_test))
print("MSE: %.4f" % mse)
# compute test set deviance
test_score = np.zeros((params['n_estimators'],), dtype=np.float64)
for i, y_pred in enumerate(clf.staged_predict(X_test)):
test_score[i] = clf.loss_(y_test, y_pred)
plt.figure(figsize=(12, 6))
plt.subplot(1, 2, 1)
plt.title('Deviance')
plt.plot(np.arange(params['n_estimators']) + 1, clf.train_score_, 'b-', label='Training Set Deviance')
plt.plot(np.arange(params['n_estimators']) + 1, test_score, 'r-', label='Test Set Deviance')
plt.legend(loc='upper right')
plt.xlabel('Boosting Iterations')
plt.ylabel('Deviance')
4.3 控制樹的尺寸
回歸樹基學習器的尺寸定義了梯度提升模型可以捕捉的變量交互的級別。一般來說,深度為h的樹可以捕捉h階的相互作用。這里有兩種方法可以控制單個回歸樹的大小。
如果你指定max_depth=h,那么完全二進制樹的深度為h。由此最多有2h個葉子節點和2h-1個分裂節點。
或者,你可以通過max_leaf_nodes參數指定葉子節點的個數來控制樹的大小。這時,樹將使用最佳優先搜索,其中不純度提高最多的節點將首先擴大。max_leaf_nodes=k有k-1個分裂節點,進行max_leaf_nodes-1次迭代交互。
我們發現max_leaf_nodes=k提供與max_depth=k-1可比較的結果,以犧牲稍高的訓練誤差為代價得到更快的訓練。
4.4 數學公式
GBRT使用下面的加法模型
hm(x)是集成模型中弱學習器的基函數。GBRT使用固定尺寸的決策樹作為弱學習器。決策樹具有即處理混合型數據的能力和對復雜功能建模的能力。
與其他提升算法類似,GBRT使用以前饋階段方式構建添加模型:
在每個階段,給定當前模型Fm-1及Fm-1(xi),選擇決策樹hm(x)來以最小化損失函數L
初始模型F0是問題特定的,對于最小二乘回歸通常選擇目標值的平均值。
梯度提升嘗試通過最速下降解決這個最小化問題:最速下降方向是當前模型Fm-1評估的損失函數的負梯度,損失函數可以為任何可微分的損失函數:
使用行搜索來選擇步長
GBRT分類與回歸的算法僅是具體損失函數的不同。
4.4.1 損失函數
下列的損失函數可被支持用于loss參數中
- 回歸
- 最小二乘'ls':由于較強的計算能力作為回歸問題的自然選擇。目標值的均值作為初始模型
- 最小一乘'lad':回歸的一個健壯損失函數,目標值的中值作為初始模型
- Huber'huber':另一種健壯的損失函數,結合了ls和lad,用alpha控制離群點
- Quantile'quantile'
- 分類
- 二項式偏差'deviance':二分類的負二項式對數概率損失函數,提供了概率估計,對數幾率作為初始模型
- 多項式偏差'deviance'
- 指數損失'exponential':Adaboost相同是損失函數,沒有上面的損失函數健壯,僅用于二分類
4.5 正則化
4.5.1 收縮
提出一種簡單的正則化策略,用v來標定每個弱學習器的貢獻。
參數v也被稱作學習率,因為它標定了梯度下降的步長,可以通過learning_rate設置。
參數learning_rate和參數n_estimators相互影響。learning_rate越小,需要n_estimators更大來保持恒定的訓練誤差。經驗表明,小的學習率可以得到更好的測試誤差。某文獻推薦將學習率設置成一個小的常數(learning_rate<=0.1),然后通過早停來選擇n_estimators。
4.5.2 子采樣
某文獻提出了一種將梯度提升和bagging(自主采樣加平均投票)結合的隨機梯度提升。每一次迭代,基函數采用訓練集的子集subsample來訓練。子集采樣不是自主采樣,通常選擇subsample=0.5
下圖說明了收縮和子采樣對模型擬合的影響。我們可以清楚地看到,收縮比無收縮好,收縮、子采樣可以進一步提高模型的準確性。另一方面,沒有收縮的子采樣,效果并不好。
隨機梯度提升允許通過計算未包含在自主采樣樣本的樣本偏差的改進來估計測試偏差的包外估計。這些存儲在屬性oob_improvement里。oob_improvement[i]如果將第i個階段添加到當前預測中,則對OOB樣本的損失進行估計。包外樣本可用于模型選擇,例如確定最佳迭代次數。OOB估計通常非常悲觀,因此我們建議使用交叉驗證,而只有在交叉驗證太費時時才考慮使用OOB。
4.6 解釋
通過簡單的可視化樹結構,可以輕松的解釋單個決策樹,然后,梯度提升樹包含了幾百個回歸樹,不能有效的可視化,幸運的是,已經有一些技術來總結解釋梯度提升樹。
4.6.1 特征重要性
特征通常不能有助于目標預測,在很多情形下,大多數特征都是不相關的,在解釋模型時,第一個問題通常是,這些重要特征是什么,如何有助于預測目標。