隨機森林在sklearn中的實現
隨機森林在sklearn中的實現:
隨機森林
1 概述
1.1 集成算法概述
1.2 sklearn中的集成算法
2 RandomForestClassi?er
2.1 重要參數
2.1.1 控制基評估器的參數
2.1.2 n_estimators
2.1.3 random_state
2.1.4 bootstrap & oob_score
2.2 重要屬性和接口
Bonus:Bagging的另一個必要條件
3 RandomForestRegressor
3.1 重要參數,屬性與接口
criterion
重要屬性和接口
3.2 實例:用隨機森林回歸填補缺失值
4 機器學習中調參的基本思想
5 實例:隨機森林在乳腺癌數據上的調參
6 附錄
6.1 Bagging vs Boosting
6.2 RFC的參數列表
6.3 RFC的屬性列表
6.4 RFC的接口列表
1 概述
1.1 集成算法概述
集成學習(ensemble learning)是時下非常流行的機器學習算法,它本身不是一個單獨的機器學習算法,而是通過在數據上構建多個模型,集成所有模型的建模結果。基本上所有的機器學習領域都可以看到集成學習的身影,在現實中集成學習也有相當大的作用,它可以用來做市場營銷模擬的建模,統計客戶來源,保留和流失,也可用來預測疾病的風險和病患者的易感性。在現在的各種算法競賽中,隨機森林,梯度提升樹(GBDT),Xgboost等集成算法的身影也隨處可見,可見其效果之好,應用之廣。
集成算法的目標:集成算法會考慮多個評估器的建模結果,匯總之後得到一個綜合的結果,以此來獲取比單個模型更好的回歸或分類表現。
多個模型集成成為的模型叫做集成評估器(ensemble estimator),組成集成評估器的每個模型都叫做基評估器(base estimator)。通常來說,有三類集成算法:裝袋法(Bagging),提升法(Boosting)和stacking。
裝袋法的核心思想是構建多個相互獨立的評估器,然後對其預測進行平均或多數表決原則來決定集成評估器的結果。裝袋法的代表模型就是隨機森林。
提升法中,基評估器是相關的,是按順序一一構建的。其核心思想是結合弱評估器的力量一次次對難以評估的樣本進行預測,從而構成一個強評估器。提升法的代表模型有Adaboost和梯度提升樹。
1.2sklearn中的集成算法
- sklearn中的集成算法模塊ensemble
集成算法中,有一半以上都是樹的集成模型,可以想見決策樹在集成中必定是有很好的效果。在這堂課中,我們會以隨機森林為例,慢慢為大家揭開集成算法的神秘面紗。
2 RandomForestClassi?er
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)
隨機森林是非常具有代表性的Bagging集成算法,它的所有基評估器都是決策樹,分類樹組成的森林就叫做隨機森林分類器,回歸樹所集成的森林就叫做隨機森林回歸器。這一節主要講解RandomForestClassi?er,隨機森林分類器。
2.1 重要參數
2.1.1 控制基評估器的參數
單個決策樹的準確率越高,隨機森林的準確率也會越高,因為裝袋法是依賴於平均值或者少數服從多數原則來決定集成的結果的。
2.1.2 n_estimators
這是森林中樹木的數量,即基評估器的數量。這個參數對隨機森林模型的精確性影響是單調的,n_estimators越大,模型的效果往往越好。但是相應的,任何模型都有決策邊界,n_estimators達到一定的程度之後,隨機森林的精確性往往不在上升或開始波動,並且,n_estimators越大,需要的計算量和內存也越大,訓練的時間也會越來越長。對於這個參數,我們是渴望在訓練難度和模型效果之間取得平衡。
n_estimators的默認值在現有版本的sklearn中是10,但是在即將更新的0.22版本中,這個默認值會被修正為100。這個修正顯示出了使用者的調參傾向:要更大的n_estimators。
- 來建立一片森林吧
樹模型的優點是簡單易懂,可視化之後的樹人人都能夠看懂,可惜隨機森林是無法被可視化的。所以為了更加直觀地讓大家體會隨機森林的效果,我們來進行一個隨機森林和單個決策樹效益的對比。我們依然使用紅酒數據集。
1. 導入我們需要的包
%matplotlib inline from sklearn.tree import DecisionTreeClassifier from sklearn.ensemble import RandomForestClassifier from sklearn.datasets import load_wine
2. 導入需要的數據集
wine = load_wine() wine.data wine.target
3. 復習:sklearn建模的基本流程
#實例化 #訓練集帶入實例化的模型去進行訓練,使用的接口是fit #使用其他接口將測試集導入我們訓練好的模型,去獲取我們希望過去的結果(score.Y_test) from sklearn.model_selection import train_test_split Xtrain, Xtest, Ytrain, Ytest = train_test_split(wine.data,wine.target,test_size=0.3)
clf = DecisionTreeClassifier(random_state=0) rfc = RandomForestClassifier(random_state=0) clf = clf.fit(Xtrain,Ytrain) rfc = rfc.fit(Xtrain,Ytrain) score_c = clf.score(Xtest,Ytest) score_r = rfc.score(Xtest,Ytest) print("Single Tree:{}".format(score_c) ,"Random Forest:{}".format(score_r) )
4. 畫出隨機森林和決策樹在一組交叉驗證下的效果對比
#目的是帶大家復習一下交叉驗證 #交叉驗證:是數據集劃分為n分,依次取每一份做測試集,每n-1份做訓練集,多次訓練模型以觀測模型穩定性的方法 from sklearn.model_selection import cross_val_score import matplotlib.pyplot as plt rfc = RandomForestClassifier(n_estimators=25) rfc_s = cross_val_score(rfc,wine.data,wine.target,cv=10) clf = DecisionTreeClassifier() clf_s = cross_val_score(clf,wine.data,wine.target,cv=10) plt.plot(range(1,11),rfc_s,label = "RandomForest") plt.plot(range(1,11),clf_s,label = "Decision Tree") plt.legend() plt.show() #====================一種更加有趣也更簡單的寫法===================# """ label = "RandomForest" for model in [RandomForestClassifier(n_estimators=25),DecisionTreeClassifier()]: score = cross_val_score(model,wine.data,wine.target,cv=10) print("{}:".format(label)),print(score.mean()) plt.plot(range(1,11),score,label = label) plt.legend() label = "DecisionTree" """
結果:
5. 畫出隨機森林和決策樹在十組交叉驗證下的效果對比(實際情況中幾乎不用,這裏只是為了更清楚的讓初學者理解隨機森林效果更好)
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() #是否有註意到,單個決策樹的波動軌跡和隨機森林一致? #再次驗證了我們之前提到的,單個決策樹的準確率越高,隨機森林的準確率也會越高
結果:
6. n_estimators的學習曲線
#####【TIME WARNING: 2mins 30 seconds】##### superpa = [] for i in range(200): 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))+1)#打印出:最高精確度取值,max(superpa))+1指的是森林數目的數量n_estimators plt.figure(figsize=[20,5]) plt.plot(range(1,201),superpa) plt.show()
結果:0.9888888888888889 42
思考:隨機森林用了什麽方法,來保證集成的效果一定好於單個分類器?
2.1.3 random_state
隨機森林的本質是一種裝袋集成算法(bagging),裝袋集成算法是對基評估器的預測結果進行平均或用多數表決原則來決定集成評估器的結果。在剛才的紅酒例子中,我們建立了25棵樹,對任何一個樣本而言,平均或多數表決原則下,當且僅當有13棵以上的樹判斷錯誤的時候,隨機森林才會判斷錯誤。單獨一棵決策樹對紅酒數據集的分類準確率在0.85上下浮動,假設一棵樹判斷錯誤的可能性為0.2(ε),那20棵樹以上都判斷錯誤的可能性是:
其中,i是判斷錯誤的次數,也是判錯的樹的數量,ε是一棵樹判斷錯誤的概率,(1-ε)是判斷正確的概率,共判對25-i次。采用組合,是因為25棵樹中,有任意i棵都判斷錯誤。
import numpy as np from scipy.special import comb np.array([comb(25,i)*(0.2**i)*((1-0.2)**(25-i)) for i in range(13,26)]).sum()
可見,判斷錯誤的幾率非常小,這讓隨機森林在紅酒數據集上的表現遠遠好於單棵決策樹。
那現在就有一個問題了:我們說袋裝法服從多數表決原則或對基分類器結果求平均,這即是說,我們默認森林中的每棵樹應該是不同的,並且會返回不同的結果。設想一下,如果隨機森林裏所有的樹的判斷結果都一致(全判斷對或全判斷錯),那隨機森林無論應用何種集成原則來求結果,都應該無法比單棵決策樹取得更好的效果才對。但我們使用了一樣的類DecisionTreeClassi?er,一樣的參數,一樣的訓練集和測試集,為什麽隨機森林裏的眾多樹會有不同的判斷結果?
問到這個問題,很多小夥伴可能就會想到了:sklearn中的分類樹DecisionTreeClassi?er自帶隨機性,所以隨機森林中的樹天生就都是不一樣的。我們在講解分類樹時曾提到,決策樹從最重要的特征中隨機選擇出一個特征來進行分枝,因此每次生成的決策樹都不一樣,這個功能由參數random_state控制。
隨機森林中其實也有random_state,用法和分類樹中相似,只不過在分類樹中,一個random_state只控制生成一棵樹,而隨機森林中的random_state控制的是生成森林的模式,而非讓一個森林中只有一棵樹。
rfc = RandomForestClassifier(n_estimators=20,random_state=2) rfc = rfc.fit(Xtrain, Ytrain) #隨機森林的重要屬性之一:estimators,查看森林中樹的狀況 rfc.estimators_[0].random_state 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
我們可以觀察到,當random_state固定時,隨機森林中生成是一組固定的樹,但每棵樹依然是不一致的,這是用”隨機挑選特征進行分枝“的方法得到的隨機性。並且我們可以證明,當這種隨機性越大的時候,袋裝法的效果一般會越來越好。用袋裝法集成時,基分類器應當是相互獨立的,是不相同的。
但這種做法的局限性是很強的,當我們需要成千上萬棵樹的時候,數據不一定能夠提供成千上萬的特征來讓我們構築盡量多盡量不同的樹。因此,除了random_state。我們還需要其他的隨機性。
2.1.4 bootstrap & oob_score
要讓基分類器盡量都不一樣,一種很容易理解的方法是使用不同的訓練集來進行訓練,而袋裝法正是通過有放回的隨機抽樣技術來形成不同的訓練數據,bootstrap就是用來控制抽樣技術的參數。
在一個含有n個樣本的原始訓練集中,我們進行隨機采樣,每次采樣一個樣本,並在抽取下一個樣本之前將該樣本放回原始訓練集,也就是說下次采樣時這個樣本依然可能被采集到,這樣采集n次,最終得到一個和原始訓練集一樣大的,n個樣本組成的自助集。由於是隨機采樣,這樣每次的自助集和原始數據集不同,和其他的采樣集也是不同的。這樣我們就可以自由創造取之不盡用之不竭,並且互不相同的自助集,用這些自助集來訓練我們的基分類器,我們的基分類器自然也就各不相同了。
bootstrap參數默認True,代表采用這種有放回的隨機抽樣技術。通常,這個參數不會被我們設置為False。
然而有放回抽樣也會有自己的問題。由於是有放回,一些樣本可能在同一個自助集中出現多次,而其他一些卻可能被忽略,一般來說,自助集大約平均會包含63%的原始數據。因為每一個樣本被抽到某個自助集中的概率為:
當n足夠大時,這個概率收斂於1-(1/e),約等於0.632。因此,會有約37%的訓練數據被浪費掉,沒有參與建模,這些數據被稱為袋外數據(out of bag data,簡寫為oob)。除了我們最開始就劃分好的測試集之外,這些數據也可以被用來作為集成算法的測試集。也就是說,在使用隨機森林時,我們可以不劃分測試集和訓練集,只需要用袋外數據來測試我們的模型即可。當然,這也不是絕對的,當n和n_estimators都不夠大的時候,很可能就沒有數據掉落在袋外,自然也就無法使用oob數據來測試模型了。
如果希望用袋外數據來測試,則需要在實例化時就將oob_score這個參數調整為True,訓練完畢之後,我們可以用隨機森林的另一個重要屬性:oob_score_來查看我們的在袋外數據上測試的結果:
隨機森林在sklearn中的實現