集成學習與隨機森林(三)隨機森林與隨機子空間


隨機森林與隨機子空間

BaggingClassifier類也支持對特征采樣,這種采樣由兩個超參數控制:max_features 與 bootstrap_features,他們的工作方式與max_samples 與 bootstrap一樣,只是他們采樣的是特征。這樣,每個模型將會在一個隨機的輸入特征子集中進行訓練。

這個技巧在處理高維輸入(例如圖片)時非常有用。同時采樣訓練數據以及特征的方法,稱為Random Patches method。而保持所有訓練數據(設置bootstrap=False,max_samples=1.0),但對特征采樣(設置bootstrap_features=True,並且/或 max_features 設置為小於1.0的值)的方法稱為隨機子空間方法(Random Subspaces method)。

對特征采樣可以產生更多的模型多樣性,通過交易一些bias以獲取一些variance的降低。

 

隨機森林

之前介紹過隨機森林,它是決策樹的集成,一般使用bagging 方法(有時候也用pasting)進行訓練,一般 max_samples 設置為訓練集的大小。在構建隨機森林時,除了使用BaggingClassifer類並傳入DecisionTreeClassifier,我們也可以使用RandomForestClassifier類,它是一個更方便的形式,並對決策樹進行了優化(類似,使用RandomForestRegressor類做回歸任務)。下面的代碼使用所有可用的CPU核訓練一個隨機森林分類器,包含500棵決策樹(每棵限制到最多16個節點):

from sklearn.ensemble import RandomForestClassifier

rnd_clf = RandomForestClassifier(n_estimators=500, max_leaf_nodes=16, n_jobs=-1)
rnd_clf.fit(X_train, y_train)

y_pred_rf = rnd_clf.predict(X_test)

RandomForestClassifer 包含DecisionTreeClassifier的所有超參數(用於控制這些樹如何生成),同時也包含所有的BaggingClassifier的超參數(用於控制集成本身)。

隨機森林算法在構造樹時引入了額外的隨機數;相比之前分割節點時搜索最佳特征,它現在會在特征的一組隨機子集中搜索最佳特征。這個算法會產生更好的樹多樣性,也就能(再次)犧牲bias以獲取更低的variance,最終會產生一個整個更好的模型。下面的BaggingClassifier與之前的RandomForestClassifier大致相同:

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

Extra-Trees

在隨機森林中構造一顆樹時,在每個節點僅會考慮特征的一組隨機子集用於分割節點(之前提到過)。我們也有其他辦法讓這些樹更隨機:對每個特征也使用隨機的閾值,而不是搜索最佳可能的閾值。

這種非常隨機的樹構成的森林稱為極隨機樹(Extremely Randomized Trees,或者簡稱Extra-Trees)。同樣,這種技術也是增加了bias來獲取更低的variance。它也讓Extra-Tree 比常規的隨機森林訓練更快,因為在構造樹的過程中,在每個節點為每個特征計算最優分割閾值的操作是決策樹中最耗時的操作之一。

我們可以使用ExtraTreesClassifier類創建一個Extra-Trees分類器。它的API與RandomForestClassifier類類似。同樣,ExtraTreeRegressor類與RandomForestRegressor類有同樣的API。

其實我們很難提前了RandomForestClassifier的表現是否會優於(或差於)ExtraTreesClassifier。一般來說,唯一判斷的辦法就是兩個都嘗試,然后使用交叉驗證(還要使用網格搜索調整超參數)進行對比。

 

特征重要性

隨機森里另外一個非常好的特點是:它使得評估每個特征的相對重要性變得容易。Sk-learn在衡量一個特征的重要性時,會根據決策樹中使用此特征減少不純度的節點的數目,取(森林中所有樹的)平均值。更准確的說,這是一個帶權平均,每個節點的權重等於這個與它關聯的樣本數目。

Sk-learn在訓練結束后會為每個特征自動計算這個分數,然后將結果縮放,以讓所有的重要程度的和等於1。我們可以使用feature_importances_ 變量直接獲取結果。例如,下面的代碼訓練一個RandomForestClassifier,使用iris數據集,並輸出每個特征的重要性。看起來最重要的特征是petal length(44%) 和 width(43%),而sepal length 與 width (分別為3% 和10%)相對更不重要:

from sklearn.datasets import load_iris

iris = load_iris()
rnd_clf = RandomForestClassifier(n_estimators=500, n_jobs=-1)
rnd_clf.fit(iris['data'], iris['target'])

for name, score in zip(iris['feature_names'], rnd_clf.feature_importances_):
    print(name, score)

sepal length (cm)
0.102018800240492 sepal width (cm) 0.02641990617224544 petal length (cm) 0.4387715410940775 petal width (cm) 0.432789752493185

類似,如果我們在MNIST數據集上訓練一個隨機森林分類器,並畫出每個像素點的重要性,則可以得到下圖:

 

 

使用隨機森林可以非常方便的快速了解到什么特征是真正有意義的,特別是我們需要做特征選擇的時候。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM