隨機森林 RandomForest
1、集成學習
集成學習(ensemble learning)可以說是現在非常火爆的機器學習方法了。它本身不是一個單獨的機器學習算法,而是通過構建並結合多個機器學習器來完成學習任務。也就是我們常說的“博採衆長”。集成學習可以用於分類問題集成,迴歸問題集成,特徵選取集成,異常點檢測集成等等。在現在的各種算法競賽中,隨機森林,梯度提升樹(GBDT),Xgboost等集成
算法的身影也隨處可見。
更多關於集成學習的概念和公式推導這裏不過多闡釋,有興趣可看這篇博客劉建平集成學習博客
1.1 Sklearn中的集成算法模塊
類 | 類功能 |
---|---|
ensemble.AdaBoostClassifier |
AdaBoost分類 |
ensemble.AdaBoostRegressor |
Adaboost迴歸 |
ensemble.BaggingClassifier |
裝袋分類器 |
ensemble.BaggingRegressor |
裝袋迴歸器 |
ensemble.ExtraTreesClassifier |
Extra-trees分類(超樹,極端隨機樹) |
ensemble.ExtraTreesRegressor |
Extra-trees迴歸 |
ensemble.GradientBoostingClassifier |
梯度提升分類 |
ensemble.GradientBoostingRegressor |
梯度提升迴歸 |
ensemble.IsolationForest |
隔離森林(用於檢測異常值) |
ensemble.RandomForestClassifier |
隨機森林分類 |
ensemble.RandomForestRegressor |
隨機森林迴歸 |
ensemble.RandomTreesEmbedding |
完全隨機樹的集成 |
ensemble.VotingClassifier |
用於不合適估算器的軟投票/多數規則分類器(如集成SVM) |
ensemble.HistGradientBoostingRegressor |
基於直方圖的梯度增強迴歸樹 |
ensemble.HistGradientBoostingClassifier |
基於直方圖的梯度增強分類樹 |
2、隨機森林 RandomForest
2.1 優缺點分析
RF的主要優點有:
- 訓練可以高度並行化,對於大數據時代的大樣本訓練速度有優勢。個人覺得這是的最主要的優點。
- 由於可以隨機選擇決策樹節點劃分特徵,這樣在樣本特徵維度很高的時候,仍然能高效的訓練模型。
- 在訓練後,可以給出各個特徵對於輸出的重要性。
- 由於採用了隨機採樣,訓練出的模型的方差小,泛化能力強。
- 對於Boosting系列的Adaboost和GBDT, RF實現比較簡單。
- 對部分特徵缺失不敏感。
RF的主要缺點有:
- 某些噪音比較大的樣本集上,RF模型容易陷入過擬合。
- 取值劃分比較多的特徵容易對RF的決策產生更大的影響,從而影響擬合的模型的效果。
2.2 分類/迴歸
2.2.1 RandomForestClassifier
sklearn.ensemble.RandomForestClassifier(n_estimators=100,
criterion='gini',
max_depth=None,
min_samples_split=2,
min_samples_leaf=1,
min_weight_fraction_leaf=0.0,
max_features='auto',
max_leaf_nodes=None,
min_impurity_decrease=0.0,
min_impurity_split=None,
bootstrap=True,
oob_score=False,
n_jobs=None,
random_state=None,
verbose=0,
warm_start=False,
class_weight=None,
ccp_alpha=0.0,
max_samples=None
)
2.2.2RandomForestRegressor
sklearn.ensemble.RandomForestRegressor(n_estimators=100,
criterion='mse',
max_depth=None,
min_samples_split=2,
min_samples_leaf=1,
min_weight_fraction_leaf=0.0,
max_features='auto',
max_leaf_nodes=None,
min_impurity_decrease=0.0,
min_impurity_split=None,
bootstrap=True,
oob_score=False,
n_jobs=None,
random_state=None,
verbose=0,
warm_start=False,
ccp_alpha=0.0,
max_samples=None
)
2.2.3 重要參數解釋
參數 | 含義 |
---|---|
n_estimators |
基學習器的數量,n_estimators越大效果往往越好。到一定的數量再增大模型提升會很小,需要的計算量和內存也越大時間越長。 |
criterion |
樹做劃分時對特徵的評價標準。分類RF默認是基尼係數(“gini”),另一個標準是信息增益(“entropy”)。迴歸RF默認是mse,另一個是絕對值差mae。 |
max_features |
RF劃分時考慮的最大特徵數。默認值爲總特徵個數開平方取整,如果特徵數非常多,我們可以靈活使用剛纔描述的其他取值來控制劃分時考慮的最大特徵數,以控制決策樹的生成時間。 |
max_depth |
決策樹最大深度。一般來說數據少或者特徵少的時候可以不管這個值。如果模型樣本量多,特徵也多的情況下,推薦限制這個最大深度,具體的取值取決於數據的分佈。 |
min_samples_split |
內部節點再劃分所需最小樣本數。這個值限制了子樹繼續劃分的條件,如果某節點的樣本數少於該值,則不會繼續再嘗試選擇最優特徵來進行劃分。 默認是2.如果樣本量不大,不需要管這個值。如果樣本量數量級非常大,則推薦增大這個值。 |
min_samples_leaf |
葉子節點最少樣本數。這個值限制了葉子節點最少的樣本數,如果某葉子節點數目小於樣本數,則會和兄弟節點一起被剪枝。 默認是1,可以輸入最少的樣本數的整數,或者最少樣本數佔樣本總數的百分比。如果樣本量數量級非常大,則推薦增大這個值。 |
min_weight_fraction_leaf |
葉子節點最小的樣本權重。這個值限制了葉子節點所有樣本權重和的最小值,如果小於這個值,則會和兄弟節點一起被剪枝。 默認是0,就是不考慮權重問題。一般來說,如果我們有較多樣本有缺失值,或者分類樹樣本的分佈類別偏差很大,就會引入樣本權重,這時我們就要注意這個值了。 |
max_leaf_nodes |
通過限制最大葉子節點數,可以防止過擬合,默認是"None”,即不限制最大的葉子節點數。如果加了限制,算法會建立在最大葉子節點數內最優的決策樹。如果特徵不多,可以不考慮這個值,但是如果特徵分成多的話,可以加以限制,具體的值可以通過交叉驗證得到。 |
min_impurity_split |
節點劃分最小不純度。這個值限制了決策樹的增長,如果某節點的不純度(基於基尼係數,均方差)小於這個閾值,則該節點不再生成子節點。即爲葉子節點 。一般不推薦改動默認值1e-7 |
oob_score |
即是否採用袋外樣本來評估模型的好壞。默認識False。個人推薦設置爲True,因爲袋外分數反應了一個模型擬合後的泛化能力。 |
bootstrap |
默認True,代表採用這種有放回的隨機抽樣技術。通常,這個參數不會被我們設置爲False。 |
2.2.4 重要屬性
屬性 | 含義 |
---|---|
estimators_ |
輸出包含單個決策樹分類器的列表,是所有訓練過的基分類器的集合 |
classes_ |
輸出一個數組(array)或者一個數組的列表(list), 結構爲標籤的數目(n classes)輸出所有標籤 |
feature_ importances_ |
輸出一個數組,結構爲特徵的數目(n features)返回每個特徵的重要性,一般是 這個特徵在多次分枝中產的信息增益的綜合,也被稱爲”基尼重要性”(Gini Importance) |
n_ classes_ |
輸出整數或列表,標籤類別的數據 |
n_ features_ |
在訓練模型(ft)時使用的特徵個數 |
n_ outputs_ |
在訓練模型(it)時輸出的結果的個數 |
oob_ score_ |
輸出浮點數,使用袋外數據來驗證模型效益的分數 |
oob_ decision function_ |
根據袋外驗證結果計 算的決策函數。如果n_ `estimators非常小, 那有可能在進行隨機放回抽樣的過程中沒有數據掉落在袋外,在這種情況下,oob_ decision. _function 的結果會是NaN。 |
2.2.5 重要接口
接口 | 含義 |
---|---|
apply (X[, check input]) |
輸入測試集或樣本點, 返回每個樣本被分到的葉節點的索引check input是接口apply的參數,輸入布爾值,默認True,通常不使用 |
decision_ path(X[, check_input) |
輸入測試集或樣本點, 返回樹中的決策樹結構,Check input同樣是參數 |
fit() |
不多說 |
get_ params(deep]) |
布爾值,獲取這個模型評估對象的參數。默認爲True,表示返回此估計器的參數幷包含作爲估算器的子對象。返回模型評估對象在實例化時的參數設置。 |
predict() |
和fit中提供的訓練集結構一致,不多說 |
predict_ log_ proba(X) |
預測所提供的測試集X中樣本點歸屬於各個標籤的對數概率 |
predict proba(X[, check_input]) |
預測所提供的測試集 X中樣本點歸屬於各個標籤的概率 |
score() |
不多說 |
set_ params(**params) |
可以爲已經建立的評估器重設參數,返回重新設置的評估器本身 |
3、隨機森林的調參
接下來以sklearn中的乳腺癌數據集來進行調參實例。
1.導入需要的庫
from sklearn.datasets import load_breast_cancer
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import GridSearchCV
from sklearn.model_selection import cross_val_score
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
2.導入數據集,探索數據
data = load_breast_cancer()
data
data.data.shape
data.target
3. 進行一次簡單的建模,看看模型本身在數據集上的效果
交叉驗證的分類默認scoring=‘accuracy’,你也可以換成其他的指標(後面會持續更新分類的評價指標)。
rfc = RandomForestClassifier(n_estimators=100,random_state=90)
score_pre = cross_val_score(rfc,data.data,data.target,cv=10).mean()
score_pre
4. 隨機森林調整的第一步:無論如何先來調n_estimators
我們將使用網格搜索對參數一個個進行調整。爲什麼我們不同時調整多個參數呢?原因有兩個:
- 同時調整多個參數會運行非常緩慢;
- 同時調整多個參數,會讓我們無法理解參數的組合是怎麼得來的,所以即便網格搜索調出來的結果不好,我們也不知道從哪裏去改。
在這裏我們選擇學習曲線,只有學習曲線,才能看見趨勢。我個人的傾向是,要看見n_estimators在什麼取值開始變得平穩,是否一直推動模型整體準確率的上升等信息。第一次的學習曲線,可以先用來幫助我們劃定範圍,我們取每十個數作爲一個階段,來觀察n_estimators的變化如何引起模型整體準確率的變化。
scorel = []
for i in range(0,200,10):
rfc = RandomForestClassifier(n_estimators=i+1,
n_jobs=-1,
random_state=90)
score = cross_val_score(rfc,data.data,data.target,cv=10).mean()
scorel.append(score)
print(max(scorel),(scorel.index(max(scorel))*10)+1)
plt.figure(figsize=[20,5])
plt.plot(range(1,201,10),scorel)
plt.show()
5. 開始按照參數對模型整體準確率的影響程度進行調參,調整max_depth
param_grid = {'max_depth':np.arange(1, 20, 1)}
# 一般根據數據的大小來進行一個試探,乳腺癌數據很小,所以可以採用1~10,或者1~20這樣的試探
# 但對於像digit recognition那樣的大型數據來說,我們應該嘗試30~50層深度(或許還不足夠
# 更應該畫出學習曲線,來觀察深度對模型的影響
rfc = RandomForestClassifier(n_estimators=39
,random_state=90
)
GS = GridSearchCV(rfc,param_grid,cv=10)#網格搜索
GS.fit(data.data,data.target)
print(GS.best_params_)#顯示調整出來的最佳參數
print(GS.best_score_)#返回調整好的最佳參數對應的準確率
6. 調整max_features
param_grid = {'max_features':np.arange(5,30,1)}
rfc = RandomForestClassifier(n_estimators=39
,random_state=90
)
GS = GridSearchCV(rfc,param_grid,cv=10)
GS.fit(data.data,data.target)
print(GS.best_params_)
print(GS.best_score_)
7.調整min_samples_leaf
param_grid={'min_samples_leaf':np.arange(1, 1+10, 1)}
rfc = RandomForestClassifier(n_estimators=39
,random_state=90
)
GS = GridSearchCV(rfc,param_grid,cv=10)
GS.fit(data.data,data.target)
print(GS.best_params_)
print(GS.best_score_)
8.調整min_samples_split
param_grid={'min_samples_split':np.arange(2, 2+20, 1)}
rfc = RandomForestClassifier(n_estimators=39
,random_state=90
)
GS = GridSearchCV(rfc,param_grid,cv=10)
GS.fit(data.data,data.target)
print(GS.best_params_)
print(GS.best_score_)
9.調參完畢,總結最佳參數
網格搜索也可以一起調整多個參數,如果有時間,電腦CPU,內存足夠好可以自己跑一下,看看網格搜索會給我們怎樣的結果,有時候,它的結果比我們的好,有時候,我們手動調整的結果會比較好。當然了,我們的乳腺癌數據集非常完美,所以
只需要調n_estimators一個參數就達到了隨機森林在這個數據集上表現得極限。
rfc = RandomForestClassifier(n_estimators=68,
random_state=90,
criterion="gini",
min_samples_split=8,
min_samples_leaf=1,
max_depth=12,
max_features=2,
max_leaf_nodes=36
)