之前在集成原理小結中總結了Bagging的原理。 理解了bagging算法,隨機森林(Random Forest,以下簡稱RF)就好理解了。它是Bagging算法的進化版,也就是說,它的思想仍然是bagging,但是進行了獨有的改進。
1. 隨機森林的原理(普通bagging的升級版)
第一,RF使用了CART決策樹作為弱學習器。第二,在使用決策樹的基礎上,RF對決策樹的建立做了改進,對於普通的決策樹,我們會在節點上所有的n個樣本特征中選擇一個最優的特征來做決策樹的左右子樹划分,但是RF是會在節點上隨機選擇一部分樣本特征,然后在這些隨機選擇的部分樣本特征中,選擇一個最優的特征來做決策樹的左右子樹划分。這樣進一步增強了模型的泛化能力。
假設RF中節點上所有的特征為n個,隨機選擇的部分特征為 ns個。
- 如果ns=n,則此時RF的CART決策樹和普通的CART決策樹沒有區別。
- ns越小,則模型約健壯,當然此時對於訓練集的擬合程度會變差。也就是說ns越小,模型的方差會減小,但是偏差會增大。在實際案例中,一般會通過交叉驗證調參獲取一個合適的ns的值。
除了上面兩點,RF和普通的bagging算法沒有什么不同, 下面簡單總結下RF的算法。
輸入為樣本集D={(x,y1),(x2,y2),...(xm,ym)},弱分類器迭代次數T。
輸出為最終的強分類器f(x)
1)對於t=1,2...,T:
a)對訓練集進行第t次隨機采樣,共采集m次,得到包含m個樣本的采樣集Dt
b)用采樣集Dt訓練第t個決策樹模型Gt(x),在訓練決策樹模型的節點的時候, 在節點上所有的樣本特征中選擇一部分樣本特征, 在這些隨機選擇的部分樣本特征中選擇一個最優的特征來做決策樹的左右子樹划分
2) 如果是分類算法預測,則T個弱學習器投出最多票數的類別或者類別之一為最終類別。如果是回歸算法,T個弱學習器得到的回歸結果進行算術平均得到的值為最終的模型輸出。
2.隨機森林的特點
作為一個可以高度並行化的算法,RF在大數據時候大有可為。 這里也對常規的隨機森林算法的優缺點做一個總結。
(1)優點
1) 訓練可以高度並行化,對於大數據時代的大樣本訓練速度有優勢。個人覺得這是的最主要的優點。
2) 由於采用隨機采樣,可以防止模型過擬合。訓練出的模型的方差小,泛化能力強。
3) 由於可以隨機選擇決策樹節點划分的特征,這樣在樣本特征維度很高的時候,不用降維,無需做特征選擇,仍然能高效的訓練模型,。
4) 相對於Boosting系列的Adaboost和GBDT, RF實現比較簡單。
5) 對部分特征缺失不敏感。
6) 在訓練后,可以給出各個特征對於輸出的重要性,模型有可解釋性
(2) 缺點
1)在某些噪音比較大的樣本集上,RF模型容易陷入過擬合。
- 取值划分比較多的特征容易對RF的決策產生更大的影響,從而影響擬合的模型的效果。
3. 隨機森林的實現和調參
在 scikit-learn 中,隨機森林的實現用集成包ensemble 中 RandomForestClassifier類。
from sklearn.ensemble import RandomForestClassifier
class sklearn.ensemble.RandomForestClassifier (n_estimators=’10’, 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)
1. 重要參數
-
基評估器的參數
隨機森林的基評估器是決策樹,單個決策樹的准確率越高,隨機森林的准確率也會越高,因為裝袋法是依賴於平均值或
者少數服從多數原則來決定集成的結果的。
-
n_estimators
這是森林中樹木的數量,即基評估器的數量。一般n_estimators越大,模型的效果往往越好。但是超過邊界后,隨機森林的精確性往往不在上升或開始波動,同時n_estimators越大,需要的計算量和內存也越大,訓練的時間也會越來越長。對於這個參數,我們是渴望在訓練難度和模型效果之間取得平衡。
現在的版本中個默認值為100。
# 單個決策樹和隨機森林,10折交叉驗證的平均准確率結果對比
%matplotlib inline
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import load_wine
from sklearn.model_selection import cross_val_score
import matplotlib.pyplot as plt
wine = load_wine()
wine.data
wine.target
rfc_l = []
clf_l = []
for i in range(10):
rfc = RandomForestClassifier(n_estimators=25)
rfc_s = cross_val_score(rfc,wine.data,wine.target,cv=10).mean()
rfc_l.append(rfc_s)
clf = DecisionTreeClassifier()
clf_s = cross_val_score(clf,wine.data,wine.target,cv=10).mean()
clf_l.append(clf_s)
plt.plot(range(1,11),rfc_l,label = "Random Forest")
plt.plot(range(1,11),clf_l,label = "Decision Tree")
plt.legend()
plt.show()

# 隨機森林中,模型准確率與森林中決策樹的數量的關系
superpa = []
for i in range(100):
rfc = RandomForestClassifier(n_estimators=i+1,n_jobs=-1)
rfc_s = cross_val_score(rfc,wine.data,wine.target,cv=10).mean()
superpa.append(rfc_s)
print(max(superpa),superpa.index(max(superpa)))
plt.figure(figsize=[20,5])
plt.plot(range(1,101),superpa)
plt.show()
0.9888888888888889 40

- random_state
由於決策樹從最重要的特征中隨機選擇出一個特征來進行分枝,因此每次生成的決策樹都不一樣,這個功能由參數random_state控制。
隨機森林中其實也有random_state,用法和分類樹中相似,只不過在分類樹中,一個random_state只控制生成一棵樹,而隨機森林中的random_state控制的是生成森林的模式,而非讓一個森林中只有一棵樹。
random_state指定一個隨機數種子,會生成一組固定的樹。
rfc = RandomForestClassifier(n_estimators=20,random_state=2)
rfc = rfc.fit(Xtrain, Ytrain)
#隨機森林的重要屬性之一:estimators,查看森林中樹的狀況
# 森林中的每一棵樹都有自己的隨機數種子
for i in range(len(rfc.estimators_)):
print(rfc.estimators_[i].random_state)
1872583848
794921487
111352301
1853453896
213298710
1922988331
1869695442
2081981515
1805465960
1376693511
1418777250
663257521
878959199
854108747
512264917
515183663
1287007039
2083814687
1146014426
570104212
- bootstrap & oob_score
隨機森林采用bootstrap的隨機采樣,即有放回的隨機抽樣基數,參數默認bootstrap = True。一般不做修改。
隨機森林由於是有放回的抽樣,一些樣本可能在同一個自助集中出現多次,而其他一些卻可能被忽略,一般來說,自助集大約平均會包含63%的原始數據。會有約37%的訓練數據被浪費掉,沒有參與建模,這些數據被稱為袋外數據(out of bag data,簡寫為oob)。除了我們最開始就划分好的測試集之外,這些數據也可以被用來作為集成算法的測試集。
如果希望用袋外數據來測試,則需要在實例化時就將oob_score這個參數調整為True,訓練完后,用oob_score_ 屬性來查看我們的在袋外數據上測試的結果。
#無需划分訓練集和測試集
rfc = RandomForestClassifier(n_estimators=25,oob_score=True)
rfc = rfc.fit(wine.data,wine.target)
#重要屬性oob_score_
rfc.oob_score_
0.9606741573033708
以下對隨機森林調參模型的優先級做了總結:
2.重要的屬性和接口
隨機森林的接口與決策樹完全一致,因此依然有四個常用接口:apply, fit, predict和score。
除此之外,還需要注意隨機森林的predict_proba接口,這個接口返回每個測試樣本對應的被分到每一類標簽的概率,標簽有幾個分類
就返回幾個概率。
傳統的隨機森林是利用袋裝法中的規則,平均或少數服從多數來決定集成的結果,而sklearn中的隨機森林是平均每個弱分類器對應的predict_proba返回的概率,得到一個平均概率,從而決定測試樣本的分類 。
# 常用的屬性和接口
rfc = RandomForestClassifier(n_estimators=25)
rfc = rfc.fit(Xtrain, Ytrain)
rfc.score(Xtest,Ytest)
rfc.feature_importances_
rfc.apply(Xtest)
rfc.predict(Xtest)
rfc.predict_proba(Xtest)
array([[0.04, 0.92, 0.04],
[0.28, 0.64, 0.08],
[0. , 1. , 0. ],
[0.88, 0.08, 0.04],
[0.92, 0.08, 0. ],
[0.04, 0.92, 0.04],
[0. , 0.92, 0.08],
[1. , 0. , 0. ],
[1. , 0. , 0. ],
[0. , 0.88, 0.12],
[0. , 1. , 0. ],
[0.8 , 0.12, 0.08],
[0.04, 0.92, 0.04],
[0.04, 0.16, 0.8 ],
[0.12, 0.8 , 0.08],
[0.12, 0.44, 0.44],
[0. , 1. , 0. ],
[0.16, 0.76, 0.08],
[1. , 0. , 0. ],
[0.12, 0.08, 0.8 ],
[0.4 , 0.44, 0.16],
[0. , 0.04, 0.96],
[0. , 0.2 , 0.8 ],
[1. , 0. , 0. ],
[0.2 , 0.68, 0.12],
[0.96, 0.04, 0. ],
[1. , 0. , 0. ],
[0. , 0.16, 0.84],
[0. , 0.92, 0.08],
[0. , 0.4 , 0.6 ],
[0. , 0.04, 0.96],
[0.48, 0.44, 0.08],
[0.2 , 0.8 , 0. ],
[0.92, 0.08, 0. ],
[0.84, 0.04, 0.12],
[0.04, 0.92, 0.04],
[1. , 0. , 0. ],
[1. , 0. , 0. ],
[0.04, 0.96, 0. ],
[1. , 0. , 0. ],
[0. , 0.52, 0.48],
[1. , 0. , 0. ],
[1. , 0. , 0. ],
[0.24, 0.76, 0. ],
[0. , 0. , 1. ],
[1. , 0. , 0. ],
[1. , 0. , 0. ],
[1. , 0. , 0. ],
[1. , 0. , 0. ],
[0.04, 0.88, 0.08],
[0.88, 0.04, 0.08],
[0. , 0.88, 0.12],
[0. , 0.08, 0.92],
[1. , 0. , 0. ]])