【菜菜的sklearn】02 隨機(jī)森林

小伙伴們大家好~o( ̄▽ ̄)ブ
我是菜菜,這里是我的sklearn課堂第2期:隨機(jī)森林在sklearn中的實(shí)現(xiàn)和調(diào)參~

我的開發(fā)環(huán)境是Jupyter lab,所用的庫和版本大家參考:
Python 3.7.1(你的版本至少要3.4以上
Scikit-learn 0.20.0 (你的版本至少要0.19
Numpy 1.15.3, Pandas 0.23.4, Matplotlib 3.0.1, SciPy 1.1.0

本文主要內(nèi)容:
?1 概述
??1.1 集成算法概述
??1.2 sklearn中的集成算法
?2 RandomForestClassifier
??2.1 重要參數(shù)
???2.1.1 控制基評估器的參數(shù)
???2.1.2 n_estimators
??2.2 重要屬性和接口
?3 機(jī)器學(xué)習(xí)中調(diào)參的基本思想
?4 實(shí)例:隨機(jī)森林在乳腺癌數(shù)據(jù)上的調(diào)參

1 概述

1.1 集成算法概述

集成學(xué)習(xí)(ensemble learning)是時(shí)下非常流行的機(jī)器學(xué)習(xí)算法,它本身不是一個(gè)單獨(dú)的機(jī)器學(xué)習(xí)算法,而是通過在數(shù)據(jù)上構(gòu)建多個(gè)模型,集成所有模型的建模結(jié)果?;旧纤械臋C(jī)器學(xué)習(xí)領(lǐng)域都可以看到集成學(xué)習(xí)的身影,在現(xiàn)實(shí)中集成學(xué)習(xí)也有相當(dāng)大的作用,它可以用來做市場營銷模擬的建模,統(tǒng)計(jì)客戶來源,保留和流失,也可用來預(yù)測疾病的風(fēng)險(xiǎn)和病患者的易感性。在現(xiàn)在的各種算法競賽中,隨機(jī)森林,梯度提升樹(GBDT),Xgboost等集成算法的身影也隨處可見,可見其效果之好,應(yīng)用之廣。

集成算法的目標(biāo)
集成算法會(huì)考慮多個(gè)評估器的建模結(jié)果,匯總之后得到一個(gè)綜合的結(jié)果,以此來獲取比單個(gè)模型更好的回歸或分類表現(xiàn)。

多個(gè)模型集成成為的模型叫做集成評估器(ensemble estimator),組成集成評估器的每個(gè)模型都叫做基評估器(base estimator)。通常來說,有三類集成算法:裝袋法(Bagging),提升法(Boosting)和stacking。

image

裝袋法的核心思想是構(gòu)建多個(gè)相互獨(dú)立的評估器,然后對其預(yù)測進(jìn)行平均或多數(shù)表決原則來決定集成評估器的結(jié)果。裝袋法的代表模型就是隨機(jī)森林。

提升法中,基評估器是相關(guān)的,是按順序一一構(gòu)建的。其核心思想是結(jié)合弱評估器的力量一次次對難以評估的樣本進(jìn)行預(yù)測,從而構(gòu)成一個(gè)強(qiáng)評估器。提升法的代表模型有Adaboost和梯度提升樹。

1.2 sklearn中的集成算法

  • sklearn中的集成算法模塊ensemble
類的功能
ensemble.AdaBoostClassifier AdaBoost分類
ensemble.AdaBoostRegressor Adaboost回歸
ensemble.BaggingClassifier 裝袋分類器
ensemble.BaggingRegressor 裝袋回歸器
ensemble.ExtraTreesClassifier Extra-trees分類(超樹,極端隨機(jī)樹)
ensemble.ExtraTreesRegressor Extra-trees回歸
ensemble.GradientBoostingClassifier 梯度提升分類
ensemble.GradientBoostingRegressor 梯度提升回歸
ensemble.IsolationForest 隔離森林
ensemble.RandomForestClassifier 隨機(jī)森林分類
ensemble.RandomForestRegressor 隨機(jī)森林回歸
ensemble.RandomTreesEmbedding 完全隨機(jī)樹的集成
ensemble.VotingClassifier 用于不合適估算器的軟投票/多數(shù)規(guī)則分類器

集成算法中,有一半以上都是樹的集成模型,可以想見決策樹在集成中必定是有很好的效果。在這堂課中,我們會(huì)以隨機(jī)森林為例,慢慢為大家揭開集成算法的神秘面紗。

  • 復(fù)習(xí):sklearn中的決策樹

在開始隨機(jī)森林之前,我們先復(fù)習(xí)一下決策樹。決策樹是一種原理簡單,應(yīng)用廣泛的模型,它可以同時(shí)被用于分類和回歸問題。決策樹的主要功能是從一張有特征和標(biāo)簽的表格中,通過對特定特征進(jìn)行提問,為我們總結(jié)出一系列決策規(guī)則,并用樹狀圖來呈現(xiàn)這些決策規(guī)則。

決策樹的核心問題有兩個(gè),一個(gè)是如何找出正確的特征來進(jìn)行提問,即如何分枝,二是樹生長到什么時(shí)候應(yīng)該停下。

對于第一個(gè)問題,我們定義了用來衡量分枝質(zhì)量的指標(biāo)不純度,分類樹的不純度用基尼系數(shù)或信息熵來衡量,回歸樹的不純度用MSE均方誤差來衡量。每次分枝時(shí),決策樹對所有的特征進(jìn)行不純度計(jì)算,選取不純度最低的特征進(jìn)行分枝,分枝后,又再對被分枝的不同取值下,計(jì)算每個(gè)特征的不純度,繼續(xù)選取不純度最低的特征進(jìn)行分枝。

每分枝一層,樹整體的不純度會(huì)越來越小,決策樹追求的是最小不純度。因此,決策樹會(huì)一致分枝,直到?jīng)]有更多的特征可用,或整體的不純度指標(biāo)已經(jīng)最優(yōu),決策樹就會(huì)停止生長。

決策樹非常容易過擬合,這是說,它很容易在訓(xùn)練集上表現(xiàn)優(yōu)秀,卻在測試集上表現(xiàn)很糟糕。為了防止決策樹的過擬合,我們要對決策樹進(jìn)行剪枝,sklearn中提供了大量的剪枝參數(shù),我們一會(huì)兒會(huì)帶大家復(fù)習(xí)一下。

  • sklearn的基本建模流程

我們先來了解一下sklearn建模的基本流程。

在這個(gè)流程下,隨機(jī)森林對應(yīng)的代碼和決策樹基本一致:

from sklearn.tree import RandomForestClassifier     #導(dǎo)入需要的模塊

rfc = RandomForestClassifier()                      #實(shí)例化
rfc = rfc.fit(X_train,y_train)                      #用訓(xùn)練集數(shù)據(jù)訓(xùn)練模型
result = rfc.score(X_test,y_test)                   #導(dǎo)入測試集,從接口中調(diào)用需要的信息
rfc = RandomForestClassifier()                      #實(shí)例化
rfc = rfc.fit(X_train,y_train)                      #用訓(xùn)練集數(shù)據(jù)訓(xùn)練模型
result = rfc.score(X_test,y_test)                   #導(dǎo)入測試集,從接口中調(diào)用需要的信息

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

隨機(jī)森林是非常具有代表性的Bagging集成算法,它的所有基評估器都是決策樹,分類樹組成的森林就叫做隨機(jī)森林分類器,回歸樹所集成的森林就叫做隨機(jī)森林回歸器。這一節(jié)主要講解RandomForestClassifier,隨機(jī)森林分類器。

2.1 重要參數(shù)

2.1.1 控制基評估器的參數(shù)

參數(shù) 含義
criterion 不純度的衡量指標(biāo),有基尼系數(shù)和信息熵兩種選擇
max_depth 樹的最大深度,超過最大深度的樹枝都會(huì)被剪掉
min_samples_leaf 一個(gè)節(jié)點(diǎn)在分枝后的每個(gè)子節(jié)點(diǎn)都必須包含至少min_samples_leaf個(gè)訓(xùn)練樣本,否則分枝就不會(huì)發(fā)生
min_samples_split 一個(gè)節(jié)點(diǎn)必須要包含至少min_samples_split個(gè)訓(xùn)練樣本,這個(gè)節(jié)點(diǎn)才允許被分枝,否則分枝就不會(huì)發(fā)生
max_features max_features限制分枝時(shí)考慮的特征個(gè)數(shù),超過限制個(gè)數(shù)的特征都會(huì)被舍棄,默認(rèn)值為總特征個(gè)數(shù)開平方取整
min_impurity_decrease 限制信息增益的大小,信息增益小于設(shè)定數(shù)值的分枝不會(huì)發(fā)生

這些參數(shù)在隨機(jī)森林中的含義,和我們在上決策樹時(shí)說明的內(nèi)容一模一樣,單個(gè)決策樹的準(zhǔn)確率越高,隨機(jī)森林的準(zhǔn)確率也會(huì)越高,因?yàn)檠b袋法是依賴于平均值或者少數(shù)服從多數(shù)原則來決定集成的結(jié)果的。

2.1.2 n_estimators

這是森林中樹木的數(shù)量,即基基評估器的數(shù)量。這個(gè)參數(shù)對隨機(jī)森林模型的精確性影響是單調(diào)的,n_estimators越大,模型的效果往往越好。但是相應(yīng)的,任何模型都有決策邊界,n_estimators達(dá)到一定的程度之后,隨機(jī)森林的精確性往往不在上升或開始波動(dòng),并且,n_estimators越大,需要的計(jì)算量和內(nèi)存也越大,訓(xùn)練的時(shí)間也會(huì)越來越長。對于這個(gè)參數(shù),我們是渴望在訓(xùn)練難度和模型效果之間取得平衡。

n_estimators的默認(rèn)值在現(xiàn)有版本的sklearn中是10,但是在即將更新的0.22版本中,這個(gè)默認(rèn)值會(huì)被修正為100。這個(gè)修正顯示出了使用者的調(diào)參傾向:要更大的n_estimators。

  • 讓我們來建立一片森林吧

樹模型的優(yōu)點(diǎn)是簡單易懂,可視化之后的樹人人都能夠看懂,可惜隨機(jī)森林是無法被可視化的。所以為了更加直觀地讓大家體會(huì)隨機(jī)森林的效果,我們來進(jìn)行一個(gè)隨機(jī)森林和單個(gè)決策樹效益的對比。我們依然使用紅酒數(shù)據(jù)集。

  1. 導(dǎo)入我們需要的包
%matplotlib inline
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import load_wine
  1. 導(dǎo)入需要的數(shù)據(jù)集
wine = load_wine()

wine.data
wine.target
  1. 復(fù)習(xí):sklearn建模的基本流程
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)
     )
  1. 畫出隨機(jī)森林和決策樹在十組交叉驗(yàn)證下的效果對比
#帶大家復(fù)習(xí)一下交叉驗(yàn)證
#交叉驗(yàn)證:是數(shù)據(jù)集劃分為n分,依次取每一份做測試集,每n-1份做訓(xùn)練集,多次訓(xùn)練模型以觀測模型穩(wěn)定性的方法

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

#是否有注意到,單個(gè)決策樹的波動(dòng)軌跡和隨機(jī)森林一致?
#再次驗(yàn)證了我們之前提到的,單個(gè)決策樹的準(zhǔn)確率越高,隨機(jī)森林的準(zhǔn)確率也會(huì)越高
  1. n_estimators的學(xué)習(xí)曲線
#####【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)))
plt.figure(figsize=[20,5])
plt.plot(range(1,201),superpa)
plt.show()
思考
隨機(jī)森林用了什么方法,來保證集成的效果一定好于單個(gè)分類器?

2.2 重要屬性和接口

隨機(jī)森林中有三個(gè)非常重要的屬性:.estimators_,.oob_score_以及.feature_importances_

.estimators_是用來查看隨機(jī)森林中所有樹的列表的。

oob_score_指的是袋外得分。隨機(jī)森林為了確保林中的每棵樹都不盡相同,所以采用了對訓(xùn)練集進(jìn)行有放回抽樣的方式來不斷組成信的訓(xùn)練集,在這個(gè)過程中,會(huì)有一些數(shù)據(jù)從來沒有被隨機(jī)挑選到,他們就被叫做“袋外數(shù)據(jù)”。這些袋外數(shù)據(jù),沒有被模型用來進(jìn)行訓(xùn)練,sklearn可以幫助我們用他們來測試模型,測試的結(jié)果就由這個(gè)屬性oob_score_來導(dǎo)出,本質(zhì)還是模型的精確度。

而.feature_importances_和決策樹中的.feature_importances_用法和含義都一致,是返回特征的重要性。

隨機(jī)森林的接口與決策樹完全一致,因此依然有四個(gè)常用接口:apply, fit, predictscore。除此之外,還需要注意隨機(jī)森林的predict_proba接口,這個(gè)接口返回每個(gè)測試樣本對應(yīng)的被分到每一類標(biāo)簽的概率,標(biāo)簽有幾個(gè)分類就返回幾個(gè)概率。如果是二分類問題,則predict_proba返回的數(shù)值大于0.5的,被分為1,小于0.5的,被分為0。傳統(tǒng)的隨機(jī)森林是利用袋裝法中的規(guī)則,平均或少數(shù)服從多數(shù)來決定集成的結(jié)果,而sklearn中的隨機(jī)森林是平均每個(gè)樣本對應(yīng)的predict_proba返回的概率,得到一個(gè)平均概率,從而決定測試樣本的分類。

大家可以分別取嘗試一下這些屬性和接口
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)

掌握了上面的知識,基本上要實(shí)現(xiàn)隨機(jī)森林分類已經(jīng)是沒問題了。從紅酒數(shù)據(jù)集的表現(xiàn)上來看,隨機(jī)森林的效用比單純的決策樹要強(qiáng)上不少,大家可以自己更換其他數(shù)據(jù)來試試看。

3 機(jī)器學(xué)習(xí)中調(diào)參的基本思想

在準(zhǔn)備這一套課程的時(shí)候,我發(fā)現(xiàn)大多數(shù)的機(jī)器學(xué)習(xí)相關(guān)的書都是遍歷各種算法和案例,為大家講解各種各樣算法的原理和用途,但卻對調(diào)參探究甚少。這中間有許多原因,其一是因?yàn)?,調(diào)參的方式總是根據(jù)數(shù)據(jù)的狀況而定,所以沒有辦法一概而論;其二是因?yàn)?,其?shí)大家也都沒有特別好的辦法。

通過畫學(xué)習(xí)曲線,或者網(wǎng)格搜索,我們能夠探索到調(diào)參邊緣(代價(jià)可能是訓(xùn)練一次模型要跑三天三夜),但是在現(xiàn)實(shí)中,高手調(diào)參恐怕還是多依賴于經(jīng)驗(yàn),而這些經(jīng)驗(yàn),來源于:
1)非常正確的調(diào)參思路和方法,
2)對模型評估指標(biāo)的理解,
3)對數(shù)據(jù)的感覺和經(jīng)驗(yàn),
4)用洪荒之力去不斷地嘗試。

我們也許無法學(xué)到高手們多年累積的經(jīng)驗(yàn),但我們可以學(xué)習(xí)他們對模型評估指標(biāo)的理解和調(diào)參的思路。

那我們首先來講講正確的調(diào)參思路。模型調(diào)參,第一步是要找準(zhǔn)目標(biāo):我們要做什么?一般來說,這個(gè)目標(biāo)是提升某個(gè)模型評估指標(biāo),比如對于隨機(jī)森林來說,我們想要提升的是模型在未知數(shù)據(jù)上的準(zhǔn)確率(由score或oob_score_來衡量)。找準(zhǔn)了這個(gè)目標(biāo),我們就需要思考:模型在未知數(shù)據(jù)上的準(zhǔn)確率受什么因素影響?在機(jī)器學(xué)習(xí)中,我們用來衡量模型在未知數(shù)據(jù)上的準(zhǔn)確率的指標(biāo),叫做泛化誤差(Genelization error)。

  • 泛化誤差

當(dāng)模型在未知數(shù)據(jù)(測試集或者袋外數(shù)據(jù))上表現(xiàn)糟糕時(shí),我們說模型的泛化程度不夠,泛化誤差大,模型的效果不好。泛化誤差受到模型的結(jié)構(gòu)(復(fù)雜度)影響。看下面這張圖,它準(zhǔn)確地描繪了泛化誤差與模型復(fù)雜度的關(guān)系,當(dāng)模型太復(fù)雜,模型就會(huì)過擬合,泛化能力就不夠,所以泛化誤差大。當(dāng)模型太簡單,模型就會(huì)欠擬合,擬合能力就不夠,所以誤差也會(huì)大。只有當(dāng)模型的復(fù)雜度剛剛好的才能夠達(dá)到泛化誤差最小的目標(biāo)。

image

那模型的復(fù)雜度與我們的參數(shù)有什么關(guān)系呢?對樹模型來說,樹越茂盛,深度越深,枝葉越多,模型就越復(fù)雜。所以樹模型是天生位于圖的右上角的模型,隨機(jī)森林是以樹模型為基礎(chǔ),所以隨機(jī)森林也是天生復(fù)雜度高的模型。隨機(jī)森林的參數(shù),都是向著一個(gè)目標(biāo)去:減少模型的復(fù)雜度,把模型往圖像的左邊移動(dòng),防止過擬合。當(dāng)然了,調(diào)參沒有絕對,也有天生處于圖像左邊的隨機(jī)森林,所以調(diào)參之前,我們要先判斷,模型現(xiàn)在究竟處于圖像的哪一邊。

泛化誤差的背后其實(shí)是“偏差-方差困境”,原理十分復(fù)雜,無論你翻開哪一本書,你都會(huì)看見長篇的數(shù)學(xué)論證和每個(gè)字都能看懂但是連在一起就看不懂的文字解釋。在下一節(jié)偏差vs方差中,我用最簡單易懂的語言為大家解釋了泛化誤差背后的原理,大家選讀。那我們只需要記住這四點(diǎn):

1)模型太復(fù)雜或者太簡單,都會(huì)讓泛化誤差高,我們追求的是位于中間的平衡點(diǎn)
2)模型太復(fù)雜就會(huì)過擬合,模型太簡單就會(huì)欠擬合
3)對樹模型和樹的集成模型來說,樹的深度越深,枝葉越多,模型越復(fù)雜
4)樹模型和樹的集成模型的目標(biāo),都是減少模型復(fù)雜度,把模型往圖像的左邊移動(dòng)

那具體每個(gè)參數(shù),都如何影響我們的復(fù)雜度和模型呢?我們一直以來調(diào)參,都是在學(xué)習(xí)曲線上輪流找最優(yōu)值,盼望能夠?qū)?zhǔn)確率修正到一個(gè)比較高的水平。然而我們現(xiàn)在了解了隨機(jī)森林的調(diào)參方向:降低復(fù)雜度,我們就可以將那些對復(fù)雜度影響巨大的參數(shù)挑選出來,研究他們的單調(diào)性,然后專注調(diào)整那些能最大限度讓復(fù)雜度降低的參數(shù)。對于那些不單調(diào)的參數(shù),或者反而會(huì)讓復(fù)雜度升高的參數(shù),我們就視情況使用,大多時(shí)候甚至可以退避?;诮?jīng)驗(yàn),我對各個(gè)參數(shù)對模型的影響程度做了一個(gè)排序。在我們調(diào)參的時(shí)候,大家可以參考這個(gè)順序。

參數(shù) 對模型在未知數(shù)據(jù)上的評估性能的影響 影響程度
n_estimators 提升至平穩(wěn),n_estimators↑,不影響單個(gè)模型的復(fù)雜度 ????
max_depth 有增有減,默認(rèn)最大深度,即最高復(fù)雜度,向復(fù)雜度降低的方向調(diào)參max_depth↓,模型更簡單,且向圖像的左邊移動(dòng) ???
min_samples
_leaf
有增有減,默認(rèn)最小限制1,即最高復(fù)雜度,向復(fù)雜度降低的方向調(diào)參min_samples_leaf↑,模型更簡單,且向圖像的左邊移動(dòng) ??
min_samples
_split
有增有減,默認(rèn)最小限制2,即最高復(fù)雜度,向復(fù)雜度降低的方向調(diào)參min_samples_split↑,模型更簡單,且向圖像的左邊移動(dòng) ??
max_features 有增有減,默認(rèn)auto,是特征總數(shù)的開平方,位于中間復(fù)雜度,既可以向復(fù)雜度升高的方向,也可以向復(fù)雜度降低的方向調(diào)參
max_features↓,模型更簡單,圖像左移
max_features↑,模型更復(fù)雜,圖像右移
max_features是唯一的,既能夠讓模型更簡單,也能夠讓模型更復(fù)雜的參數(shù),所以在調(diào)整這個(gè)參數(shù)的時(shí)候,需要考慮我們調(diào)參的方向
?
criterion 有增有減,一般使用gini 看具體情況

有了以上的知識儲備,我們現(xiàn)在也能夠通過參數(shù)的變化來了解,模型什么時(shí)候到達(dá)了極限,當(dāng)復(fù)雜度已經(jīng)不能再降低的時(shí)候,我們就不必再調(diào)整了,因?yàn)檎{(diào)整大型數(shù)據(jù)的參數(shù)是一件非常費(fèi)時(shí)費(fèi)力的事。除了學(xué)習(xí)曲線和網(wǎng)格搜索,我們現(xiàn)在有了基于對模型和正確的調(diào)參思路的“推測”能力,這能夠讓我們的調(diào)參能力更上一層樓。

  • 偏差 vs 方差(選讀)

一個(gè)集成模型(f)在未知數(shù)據(jù)集(D)上的泛化誤差E(f;D),由方差(var),偏差(bais)和噪聲(ε)共同決定。
E(f;D) = bias^2(x) + var(x) +\varepsilon^2

關(guān)鍵概念:偏差與方差
觀察下面的圖像,每個(gè)點(diǎn)就是集成算法中的一個(gè)基評估器產(chǎn)生的預(yù)測值。紅色虛線代表著這些預(yù)測值的均值,而藍(lán)色的線代表著數(shù)據(jù)本來的面貌。

偏差:模型的預(yù)測值與真實(shí)值之間的差異,即每一個(gè)紅點(diǎn)到藍(lán)線的距離。在集成算法中,每個(gè)基評估器都會(huì)有自己的偏差,集成評估器的偏差是所有基評估器偏差的均值。模型越精確,偏差越低。

方差:反映的是模型每一次輸出結(jié)果與模型預(yù)測值的平均水平之間的誤差,即每一個(gè)紅點(diǎn)到紅色虛線的距離,衡量模型的穩(wěn)定性。模型越穩(wěn)定,方差越低。
image

其中偏差衡量模型是否預(yù)測得準(zhǔn)確,偏差越小,模型越“準(zhǔn)”;而方差衡量模型每次預(yù)測的結(jié)果是否接近,即是說方差越小,模型越“穩(wěn)”;噪聲是機(jī)器學(xué)習(xí)無法干涉的部分,為了讓世界美好一點(diǎn),我們就不去研究了。一個(gè)好的模型,要對大多數(shù)未知數(shù)據(jù)都預(yù)測得”準(zhǔn)“又”穩(wěn)“。即是說,當(dāng)偏差和方差都很低的時(shí)候,模型的泛化誤差就小,在未知數(shù)據(jù)上的準(zhǔn)確率就高。

偏差大 偏差小
方差大 模型不適合這個(gè)數(shù)據(jù)
換模型
過擬合
模型很復(fù)雜
對某些數(shù)據(jù)集預(yù)測很準(zhǔn)確
對某些數(shù)據(jù)集預(yù)測很糟糕
方差小 欠擬合
模型相對簡單
預(yù)測很穩(wěn)定
但對所有的數(shù)據(jù)預(yù)測都不太準(zhǔn)確
泛化誤差小,我們的目標(biāo)

通常來說,方差和偏差有一個(gè)很大,泛化誤差都會(huì)很大。然而,方差和偏差是此消彼長的,不可能同時(shí)達(dá)到最小值。這個(gè)要怎么理解呢?來看看下面這張圖:

image

從圖上可以看出,模型復(fù)雜度大的時(shí)候,方差高,偏差低。偏差低,就是要求模型要預(yù)測得“準(zhǔn)”。模型就會(huì)更努力去學(xué)習(xí)更多信息,會(huì)具體于訓(xùn)練數(shù)據(jù),這會(huì)導(dǎo)致,模型在一部分?jǐn)?shù)據(jù)上表現(xiàn)很好,在另一部分?jǐn)?shù)據(jù)上表現(xiàn)卻很糟糕。模型泛化性差,在不同數(shù)據(jù)上表現(xiàn)不穩(wěn)定,所以方差就大。而要盡量學(xué)習(xí)訓(xùn)練集,模型的建立必然更多細(xì)節(jié),復(fù)雜程度必然上升。所以,復(fù)雜度高,方差高,總泛化誤差高。

相對的,復(fù)雜度低的時(shí)候,方差低,偏差高。方差低,要求模型預(yù)測得“穩(wěn)”,泛化性更強(qiáng),那對于模型來說,它就不需要對數(shù)據(jù)進(jìn)行一個(gè)太深的學(xué)習(xí),只需要建立一個(gè)比較簡單,判定比較寬泛的模型就可以了。結(jié)果就是,模型無法在某一類或者某一組數(shù)據(jù)上達(dá)成很高的準(zhǔn)確度,所以偏差就會(huì)大。所以,復(fù)雜度低,偏差高,總泛化誤差高。

我們調(diào)參的目標(biāo)是,達(dá)到方差和偏差的完美平衡!雖然方差和偏差不能同時(shí)達(dá)到最小值,但他們組成的泛化誤差卻可以有一個(gè)最低點(diǎn),而我們就是要尋找這個(gè)最低點(diǎn)。對復(fù)雜度大的模型,要降低方差,對相對簡單的模型,要降低偏差。隨機(jī)森林的基評估器都擁有較低的偏差和較高的方差,因?yàn)闆Q策樹本身是預(yù)測比較”準(zhǔn)“,比較容易過擬合的模型,裝袋法本身也要求基分類器的準(zhǔn)確率必須要有50%以上。所以以隨機(jī)森林為代表的裝袋法的訓(xùn)練過程旨在降低方差,即降低模型復(fù)雜度,所以隨機(jī)森林參數(shù)的默認(rèn)設(shè)定都是假設(shè)模型本身在泛化誤差最低點(diǎn)的右邊。

所以,我們在降低復(fù)雜度的時(shí)候,本質(zhì)其實(shí)是在降低隨機(jī)森林的方差,隨機(jī)森林所有的參數(shù),也都是朝著降低方差的目標(biāo)去。有了這一層理解,我們對復(fù)雜度和泛化誤差的理解就更上一層樓了,對于我們調(diào)參,也有了更大的幫助。

關(guān)于方差-偏差的更多內(nèi)容,大家可以參考周志華的《機(jī)器學(xué)習(xí)》。

image

4 實(shí)例:隨機(jī)森林在乳腺癌數(shù)據(jù)上的調(diào)參

在這節(jié)課中,我們了解了隨機(jī)森林,并且學(xué)習(xí)了機(jī)器學(xué)習(xí)中調(diào)參的基本思想,了解了方差和偏差如何受到隨機(jī)森林的參數(shù)們的影響。這一節(jié),我們就來使用我們剛才學(xué)的,基于方差和偏差的調(diào)參方法,在乳腺癌數(shù)據(jù)上進(jìn)行一次隨機(jī)森林的調(diào)參。乳腺癌數(shù)據(jù)是sklearn自帶的分類數(shù)據(jù)之一。

案例中,往往使用真實(shí)數(shù)據(jù),為什么我們要使用sklearn自帶的數(shù)據(jù)呢?因?yàn)檎鎸?shí)數(shù)據(jù)在隨機(jī)森林下的調(diào)參過程,往往非常緩慢。真實(shí)數(shù)據(jù)量大,維度高,在使用隨機(jī)森林之前需要一系列的處理,因此不太適合用來做直播中的案例演示。在本章,我為大家準(zhǔn)備了kaggle上下載的辨別手寫數(shù)字的數(shù)據(jù),有4W多條記錄700多個(gè)左右的特征,隨機(jī)森林在這個(gè)辨別手寫數(shù)字的數(shù)據(jù)上有非常好的表現(xiàn),其調(diào)參案例也是非常經(jīng)典,但是由于數(shù)據(jù)的維度太高,太過復(fù)雜,運(yùn)行一次完整的網(wǎng)格搜索需要四五個(gè)小時(shí),因此不太可能拿來給大家進(jìn)行演示。我們上周的案例中用的泰坦尼克號數(shù)據(jù),用來調(diào)參的話也是需要很長時(shí)間,因此我才選擇sklearn當(dāng)中自帶的,結(jié)構(gòu)相對清晰簡單的數(shù)據(jù)來為大家做這個(gè)案例。大家感興趣的話,可以進(jìn)群去下載數(shù)據(jù),也可以直接到kaggle上進(jìn)行下載,數(shù)據(jù)集名稱是Digit Recognizer(https://www.kaggle.com/c/digit-recognizer)。

那我們接下來,就用乳腺癌數(shù)據(jù),來看看我們的調(diào)參代碼。

  1. 導(dǎo)入需要的庫
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
  1. 導(dǎo)入數(shù)據(jù)集,探索數(shù)據(jù)
data = load_breast_cancer()
data

data.data.shape

data.target

可以看到,乳腺癌數(shù)據(jù)集有569條記錄,30個(gè)特征,單看維度雖然不算太高,但是樣本量非常少。過擬合的情況可能存在。

  1. 進(jìn)行一次簡單的建模,看看模型本身在數(shù)據(jù)集上的效果
rfc = RandomForestClassifier(n_estimators=100,random_state=90)
score_pre = cross_val_score(rfc,data.data,data.target,cv=10).mean()
score_pre

這里可以看到,隨機(jī)森林在乳腺癌數(shù)據(jù)上的表現(xiàn)本就還不錯(cuò),在現(xiàn)實(shí)數(shù)據(jù)集上,基本上不可能什么都不調(diào)就看到95%以上的準(zhǔn)確率

  1. 隨機(jī)森林調(diào)整的第一步:無論如何先來調(diào)n_estimators

在這里我們選擇學(xué)習(xí)曲線,可以使用網(wǎng)格搜索嗎?可以,但是只有學(xué)習(xí)曲線,才能看見趨勢
我個(gè)人的傾向是,要看見n_estimators在什么取值開始變得平穩(wěn),是否一直推動(dòng)模型整體準(zhǔn)確率的上升等信息
第一次的學(xué)習(xí)曲線,可以先用來幫助我們劃定范圍,我們?nèi)∶渴畟€(gè)數(shù)作為一個(gè)階段,來觀察n_estimators的變化如何引起模型整體準(zhǔn)確率的變化

#####【TIME WARNING: 30 seconds】#####

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

#list.index([object])
#返回這個(gè)object在列表list中的索引
  1. 在確定好的范圍內(nèi),進(jìn)一步細(xì)化學(xué)習(xí)曲線
scorel = []
for i in range(35,45):
    rfc = RandomForestClassifier(n_estimators=i,
                                 n_jobs=-1,
                                 random_state=90)
    score = cross_val_score(rfc,data.data,data.target,cv=10).mean()
    scorel.append(score)
print(max(scorel),([*range(35,45)][scorel.index(max(scorel))]))
plt.figure(figsize=[20,5])
plt.plot(range(35,45),scorel)
plt.show()

調(diào)整n_estimators的效果顯著,模型的準(zhǔn)確率立刻上升了0.005。接下來就進(jìn)入網(wǎng)格搜索,我們將使用網(wǎng)格搜索對參數(shù)一個(gè)個(gè)進(jìn)行調(diào)整。為什么我們不同時(shí)調(diào)整多個(gè)參數(shù)呢?原因有兩個(gè):
1)同時(shí)調(diào)整多個(gè)參數(shù)會(huì)運(yùn)行非常緩慢,在課堂上我們沒有這么多的時(shí)間。
2)同時(shí)調(diào)整多個(gè)參數(shù),會(huì)讓我們無法理解參數(shù)的組合是怎么得來的,所以即便網(wǎng)格搜索調(diào)出來的結(jié)果不好,我們也不知道從哪里去改。
在這里,為了使用復(fù)雜度-泛化誤差方法(方差-偏差方法),我們對參數(shù)進(jìn)行一個(gè)個(gè)地調(diào)整。

  1. 為網(wǎng)格搜索做準(zhǔn)備,書寫網(wǎng)格搜索的參數(shù)

有一些參數(shù)是沒有參照的,很難說清一個(gè)范圍,這種情況下我們使用學(xué)習(xí)曲線,看趨勢,從曲線跑出的結(jié)果中選取一個(gè)更小的區(qū)間,再跑曲線

param_grid = {'n_estimators':np.arange(0, 200, 10)}
param_grid = {'max_depth':np.arange(1, 20, 1)}
param_grid = {'max_leaf_nodes':np.arange(25,50,1)}

對于大型數(shù)據(jù)集,可以嘗試從1000來構(gòu)建,先輸入1000,每100個(gè)葉子一個(gè)區(qū)間,再逐漸縮小范圍

有一些參數(shù)是可以找到一個(gè)范圍的,或者說我們知道他們的取值和隨著他們的取值,模型的整體準(zhǔn)確率會(huì)如何變化,這樣的參數(shù)我們就可以直接跑網(wǎng)格搜索

param_grid = {'criterion':['gini', 'entropy']}
param_grid = {'min_samples_split':np.arange(2, 2+20, 1)}
param_grid = {'min_samples_leaf':np.arange(1, 1+10, 1)}
param_grid = {'max_features':np.arange(5,30,1)}

  1. 開始按照參數(shù)對模型整體準(zhǔn)確率的影響程度進(jìn)行調(diào)參,首先調(diào)整max_depth
    一般根據(jù)數(shù)據(jù)的大小來進(jìn)行一個(gè)試探,乳腺癌數(shù)據(jù)很小,所以可以采用110,或者120這樣的試探
    但對于像digit recognition那樣的大型數(shù)據(jù)來說,我們應(yīng)該嘗試30~50層深度(或許還不足夠
    更應(yīng)該畫出學(xué)習(xí)曲線,來觀察深度對模型的影響
#調(diào)整max_depth

param_grid = {'max_depth':np.arange(1, 20, 1)}

rfc = RandomForestClassifier(n_estimators=39
                             ,random_state=90
                            )
GS = GridSearchCV(rfc,param_grid,cv=10)
GS.fit(data.data,data.target)

GS.best_params_

GS.best_score_

在這里,我們注意到,將max_depth設(shè)置為有限之后,模型的準(zhǔn)確率下降了。限制max_depth,是讓模型變得簡單,把模型向左推,而模型整體的準(zhǔn)確率下降了,即整體的泛化誤差上升了,這說明模型現(xiàn)在位于圖像左邊,即泛化誤差最低點(diǎn)的左邊(偏差為主導(dǎo)的一邊)。通常來說,隨機(jī)森林應(yīng)該在泛化誤差最低點(diǎn)的右邊,樹模型應(yīng)該傾向于過擬合,而不是擬合不足。這和數(shù)據(jù)集本身有關(guān),但也有可能是我們調(diào)整的n_estimators對于數(shù)據(jù)集來說太大,因此將模型拉到泛化誤差最低點(diǎn)去了。然而,既然我們追求最低泛化誤差,那我們就保留這個(gè)n_estimators,除非有其他的因素,可以幫助我們達(dá)到更高的準(zhǔn)確率。

當(dāng)模型位于圖像左邊時(shí),我們需要的是增加模型復(fù)雜度(增加方差,減少偏差)的選項(xiàng),因此max_depth應(yīng)該盡量大,min_samples_leaf和min_samples_split都應(yīng)該盡量小。這幾乎是在說明,除了max_features,我們沒有任何參數(shù)可以調(diào)整了,因?yàn)閙ax_depth,min_samples_leaf和min_samples_split是剪枝參數(shù),是減小復(fù)雜度的參數(shù)。在這里,我們可以預(yù)言,我們已經(jīng)非常接近模型的上限,模型很可能沒有辦法再進(jìn)步了。

那我們這就來調(diào)整一下max_features,看看模型如何變化。

  1. 調(diào)整max_features
    max_features是唯一一個(gè)即能夠?qū)⒛P屯螅ǖ头讲罡咂睿┩?,也能夠?qū)⒛P屯遥ǜ叻讲畹推睿┩频膮?shù)。我們需要根據(jù)調(diào)參前,模型所在的位置(在泛化誤差最低點(diǎn)的左邊還是右邊)來決定我們要將max_features往哪邊調(diào)?,F(xiàn)在模型位于圖像左側(cè),我們需要的是更高的復(fù)雜度,因此我們應(yīng)該把max_features往更大的方向調(diào)整,可用的特征越多,模型才會(huì)越復(fù)雜。max_features的默認(rèn)最小值是sqrt(n_features),因此我們使用這個(gè)值作為調(diào)參范圍的最小值。
    param_grid = {'max_features':np.arange(5,30,1)}
#調(diào)整max_features
rfc = RandomForestClassifier(n_estimators=39
                             ,random_state=90
                            )
GS = GridSearchCV(rfc,param_grid,cv=10)
GS.fit(data.data,data.target)

GS.best_params_

GS.best_score_

網(wǎng)格搜索返回了max_features的最小值,可見max_features升高之后,模型的準(zhǔn)確率降低了。這說明,我們把模型往右推,模型的泛化誤差增加了。前面用max_depth往左推,現(xiàn)在用max_features往右推,泛化誤差都增加,這說明模型本身已經(jīng)處于泛化誤差最低點(diǎn),已經(jīng)達(dá)到了模型的預(yù)測上限,沒有參數(shù)可以左右的部分了。剩下的那些誤差,是噪聲決定的,已經(jīng)沒有方差和偏差的舞臺了。

如果是現(xiàn)實(shí)案例,我們到這一步其實(shí)就可以停下了,因?yàn)閺?fù)雜度和泛化誤差的關(guān)系已經(jīng)告訴我們,模型不能再進(jìn)步了。調(diào)參和訓(xùn)練模型都需要很長的時(shí)間,明知道模型不能進(jìn)步了還繼續(xù)調(diào)整,不是一個(gè)有效率的做法。如果我們希望模型更進(jìn)一步,我們會(huì)選擇更換算法,或者更換做數(shù)據(jù)預(yù)處理的方式。但是在課上,出于練習(xí)和探索的目的,我們繼續(xù)調(diào)整我們的參數(shù),讓大家觀察一下模型的變化,看看我們預(yù)測得是否正確。

依然按照參數(shù)對模型整體準(zhǔn)確率的影響程度進(jìn)行調(diào)參。

  1. 調(diào)整min_samples_leaf
    對于min_samples_split和min_samples_leaf,一般是從他們的最小值開始向上增加10或20
    面對高維度高樣本量數(shù)據(jù),如果不放心,也可以直接+50,對于大型數(shù)據(jù),可能需要200~300的范圍
    如果調(diào)整的時(shí)候發(fā)現(xiàn)準(zhǔn)確率無論如何都上不來,那可以放心大膽調(diào)一個(gè)很大的數(shù)據(jù),大力限制模型的復(fù)雜度
#調(diào)整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)

GS.best_params_

GS.best_score_

可以看見,網(wǎng)格搜索返回了min_samples_leaf的最小值,并且模型整體的準(zhǔn)確率還降低了,這和max_depth的情況一致,參數(shù)把模型向左推,但是模型的泛化誤差上升了。在這種情況下,我們顯然是不要把這個(gè)參數(shù)設(shè)置起來的,就讓它默認(rèn)就好了。

  1. 不懈努力,繼續(xù)嘗試min_samples_split
#調(diào)整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)

GS.best_params_

GS.best_score_

和min_samples_leaf一樣的結(jié)果,返回最小值并且模型整體的準(zhǔn)確率降低了。

  1. 最后嘗試一下criterion
#調(diào)整Criterion

param_grid = {'criterion':['gini', 'entropy']}

rfc = RandomForestClassifier(n_estimators=39
                             ,random_state=90
                            )
GS = GridSearchCV(rfc,param_grid,cv=10)
GS.fit(data.data,data.target)

GS.best_params_

GS.best_score_
  1. 調(diào)整完畢,總結(jié)出模型的最佳參數(shù)
rfc = RandomForestClassifier(n_estimators=39,random_state=90)
score = cross_val_score(rfc,data.data,data.target,cv=10).mean()
score

score - score_pre

在整個(gè)調(diào)參過程之中,我們首先調(diào)整了n_estimators(無論如何都請先走這一步),然后調(diào)整max_depth,通過max_depth產(chǎn)生的結(jié)果,來判斷模型位于復(fù)雜度-泛化誤差圖像的哪一邊,從而選擇我們應(yīng)該調(diào)整的參數(shù)和調(diào)參的方向。如果感到困惑,也可以畫很多學(xué)習(xí)曲線來觀察參數(shù)會(huì)如何影響我們的準(zhǔn)確率,選取學(xué)習(xí)曲線中單調(diào)的部分來放大研究(如同我們對n_estimators做的)。學(xué)習(xí)曲線的拐點(diǎn)也許就是我們一直在追求的,最佳復(fù)雜度對應(yīng)的泛化誤差最低點(diǎn)(也是方差和偏差的平衡點(diǎn))。

網(wǎng)格搜索也可以一起調(diào)整多個(gè)參數(shù),大家只要有時(shí)間,可以自己跑一下,看看網(wǎng)格搜索會(huì)給我們怎樣的結(jié)果,有時(shí)候,它的結(jié)果比我們的好,有時(shí)候,我們手動(dòng)調(diào)整的結(jié)果會(huì)比較好。當(dāng)然了,我們的乳腺癌數(shù)據(jù)集非常完美,所以只需要調(diào)n_estimators一個(gè)參數(shù)就達(dá)到了隨機(jī)森林在這個(gè)數(shù)據(jù)集上表現(xiàn)得極限。在我們上周使用的泰坦尼克號案例的數(shù)據(jù)中,我們使用同樣的方法調(diào)出了如下的參數(shù)組合。

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
                             )

基于泰坦尼克號數(shù)據(jù)調(diào)整出來的參數(shù),數(shù)據(jù)的處理過程請參考上一期的完整視頻。這個(gè)組合的準(zhǔn)確率達(dá)到了83.915%,比單棵決策樹提升了大約7%,比調(diào)參前的隨機(jī)森林提升了2.02%,這對于調(diào)參來說其實(shí)是一個(gè)非常巨大的進(jìn)步。不過,泰坦尼克號數(shù)據(jù)的運(yùn)行緩慢,大家量力量時(shí)間而行,可以試試看用復(fù)雜度-泛化誤差方法(方差-偏差方法)來解讀一下這個(gè)調(diào)參結(jié)果和過程。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容