【Scikit-Learn 中文文檔】集成方法 - 監督學習 - 用戶指南 | ApacheCN

中文文檔: http://sklearn.apachecn.org/cn/stable/modules/ensemble.html

英文文檔: http://sklearn.apachecn.org/en/stable/modules/ensemble.html

官方文檔: http://scikit-learn.org/stable/

GitHub: https://github.com/apachecn/scikit-learn-doc-zh(覺得不錯麻煩給個 Star,我們一直在努力)

貢獻者: https://github.com/apachecn/scikit-learn-doc-zh#貢獻者

關於我們: http://www.apachecn.org/organization/209.html




1.11. 集成方法

注意,在本文中 bagging  boosting 爲了更好的保留原文意圖,不進行翻譯estimator->估計器  base estimator->基估計器

集成方法 的目標是把使用給定學習算法構建的多個基估計器的預測結果結合起來,從而獲得比單個估計器更好的泛化能力/魯棒性。

集成方法通常分爲兩種:

  • 平均方法,該方法的原理是構建多個獨立的估計器,然後取它們的預測結果的平均。一般來說組合之後的估計器是會比單個估計器要好的,因爲它的方差減小了。

    示例: Bagging 方法隨機森林, …

  • 相比之下,在 boosting 方法 中,基估計器是依次構建的,並且每一個基估計器都嘗試去減少組合估計器的偏差。這種方法主要目的是爲了結合多個弱模型,使集成的模型更加強大。

    示例: AdaBoost梯度提升樹, …

1.11.1. Bagging meta-estimator(Bagging 元估計器)

在集成算法中,bagging 方法會在原始訓練集的隨機子集上構建一類黑盒估計器的多個實例,然後把這多個估計器的預測結果結合起來形成最終的預測結果。 該方法通過在構建模型的過程中引入隨機性,來減少基估計器的方差(例如,決策樹)。 在多數情況下,bagging 方法提供了一種非常簡單的方式來對單一模型進行改進,而無需修改背後的算法。 因爲 bagging 方法可以減小過擬合,所以通常最適合在強分類器和複雜模型上使用(例如,完全決策樹,fully developed decision trees),相比之下 boosting 方法則在弱模型上表現更好(例如,淺層決策樹,shallow decision trees)。

bagging 方法有很多種,區別大多數在於抽取訓練子集的方法:

  • 如果抽取的數據集是對於樣例抽取的子集,我們叫做粘貼 (Pasting) [B1999] 。
  • 如果樣例抽取是有放回的,我們稱爲 Bagging [B1996] 。
  • 如果抽取的數據集的隨機子集是對於特徵抽取的隨機子集,我們叫做隨機子空間 (Random Subspaces) [H1998] 。
  • 最後,如果估計器構建在對於樣本和特徵抽取的子集之上時,我們叫做隨機補丁 (Random Patches) [LG2012] 。

在 scikit-learn 中,bagging 方法使用統一的 BaggingClassifier 元估計器(或者 BaggingRegressor ),輸入的參數和隨機子集抽取策略由用戶指定。max_samples 和 max_features 控制着子集的大小(對於樣例和特徵), bootstrap 和 bootstrap_features 控制着樣例和特徵的抽取是有放回還是無放回的。 當使用樣本子集時,通過設置 oob_score=True ,可以使用袋外(out-of-bag)樣本來評估泛化精度。下面的代碼片段說明了如何構造一個 KNeighborsClassifier 估計器的 bagging 集成實例,每一個基估計器都建立在 50% 的樣本隨機子集和 50% 的特徵隨機子集上。

>>>
>>> from sklearn.ensemble import BaggingClassifier
>>> from sklearn.neighbors import KNeighborsClassifier
>>> bagging = BaggingClassifier(KNeighborsClassifier(),
...                             max_samples=0.5, max_features=0.5)

參考文獻

[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.

1.11.2. 由隨機樹組成的森林

sklearn.ensemble 模塊包含兩個基於 隨機決策樹 的平均算法: RandomForest 算法和 Extra-Trees 算法。 這兩種算法都是專門爲樹而設計的擾動和組合技術(perturb-and-combine techniques) [B1998] 。 這意味着通過在分類器構造過程中引入隨機性來創建一組不同的分類器。集成分類器的預測結果是單個分類器預測結果的平均值。

與其他分類器一樣,森林分類器必須擬合(fitted)兩個數組: 保存訓練樣本的數組(或稀疏或稠密的)X,大小爲 [n_samples, n_features],和 保存訓練樣本目標值(類標籤)的數組 Y,大小爲 [n_samples]:

>>>
>>> from sklearn.ensemble import RandomForestClassifier
>>> X = [[0, 0], [1, 1]]
>>> Y = [0, 1]
>>> clf = RandomForestClassifier(n_estimators=10)
>>> clf = clf.fit(X, Y)

同 決策樹 一樣,隨機森林算法(forests of trees)也能夠通過擴展來解決 多輸出問題 (如果 Y 的大小是 [n_samples, n_outputs]).

1.11.2.1. 隨機森林

在隨機森林中(參見 ExtraTreesClassifier 和 ExtraTreesRegressor 類), 集成模型中的每棵樹構建時的樣本都是由訓練集經過有放回抽樣得來的(例如,自助採樣法-bootstrap sample,這裏採用西瓜書中的譯法)。 另外,在構建樹的過程中進行結點分割時,選擇的分割點不再是所有特徵中最佳分割點,而是特徵的一個隨機子集中的最佳分割點。 由於這種隨機性,森林的偏差通常會有略微的增大(相對於單個非隨機樹的偏差),但是由於取了平均,其方差也會減小,通常能夠補償偏差的增加,從而產生一個總體上更好的模型。

與原始文獻 [B2001] 不同的是,scikit-learn 的實現是取每個分類器預測概率的平均,而不是讓每個分類器對類別進行投票。

1.11.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()                             
0.97...
>>>
>>> clf = RandomForestClassifier(n_estimators=10, max_depth=None,
...     min_samples_split=2, random_state=0)
>>> scores = cross_val_score(clf, X, y)
>>> 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)
>>> scores.mean() > 0.999
True
../_images/sphx_glr_plot_forest_iris_0011.png

1.11.2.3. 參數

使用這些方法時要調整的參數主要是 n_estimators 和 max_features。 前者(n_estimators)是森林裏樹的數量,通常數量越大,效果越好,但是計算時間也會隨之增加。 此外要注意,當樹的數量超過一個臨界值之後,算法的效果並不會很顯著地變好。 後者(max_features)是分割節點時考慮的特徵的隨機子集的大小。 這個值越低,方差減小得越多,但是偏差的增大也越多。 根據經驗,迴歸問題中使用 max_features = n_features, 分類問題使用 max_features = sqrt(n_features (其中 n_features 是特徵的個數)是比較好的默認值。 max_depth = None  min_samples_split = 2 結合通常會有不錯的效果(即生成完全的樹)。 請記住,這些(默認)值通常不是最佳的,同時還可能消耗大量的內存,最佳參數值應由交叉驗證獲得。 另外,請注意,在隨機林中,默認使用自助採樣法(bootstrap = True), 然而 extra-trees 的默認策略是使用整個數據集(bootstrap = False)。 當使用自助採樣法方法抽樣時,泛化精度是可以通過剩餘的或者袋外的樣本來估算的,設置 oob_score = True 即可實現。

提示:

默認參數下模型複雜度是:O(M*N*log(N)), 其中 M 是樹的數目,N 是樣本數。 可以通過設置以下參數來降低模型複雜度:min_samples_split, min_samples_leaf, max_leaf_nodes`` 和 ``max_depth.

1.11.2.4. 並行化

最後,這個模塊還支持樹的並行構建和預測結果的並行計算,這可以通過 n_jobs 參數實現。 如果設置 n_jobs = k,則計算被劃分爲 k 個作業,並運行在機器的 k 個核上。 如果設置 n_jobs = -1,則使用機器的所有核。 注意由於進程間通信具有一定的開銷,這裏的提速並不是線性的(即,使用 k 個作業不會快k倍)。 當然,在建立大量的樹,或者構建單個樹需要相當長的時間(例如,在大數據集上)時,(通過並行化)仍然可以實現顯著的加速。

參考文獻

[B2001]
  1. Breiman, “Random Forests”, Machine Learning, 45(1), 5-32, 2001.
[B1998]
  1. Breiman, “Arcing Classifiers”, Annals of Statistics 1998.
  • P. Geurts, D. Ernst., and L. Wehenkel, “Extremely randomized trees”, Machine Learning, 63(1), 3-42, 2006.

1.11.2.5. 特徵重要性評估

特徵對目標變量預測的相對重要性可以通過(樹中的決策節點的)特徵使用的相對順序(即深度)來進行評估。 決策樹頂部使用的特徵對更大一部分輸入樣本的最終預測決策做出貢獻;因此,可以使用接受每個特徵對最終預測的貢獻的樣本比例來評估該 特徵的相對重要性 。

通過對多個隨機樹中的 預期貢獻率 (expected activity rates)**取平均**,可以減少這種估計的 方差 ,並將其用於特徵選擇。

下面的例子展示了一個面部識別任務中每個像素的相對重要性,其中重要性由顏色(的深淺)來表示,使用的模型是ExtraTreesClassifier。

modules/../auto_examples/ensemble/images/sphx_glr_plot_forest_importances_faces_001.png

實際上,在擬合模型時這些估計值存儲在 feature_importances_ 屬性中。 這是一個大小爲 (n_features,) 的數組,其每個元素值爲正,並且總和爲 1.0。一個元素的值越高,其對應的特徵對預測函數的貢獻越大。

1.11.2.6. 完全隨機樹嵌入

RandomTreesEmbedding 實現了一個無監督的數據轉換。 通過由完全隨機樹構成的森林,RandomTreesEmbedding 使用數據最終歸屬的葉子節點的索引值(編號)對數據進行編碼。 該索引以 one-of-K 方式編碼,最終形成一個高維的稀疏二進制編碼。 這種編碼可以被非常高效地計算出來,並且可以作爲其他學習任務的基礎。 編碼的大小和稀疏度可以通過選擇樹的數量和每棵樹的最大深度來影響。對於集成中的每棵樹,編碼包含一個實體(校對者注:這裏真的沒搞懂)。 編碼的大小(維度)最多爲 n_estimators * 2 ** max_depth,即森林中的葉子節點的最大數。

由於相鄰數據點更可能位於樹的同一葉子中,該變換可以作爲一種隱式地非參數密度估計。

示例:

See also

 

流形學習 方法也可以用於特徵空間的非線性表示, 以及降維.

1.11.3. AdaBoost

模型 sklearn.ensemble 包含了流行的提升算法 AdaBoost, 這個算法是由 Freund and Schapire 在 1995 年提出來的 [FS1995].

AdaBoost 的核心思想是用反覆修改的數據(校對者注:主要是修正數據的權重)來學習一系列的弱學習器(一個弱學習器模型僅僅比隨機猜測好一點, 比如一個簡單的決策樹),由這些弱學習器的預測結果通過加權投票(或加權求和)的方式組合, 得到我們最終的預測結果。在每一次所謂的提升(boosting)迭代中,數據的修改由應用於每一個訓練樣本的(新) 的權重 w_1w_2, …, w_N組成(校對者注:即修改每一個訓練樣本應用於新一輪學習器的權重)。  初始化時,將所有弱學習器的權重都設置爲 w_i = 1/N,因此第一次迭代僅僅是通過原始數據訓練出一個弱學習器。在接下來的  連續迭代中,樣本的權重逐個地被修改,學習算法也因此要重新應用這些已經修改的權重。在給定的一個迭代中, 那些在上一輪迭代中被預測爲錯誤結果的樣本的權重將會被增加,而那些被預測爲正確結果的樣本的權 重將會被降低。隨着迭代次數的增加,那些難以預測的樣例的影響將會越來越大,每一個隨後的弱學習器都將 會被強迫更加關注那些在之前被錯誤預測的樣例 [HTF].

../_images/sphx_glr_plot_adaboost_hastie_10_2_0011.png

AdaBoost 既可以用在分類問題也可以用在迴歸問題中:

1.11.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()                             
0.9...

弱學習器的數量由參數 n_estimators 來控制。 learning_rate 參數用來控制每個弱學習器對 最終的結果的貢獻程度(校對者注:其實應該就是控制權重修改的速率,這裏不太記得了,不確定)。 弱學習器默認使用決策樹。不同的弱學習器可以通過參數 base_estimator``來指定。 獲取一個好的預測結果主要需要調整的參數是 ``n_estimators 和 base_estimator 的複雜度 (例如:對於弱學習器爲決策樹的情況,樹的深度 max_depth 或葉子節點的最小樣本數 min_samples_leaf 等都是控制樹的複雜度的參數)

示例:

參考

[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]
  1. Drucker. “Improving Regressors using Boosting Techniques”, 1997.
[HTF] T. Hastie, R. Tibshirani and J. Friedman, “Elements of Statistical Learning Ed. 2”, Springer, 2009.

1.11.4. 梯度樹提升(Gradient Tree Boosting)

Gradient Tree Boosting 或梯度提升迴歸樹(GBRT)是對於任意的可微損失函數的提升算法的泛化。 GBRT 是一個準確高效的現有程序, 它既能用於分類問題也可以用於迴歸問題。梯度樹提升模型被應用到各種領域,包括網頁搜索排名和生態領域.

GBRT 的優點:

  • 對混合型數據的自然處理(異構特徵)
  • 強大的預測能力
  • 在輸出空間中對異常點的魯棒性(通過具有魯棒性的損失函數實現)

GBRT 的缺點:

  • 可擴展性差(校對者注:此處的可擴展性特指在更大規模的數據集/複雜度更高的模型上使用的能力,而非我們通常說的功能的擴展性;GBRT 支持自定義的損失函數,從這個角度看它的擴展性還是很強的!)。由於提升算法的有序性(也就是說下一步的結果依賴於上一步),因此很難做並行.

模塊 sklearn.ensemble 通過梯度提升樹提供了分類和迴歸的方法.

1.11.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)                 
0.913...

弱學習器(例如:迴歸樹)的數量由參數 n_estimators 來控制;每個樹的大小可以通過由參數 max_depth 設置樹的深度,或者由參數 max_leaf_nodes 設置葉子節點數目來控制。 learning_rate 是一個在 (0,1] 之間的超參數,這個參數通過 shrinkage(縮減步長) 來控制過擬合。

Note

 

超過兩類的分類問題需要在每一次迭代時推導 n_classes 個迴歸樹。因此,所有的需要推導的樹數量等 於n_classes * n_estimators 。對於擁有大量類別的數據集我們強烈推薦使用 RandomForestClassifier 來代替GradientBoostingClassifier .

1.11.4.2. 迴歸

對於迴歸問題 GradientBoostingRegressor 支持一系列 different loss functions , 這些損失函數可以通過參數 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))    
5.00...

下圖展示了應用損失函數爲最小二乘損失,基學習器個數爲 500 的 GradientBoostingRegressor 來處理sklearn.datasets.load_boston 數據集的結果。左圖表示每一次迭代的訓練誤差和測試誤差。每一次迭 代的訓練誤差保存在提升樹模型的 train_score_ 屬性中,每一次迭代的測試誤差能夠通過 staged_predict 方法獲取,該方法返回一個生成器,用來產生每一 個迭代的預測結果。類似下面這樣的圖表,可以用於決定最優的樹的數量,從而進行提前停止。右圖表示每個特徵的重要性,它 可以通過 feature_importances_ 屬性來獲取.

../_images/sphx_glr_plot_gradient_boosting_regression_0011.png

1.11.4.3. 擬合額外的弱學習器

GradientBoostingRegressor 和 :class:`GradientBoostingClassifier`都支持設置參數

warm_start=True,這樣設置允許我們在已經擬合的模型上面添加更多的估計器.

>>>
>>> _ = 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...

1.11.4.4. 控制樹的大小

迴歸樹基學習器的大小定義了可以被梯度提升模型捕捉到的變量(即特徵)相互作用(即多個特徵共同對預測產生影響)的程度。 通常一棵深度爲 h 的樹能捕獲到秩爲 h 的相互作用。這裏有兩種控制單棵迴歸樹大小的方法。

如果你指定 max_depth=h ,那麼將會一個深度爲 h 的完全二叉樹。這棵樹將會有(至多) 2**h 個 葉子節點和 2**h - 1 個切分節點。

另外,你能通過參數 max_leaf_nodes 指定葉子節點的數量來控制樹的大小。在這種情況下,樹將會 使用最優優先搜索來生成,這種搜索方式是通過每次選取對不純度提升最大的節點來展開。一棵樹的 max_leaf_nodes=k 擁有 k - 1 個切分節點,因此可以模擬秩最高達到 max_leaf_nodes - 1 的相互作用(即 max_leaf_nodes - 1 個特徵共同決定預測值)。

我們發現 max_leaf_nodes=k 可以給出與 max_depth=k-1 品質相當的結果,但是其訓練速度明顯更快,同時 也會多一點訓練誤差作爲代價。參數 max_leaf_nodes 對應於文章 [F2001] 中梯度提升章節中的變量 J, 同時與 R 語言的 gbm 包的參數 interaction.depth 相關,兩者間的關係是 max_leaf_nodes == interaction.depth + 1

1.11.4.5. 數學公式 (Mathematical formulation)

GBRT 可以認爲是以下形式的可加模型:

F(x) = \sum_{m=1}^{M} \gamma_m h_m(x)

其中 h_m(x) 是基本函數,在提升算法場景中它通常被稱作 weak learners . 梯度樹提升算法(Gradient Tree Boosting)使用固定大小 的 decision trees 作爲弱分類器,決策樹本身擁有的一些特性使它能夠在提升過程中變得有價值, 例如,處理混合類型數據以及構建具有複雜功能模型的能力.

與其他提升算法類似,GBRT 利用前向分步算法思想構建加法模型:

F_m(x) = F_{m-1}(x) + \gamma_m h_m(x)

在每一個階段中,在當前模型 F_{m-1} 和擬合函數 F_{m-1}(x_i) 給定的情況下,選擇合適的決策樹函數 h_m(x) ,從而最小化損失函數 L .

F_m(x) = F_{m-1}(x) + \arg\min_{h} \sum_{i=1}^{n} L(y_i,F_{m-1}(x_i) - h(x))

初始模型 F_{0} 是問題的具體,對於最小二乘迴歸,通常選擇目標值的平均值.

Note

 

初始化模型也能夠通過 init 參數來指定,但被傳對象需要實現 fit 和 predict 函數.

梯度提升(Gradient Boosting)嘗試通過最速下降法以數字方式解決這個最小化問題.最速下降方向是在當前模型 F_{m-1} 下評估的 損失函數的負梯度,其中模型 F_{m-1} 可以計算任何可微損失函數:

F_m(x) = F_{m-1}(x) + \gamma_m \sum_{i=1}^{n} \nabla_F L(y_i,F_{m-1}(x_i))

其中步長:math:gamma_m 通過如下方式線性搜索獲得:

\gamma_m = \arg\min_{\gamma} \sum_{i=1}^{n} L(y_i, F_{m-1}(x_i)- \gamma \frac{\partial L(y_i, F_{m-1}(x_i))}{\partial F_{m-1}(x_i)})

該算法處理分類和迴歸問題不同之處在於具體損失函數的使用.

1.11.4.5.1. 損失函數 (Loss Functions)

以下是目前支持的損失函數,具體損失函數可以通過參數 loss 指定:

  • 迴歸 (Regression)
    • Least squares ('ls'): 由於其優越的計算性能,該損失函數成爲迴歸算法中的自然選擇。 初始模型通過目標值的均值給出.
    • Least absolute deviation ('lad'): 迴歸中具有魯棒性的損失函數,初始模型通過目 標值的中值給出.
    • Huber ('huber'): 迴歸中另一個具有魯棒性的損失函數,它是最小二乘和最小絕對偏差兩者的結合. 其利用 alpha 來控制模型對於異常點的敏感度(詳細介紹請參考 [F2001]).
    • Quantile ('quantile'): 分位數迴歸損失函數.用 0 < alpha < 1 來指定分位數這個損 失函數可以用來產生預測間隔.(詳見 Prediction Intervals for Gradient Boosting Regression ).
  • 分類 (Classification)
    • Binomial deviance ('deviance'): 對於二分類問題(提供概率估計)即負的二項log似然 損失函數.模型以log的比值比來初始化.
    • Multinomial deviance ('deviance'): 對於多分類問題的負的多項log似然損失函數具有 n_classes 個互斥的類.提供概率估計. 初始模型由每個類的先驗概率給出.在每一次迭代中 n_classes 迴歸樹被構建,這使得 GBRT 在處理多類別數據集時相當低效.
    • Exponential loss ('exponential'): 與 AdaBoostClassifier 具有相同的損失 函數.與 'deviance' 相比,對具有錯誤標記的樣本的魯棒性較差,僅用於在二分類問題.

1.11.4.6. 正則化 (Regularization)

1.11.4.6.1. 收縮率 (Shrinkage)

[F2001] 提出一個簡單的正則化策略,通過一個因子 \nu 來衡量每個弱分類器對於最終結果的貢獻:

F_m(x) = F_{m-1}(x) + \nu \gamma_m h_m(x)

參數 \nu 由於它縮小了梯度下降的步長, 因此也叫作 learning rate ,它可以通過 learning_rate 參數來設置.

在擬合一定數量的弱分類器時,參數 learning_rate 和參數 n_estimators 之間有很強的制約關係. 較小的``learning_rate`` 需要大量的弱分類器才能保證訓練誤差的不變.經驗表明數值較小的 learning_rate 將會得到更好的測試誤差. [HTF2009] 推薦把 learning_rate 設置爲一個較小的常數 (例如: learning_rate <= 0.1 )同時通過提前停止策略來選擇合適的 n_estimators . 有關 learning_rate 和 n_estimators 更詳細的討論可以參考 [R2007].

1.11.4.6.2. 子採樣 (Subsampling)

[F1999] 提出了隨機梯度提升,這種方法將梯度提升(gradient boosting)和bootstrap averaging(bagging)相結合.在每次迭代 中,基分類器是通過抽取所有可利用訓練集中一小部分的 subsample 訓練得到的.子樣本採用無放回的方式採 樣. subsample 參數的值一般設置爲0.5.

下圖表明瞭收縮率和子採樣對於模型擬合好壞的影響.我們可以明顯看到收縮率在無收縮的情況下擁有更好的表現.而將子採 樣和收縮率相結合能進一步的提高模型的準確率.相反,使用子採樣而不使用縮減的結果十分糟糕.

../_images/sphx_glr_plot_gradient_boosting_regularization_0011.png

另一個減少方差的策略是特徵子採樣,這種方法類似於 RandomForestClassifier 中的隨機分割. 子採樣的特徵數可以通過參數 max_features 來控制.

Note

 

採用一個較小的 max_features 值能大大縮減模型的訓練時間.

隨機梯度提升允許計算測試偏差的袋外估計(Out-of-bag),方法是通過計算那些不在自助採樣之內的樣本偏差的改進.這個改進保存在屬性 oob_improvement_ 中. oob_improvement_[i] 如果將 第i步添加到當前預測中,則可以改善OOB樣本的損失.袋外估計可以使用在模型選擇中,例如決定最優迭代次 數.OOB估計通常都很悲觀,因此我們推薦使用交叉驗證來代替它,而當交叉驗證太耗時時我們就只能使用OOB了.

1.11.4.7. 解釋性 (Interpretation)

通過簡單地可視化樹結構可以很容易地解釋單個決策樹,然而對於梯度提升模型來說,一般擁有數百棵/種迴歸樹,因此通過目視檢查每一棵樹 是很難解釋的.幸運的是,有很多關於總結和解釋梯度提升模型的技術已經被提出.

1.11.4.7.1. 特徵重要性 (Feature importance)

通常情況下每個特徵對於預測目標的貢獻是不同的.在很多情形下大多數特徵實際上是無關的.當解釋一個模型時,第一 個問題通常是:這些重要的特徵是什麼?他們如何在預測目標方面做出積極的響應?

單個決策樹本質上是通過選擇最佳切分點來進行特徵選擇.這個信息可以用來檢測每個特徵的重要性.基本思想是:在樹 的分割點中使用的特徵越頻繁,特徵越重要。 這個重要的概念可以通過簡單地平均每棵樹的特徵重要性來擴展到 決策樹集合.(詳見 特徵重要性評估 ).

對於一個訓練好的梯度提升模型,其特徵重要性分數可以通過屬性 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.11,  0.1 ,  0.11,  ...

示例 (Examples):

1.11.4.7.2. 部分依賴 (Partial dependence)

部分依賴圖(PDP)展示了目標響應和一系列目標特徵的依賴關係,同時邊緣化了其他所有特徵值(候選特徵). 直覺上,我們可以將部分依賴解釋爲作爲目標特徵函數 [2] 的預期目標響應 [1] .

由於人類感知能力的限制,目標特徵的設置必須小一點(通常是1到2),因此目標特徵通常在最重要的特徵中選擇.

下圖展示了加州住房數據集的四個單向和一個雙向部分依賴圖:

modules/../auto_examples/ensemble/images/sphx_glr_plot_partial_dependence_001.png

單向 PDPs 告訴我們目標響應和目標特徵的相互影響(例如:線性或者非線性).上圖中的左上圖展示了一個地區中等收入對 中等房價的影響.我們可以清楚的看到兩者之間是線性相關的.

具有兩個目標特徵的 PDPs 顯示這兩個特徵之間的相互影響.例如:上圖中兩個變量的 PDP 展示了房價中位數與房屋年齡和 每戶平均入住人數之間的依賴關係.我們能清楚的看到這兩個特徵之間的影響:對於每戶入住均值而言,當其值大於 2 時, 房價與房屋年齡幾乎是相對獨立的,而其值小於2的時,房價對房屋年齡的依賴性就會很強.

模型 partial_dependence 提供了一個便捷的函數 plot_partial_dependence 來產生單向或雙向部分依 賴圖.在下圖的例子中我們展示如何創建一個部分依賴的網格圖:特徵值介於 0 和 1 的兩個單向依賴PDPs和一 個在兩個特徵間的雙向 PDPs:

>>>
>>> from sklearn.datasets import make_hastie_10_2
>>> from sklearn.ensemble import GradientBoostingClassifier
>>> from sklearn.ensemble.partial_dependence import plot_partial_dependence

>>> 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)
>>> features = [0, 1, (0, 1)]
>>> fig, axs = plot_partial_dependence(clf, X, features) 

對於多類別的模型,你需要通過 label 參數設置類別標籤來創建 PDPs:

>>>
>>> from sklearn.datasets import load_iris
>>> iris = load_iris()
>>> mc_clf = GradientBoostingClassifier(n_estimators=10,
...     max_depth=1).fit(iris.data, iris.target)
>>> features = [3, 2, (3, 2)]
>>> fig, axs = plot_partial_dependence(mc_clf, X, features, label=0) 

如果你需要部分依賴函數的原始值而不是圖,你可以調用 partial_dependence 函數:

>>>
>>> from sklearn.ensemble.partial_dependence import partial_dependence

>>> pdp, axes = partial_dependence(clf, [0], X=X)
>>> pdp  
array([[ 2.46643157,  2.46643157, ...
>>> axes  
[array([-1.62497054, -1.59201391, ...

該函數允許通過 grid 參數指定應該評估部分依賴函數的的目標特徵值或通過 X 參數設置從訓練數據中自動創建 grid 的便利模式.如果 X 被給出,函數返回的 axes 爲每個目標特徵提供軸.

對於 grid 中的每一個’目標’特徵值,部分依賴函數需要邊緣化一棵樹中所有候選特徵的可能值的預測. 在決策樹中,這個函數可以在不參考訓練數據的情況下被高效的評估,對於每一網格點執行加權遍歷: 如果切分點包含’目標’特徵,遍歷其相關的左分支或相關的右分支,否則就遍歷兩個分支.每一個分支將被通過進入該分支的訓練樣本的佔比加權, 最後,部分依賴通過所有訪問的葉節點的權重的平均值給出.組合樹(tree ensembles)的整體結果,需要對每棵樹的結果再次平均得到.

註解 (Footnotes)

[1] For classification with loss='deviance' the target response is logit(p).
[2] More precisely its the expectation of the target response after accounting for the initial model; partial dependence plots do not include the init model.

示例 (Examples):

參考 (References)

[F2001] (123) J. Friedman, “Greedy Function Approximation: A Gradient Boosting Machine”, The Annals of Statistics, Vol. 29, No. 5, 2001.
[F1999]
  1. Friedman, “Stochastic Gradient Boosting”, 1999
[HTF2009]
  1. Hastie, R. Tibshirani and J. Friedman, “Elements of Statistical Learning Ed. 2”, Springer, 2009.
[R2007]
  1. Ridgeway, “Generalized Boosted Models: A guide to the gbm package”, 2007

1.11.5. 投票分類器 (Voting Classifier)

VotingClassifier (投票分類器)的原理是結合了多個不同的機器學習分類器,並且採用多數表決(majority vote)或者平均預測概率(軟投票)的方式來預測分類標籤. 這樣的分類器可以用於一組同樣表現良好的模型,以便平衡它們各自的弱點.

1.11.5.1. 多數類標籤 (又稱爲,多數/硬投票)

在多數投票中,特定樣本的預測類別標籤是表示單獨分類器預測的類別標籤中票數佔據多數(模式)的類別標籤。

例如, 如果給定樣本的預測是

  • classifier 1 -> class 1
  • classifier 2 -> class 1
  • classifier 3 -> class 2

類別 1 佔據多數,通過 voting='hard' 參數設置投票分類器爲多數表決方式,會得到該樣本的預測結果是類別 1.

在平局的情況下,投票分類器(VotingClassifier)將根據升序排序順序選擇類標籤。 例如,場景如下:

  • classifier 1 -> class 2
  • classifier 2 -> class 1

這種情況下,class 1 將會被指定爲該樣本的類標籤.

1.11.5.1.1. 用法 (Usage)

以下示例顯示如何擬合多數規則分類器:

>>>
>>> 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(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, cv=5, scoring='accuracy')
...     print("Accuracy: %0.2f (+/- %0.2f) [%s]" % (scores.mean(), scores.std(), label))
Accuracy: 0.90 (+/- 0.05) [Logistic Regression]
Accuracy: 0.93 (+/- 0.05) [Random Forest]
Accuracy: 0.91 (+/- 0.04) [naive Bayes]
Accuracy: 0.95 (+/- 0.05) [Ensemble]

1.11.5.2. 加權平均概率 (軟投票)

與大多數投票(硬投票)相比,軟投票將類別標籤返回爲預測概率之和的 argmax.

具體的權重可以通過權重參數 weights 分配給每個分類器.當提供權重參數 weights 時,收集每個分類器的預測分類概率, 乘以分類器權重並取平均值.然後從具有最高平均概率的類別標籤導出最終類別標籤.

爲了用一個簡單的例子來說明這一點,假設我們有3個分類器和一個3類分類問題,我們給所有分類器賦予相等的權重:w1 = 1,w2 = 1,w3 = 1.

樣本的加權平均概率計算如下:

分類器 類別 1 類別 2 類別 3
分類器 1 w1 * 0.2 w1 * 0.5 w1 * 0.3
分類器 2 w2 * 0.6 w2 * 0.3 w2 * 0.1
分類器 3 w3 * 0.3 w3 * 0.4 w3 * 0.3
加權平均的結果 0.37 0.4 0.23

這裏可以看出,預測的類標籤是 2,因爲它具有最大的平均概率.

下邊的示例程序說明了當軟投票分類器(soft VotingClassifier)是基於線性支持向量機(linear SVM)、決策樹(Decision Tree)、K近鄰(K-nearest )分類器時,決策域可能如何變化:

>>>
>>> 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)
../_images/sphx_glr_plot_voting_decision_regions_0011.png

1.11.5.3. 投票分類器(VotingClassifier )在網格搜索(GridSearch)應用

爲了調整每個估計器的超參數,`VotingClassifier` 也可以和 GridSearch 一起使用:

>>>
>>> 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)

1.11.5.3.1. 用法 (Usage)

爲了基於預測的類別概率預測類別標籤(投票分類器中的 scikit-learn estimators 必須支持 predict_proba 方法):

>>>
>>> eclf = VotingClassifier(estimators=[('lr', clf1), ('rf', clf2), ('gnb', clf3)], voting='soft')

可選地,也可以爲單個分類器提供權重:

>>>
>>> eclf = VotingClassifier(estimators=[('lr', clf1), ('rf', clf2), ('gnb', clf3)], voting='soft', weights=[2,5,1])



中文文檔: http://sklearn.apachecn.org/cn/stable/modules/ensemble.html

英文文檔: http://sklearn.apachecn.org/en/stable/modules/ensemble.html

官方文檔: http://scikit-learn.org/stable/

GitHub: https://github.com/apachecn/scikit-learn-doc-zh(覺得不錯麻煩給個 Star,我們一直在努力)

貢獻者: https://github.com/apachecn/scikit-learn-doc-zh#貢獻者

關於我們: http://www.apachecn.org/organization/209.html

有興趣的們也可以和我們一起來維護,持續更新中 。。。

機器學習交流羣: 629470233

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章