2020-05-19 第十章 決策樹與隨機森林(python)

01 決策樹節(jié)點字段的選擇

模型介紹

決策樹屬于經(jīng)典的十大數(shù)據(jù)挖掘算法之一,是一種類似于流程圖的樹結(jié)構(gòu),其規(guī)則就是IF...THEN...的思想,可以用于數(shù)值型因變量的預(yù)測和離散型因變量的分類。
該算法簡單直觀、通俗易懂,不需要研究者掌握任何領(lǐng)域知識或復(fù)雜的數(shù)學(xué)推理,而且算法的結(jié)果輸出具有很強的解釋性。

image.png

圖中的決策樹呈現(xiàn)自頂向下的生長過程,深色的橢圓表示樹的根節(jié)點;淺色的橢圓表示樹的中間節(jié)點;方框則表示樹的葉節(jié)點。
對于所有的非葉節(jié)點來說,都是用來表示條件判斷,而葉節(jié)點則存儲最終的分類結(jié)果,例如中年分支下的葉節(jié)點(4,0)表示4位客戶購買,0位客戶不購買。

信息增益

熵原本是物理學(xué)中的一個定義,后來香農(nóng)將其引申到了信息論領(lǐng)域,用來表示信息量的大小。信息量越大(分類越不“純凈”),對應(yīng)的熵值就越大,反之亦然。信息熵的計算公式如下:

image.png

在實際應(yīng)用中,會將概率p_k的值用經(jīng)驗概率替換,所以經(jīng)驗信息熵可以表示為:
image.png

舉例:以產(chǎn)品是否被購買為例,假設(shè)數(shù)據(jù)集一共包含14個樣本,其中購買的用戶有9個,沒有購買的用戶有5個,所以對于是否購買這個事件來說,它的經(jīng)驗信息熵為:
image.png

條件熵
image.png

其中,P(A_i)表示 A事件的第i種值對應(yīng)的概率;H(D_k|A_i)為已知A_i的情況下,D事件為k值的條件熵,其對應(yīng)的計算公式為P(D_k|A_i)log_2P(D_k|A_i);|D_i|表示A_i的頻數(shù),|D_i|/|D|表示A_i在所有樣本中的頻率;|D_ik|表示A_i下D事件為k值的頻數(shù),|D_ik|/|D_i|表示所有A_i中,D事件為k值的頻率。
Gain_A(D)=H(D)?H(D|A):
對于已知的事件A來說,事件D的信息增益就是D的信息熵與A事件下D的條件熵之差,事件A對事件D的影響越大,條件熵H(D|A)就會越?。ㄔ谑录嗀的影響下,事件D被劃分得越“純凈”),體現(xiàn)在信息增益上就是差值越大,進而說明事件D的信息熵下降得越多。
所以,在根節(jié)點或中間節(jié)點的變量選擇過程中,就是挑選出各自變量下因變量的信息增益最大的。
image.png

決策樹中的ID3算法使用信息增益指標(biāo)實現(xiàn)根節(jié)點或中間節(jié)點的字段選擇,但是該指標(biāo)存在一個非常明顯的缺點,即信息增益會偏向于取值較多的字段。
為了克服信息增益指標(biāo)的缺點,提出了信息增益率的概念,它的思想很簡單,就是在信息增益的基礎(chǔ)上進行相應(yīng)的懲罰。信息增益率的公式可以表示為:
image.png

其中,H_A為事件A的信息熵。事件A的取值越多, Gain_A(D)可能越大,但同時H_A也會越大,這樣以商的形式就實現(xiàn)了Gain_A(D)的懲罰。
image.png

image.png

從上面的計算結(jié)果可知,Age變量的信息增益率仍然是最大的,所以在根節(jié)點處仍然選擇Age變量進行判斷和分支。

基尼指數(shù)

決策樹中的C4.5算法使用信息增益率指標(biāo)實現(xiàn)根節(jié)點或中間節(jié)點的字段選擇,但該算法與ID3算法一致,都只能針對離散型因變量進行分類,對于連續(xù)型的因變量就顯得束手無策了。
為了能夠讓決策樹預(yù)測連續(xù)型的因變量,Breiman等人在1984年提出了CART算法,該算法也稱為分類回歸樹,它所使用的字段選擇指標(biāo)是基尼指數(shù)。

image.png

image.png

假設(shè)表中的Edu表示客戶的受教育水平,Credit為客戶在第三方的信用記錄,Loan為因變量,表示銀行是否對其發(fā)放貸款。根據(jù)基尼指數(shù)的公式,可以計算Loan變量的基尼指數(shù)值:
image.png

條件基尼指數(shù)
image.png

其中,P(A_i)表示 A變量在某個二元劃分下第i組的概率,其對應(yīng)的經(jīng)驗概率為|D_i|/|D|,即A變量中第i組的樣本量與總樣本量的商;Gini(D_k|A_i)表示在已知分組A_i的情況下,變量D取第k種值的條件基尼指數(shù),其中|D_ik|/|D_i|表示分組A_i內(nèi)變量D取第k種值的頻率。
image.png

基尼指數(shù)增益

與信息增益類似,還需要考慮自變量對因變量的影響程度,即因變量的基尼指數(shù)下降速度的快慢,下降得越快,自變量對因變量的影響就越強。下降速度的快慢可用下方式子衡量:


image.png

決策樹模型的Python函數(shù)

DecisionTreeClassifier(criterion='gini', splitter='best', 
                                    max_depth=None,min_samples_split=2, 
                                    min_samples_leaf=1,
                                    min_weight_fraction_leaf=0.0,max_features=None,            
                                    random_state=None, max_leaf_nodes=None,                                
                                    min_impurity_decrease=0.0, min_impurity_split=None, 
                                    class_weight=None, presort=False)

criterion:用于指定選擇節(jié)點字段的評價指標(biāo),對于分類決策樹,默認(rèn)為'gini',表示采用基尼指數(shù)選擇節(jié)點的最佳分割字段;對于回歸決策樹,默認(rèn)為'mse',表示使用均方誤差選擇節(jié)點的最佳分割字段
splitter:用于指定節(jié)點中的分割點選擇方法,默認(rèn)為'best',表示從所有的分割點中選擇最佳分割點;如果指定為'random',則表示隨機選擇分割點
max_depth:用于指定決策樹的最大深度,默認(rèn)為None,表示樹的生長過程中對深度不做任何限制
min_samples_split:用于指定根節(jié)點或中間節(jié)點能夠繼續(xù)分割的最小樣本量, 默認(rèn)為2
min_samples_leaf:用于指定葉節(jié)點的最小樣本量,默認(rèn)為1
min_weight_fraction_leaf:用于指定葉節(jié)點最小的樣本權(quán)重,默認(rèn)為None,表示不考慮葉節(jié)點的樣本權(quán)值
max_features:用于指定決策樹包含的最多分割字段數(shù),默認(rèn)為None,表示分割時使用所有的字段,與指定'auto'效果一致;如果為具體的整數(shù),則考慮使用對應(yīng)的分割字段數(shù);如果為0~1的浮點數(shù),則考慮對應(yīng)百分比的字段個數(shù);如果為'sqrt',則表示最多考慮√P個字段;如果為'log2',則表示最多使用log_2P個字段
random_state:用于指定隨機數(shù)生成器的種子,默認(rèn)為None,表示使用默認(rèn)的隨機數(shù)生成器
max_leaf_nodes:用于指定最大的葉節(jié)點個數(shù),默認(rèn)為None,表示對葉節(jié)點個數(shù)不做任何限制
min_impurity_decrease:用于指定節(jié)點是否繼續(xù)分割的最小不純度值,默認(rèn)為0
min_impurity_split:同參數(shù)min_impurity_decrease含義一致,該參數(shù)已在0.21版本剔除
class_weight:用于指定因變量中類別之間的權(quán)重,默認(rèn)為None,表示每個類別的權(quán)重都相等;如果為balanced,則表示類別權(quán)重與原始樣本中類別的比例成反比;還可以通過字典傳遞類別之間的權(quán)重差異,其形式為{class_label:weight}
presort:bool類型參數(shù),是否對數(shù)據(jù)進行預(yù)排序,默認(rèn)為False。如果數(shù)據(jù)集的樣本量比較小,設(shè)置為True可以提高模型的執(zhí)行速度;如果數(shù)據(jù)集的樣本量比較大,則不易設(shè)置為True

02 決策樹的剪枝技術(shù)

誤差降低剪枝法

image.png
  • 將決策樹的某個非葉子節(jié)點作為剪枝的候選對象(如圖中的x_3處節(jié)點),如果將其子孫節(jié)點刪除(對應(yīng)的兩個葉節(jié)點),則x_3處的節(jié)點就變成了葉節(jié)點。
  • 利用投票原則,將此處葉節(jié)點中頻數(shù)最高的類別用作分類標(biāo)準(zhǔn)(如圖中剪枝后該葉節(jié)點屬于類A)。
  • 利用剪枝后的新樹在測試數(shù)據(jù)集上進行預(yù)測,然后對比新樹與老樹在測試集上的誤判樣本量,如果新樹的誤判樣本量低于老樹的誤判樣本量,則將x_3處的中間節(jié)點替換為葉節(jié)點,否則不進行剪枝。
  • 重復(fù)前面的三步,直到新的決策樹能夠最大限度地提高測試數(shù)據(jù)集上的預(yù)測準(zhǔn)確率。

悲觀剪枝法

image.png

其中,e^′(T)表示剪枝后中間節(jié)點T被換成葉節(jié)點的誤判率;e^′(T_t)表示中間節(jié)點T剪枝前其對應(yīng)的所有葉節(jié)點的誤判率;E(T)為中間節(jié)點T處的誤判個數(shù);E(t_i)為節(jié)點T下的所有葉節(jié)點誤判個數(shù);L表示中間節(jié)點T對應(yīng)的所有葉節(jié)點個數(shù);N表示中間節(jié)點T的樣本個數(shù);N_i表示各葉節(jié)點中的樣本個數(shù),其實∑_i^L N_{i=1}=N。
image.png

剪枝標(biāo)準(zhǔn)

對比剪枝前后葉節(jié)點誤判率的標(biāo)準(zhǔn)就是,如果剪枝后葉節(jié)點的誤判率期望在剪枝前葉節(jié)點誤判率期望的一個標(biāo)準(zhǔn)差內(nèi),則認(rèn)為剪枝是合理的,否則不能剪枝。

在決策樹圖中,假設(shè)以T_2節(jié)點為例,剪枝前對應(yīng)了3個葉節(jié)點,誤判個數(shù)分別為3,2,0;如果將其所有葉節(jié)點都剪掉,T_2便成為了T_1的葉節(jié)點,誤判樣本數(shù)為7。根據(jù)計算公式,可以得到:


image.png

代價復(fù)雜度剪枝法

從字面理解,該剪枝方法涉及兩則信息,一則是代價,是指將中間節(jié)點替換為葉節(jié)點后誤判率會上升;另一則是復(fù)雜度,是指剪枝后葉節(jié)點的個數(shù)減少,進而使模型的復(fù)雜度下降。為了平衡上升的誤判率與下降的復(fù)雜度,需要加入一個系數(shù)a,故可以將代價復(fù)雜度剪枝法的目標(biāo)函數(shù)寫成:

image.png

其中,C(T)=∑_{i=1}^L N_i×H(i);i表示節(jié)點T下第i個葉節(jié)點;N_i為第i個葉節(jié)點的樣本量;H(i)為第i個葉節(jié)點的信息熵;|N_leaf|為節(jié)點T對應(yīng)的所有葉節(jié)點個數(shù);a就是調(diào)節(jié)參數(shù)。問題是參數(shù)a該如何計算呢?
節(jié)點T剪枝前的目標(biāo)函數(shù)值為:
image.png

節(jié)點T剪枝后的目標(biāo)函數(shù)值為:
image.png

C_α(T)_before=C_α(T)_after,得到:
image.png

image.png

剪枝過程
(1)對于一棵充分生長的樹,不妨含有4個非葉子節(jié)點和5個葉子節(jié)點,根據(jù)計算a值的公式,可以得到所有非葉子節(jié)點對應(yīng)的a值。
(2)挑選出最小的a值,不妨為α_3,然后對T_3進行剪枝,使其成為葉子節(jié)點,便得到一棵新樹。
(3)接下來重新計算剩余非葉子節(jié)點所對應(yīng)的a值。
(4)不斷重復(fù)(2)和(3),直到?jīng)Q策樹被剪枝成根節(jié)點,最終得到N棵新樹。
(5)將測試數(shù)據(jù)集運用到N棵新樹中,再從中挑選出誤判率最低的樹作為最佳的決策樹。

03 隨機森林的思想解讀

思想解讀

image.png
  • 利用Bootstrap抽樣法,從原始數(shù)據(jù)集中生成k個數(shù)據(jù)集,并且每個數(shù)據(jù)集都含有N個觀測和P個自變量。
  • 針對每一個數(shù)據(jù)集,構(gòu)造一棵CART決策樹,在構(gòu)建子樹的過程中,并沒有將所有自變量用作節(jié)點字段的選擇,而是隨機選擇p個字段。
  • 讓每一棵決策樹盡可能地充分生長,使得樹中的每個節(jié)點盡可能“純凈”,即隨機森林中的每一棵子樹都不需要剪枝。
  • 針對k棵CART樹的隨機森林,對分類問題利用投票法,將最高得票的類別用于最終的判斷結(jié)果;對回歸問題利用均值法,將其用作預(yù)測樣本的最終結(jié)果。

隨機森林的Python函數(shù)

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=1, random_state=None, 
                    verbose=0, warm_start=False, class_weight=None)

n_estimators:用于指定隨機森林所包含的決策樹個數(shù)
criterion:用于指定每棵決策樹節(jié)點的分割字段所使用的度量標(biāo)準(zhǔn),用于分類的隨機森林,默認(rèn)的criterion值為'gini';用于回歸的隨機森林,默認(rèn)的criterion值為'mse'
max_depth:用于指定每棵決策樹的最大深度,默認(rèn)不限制樹的生長深度
min_samples_split:用于指定每棵決策樹根節(jié)點或中間節(jié)點能夠繼續(xù)分割的最小樣本量, 默認(rèn)為2
min_samples_leaf:用于指定每棵決策樹葉節(jié)點的最小樣本量,默認(rèn)為1
min_weight_fraction_leaf:用于指定每棵決策樹葉節(jié)點最小的樣本權(quán)重,默認(rèn)為None,表示不考慮葉節(jié)點的樣本權(quán)值
max_features:用于指定每棵決策樹包含的最多分割字段數(shù),默認(rèn)為None,表示分割時使用所有的字段
max_leaf_nodes:用于指定每棵決策樹最大的葉節(jié)點個數(shù),默認(rèn)為None,表示對葉節(jié)點個數(shù)不做任何限制
min_impurity_decrease:用于指定每棵決策樹的節(jié)點是否繼續(xù)分割的最小不純度值,默認(rèn)為0
bootstrap:bool類型參數(shù),是否對原始數(shù)據(jù)集進行bootstrap抽樣,用于子樹的構(gòu)建,默認(rèn)為True
oob_score:bool類型參數(shù),是否使用包外樣本計算泛化誤差,默認(rèn)為False,包外樣本是指每次bootstrap抽樣時沒有被抽中的樣本
n_jobs:用于指定計算隨機森林算法的CPU個數(shù),默認(rèn)為1
random_state:用于指定隨機數(shù)生成器的種子,默認(rèn)為None,表示使用默認(rèn)的隨機數(shù)生成器
verbose:用于指定隨機森林計算過程中是否輸出日志信息,默認(rèn)為0,表示不輸出
warm_start:bool類型參數(shù),是否基于上一次的訓(xùn)練結(jié)果進行本次的運算,默認(rèn)為False
class_weight:用于指定因變量中類別之間的權(quán)重,默認(rèn)為None,表示每個類別的權(quán)重都相等

04 決策樹與隨機森林的應(yīng)用實戰(zhàn)

Titanic幸存分類--決策樹

# 導(dǎo)入第三方模塊
import pandas as pd
# 讀入數(shù)據(jù)
Titanic = pd.read_csv('./Titanic.csv')
Titanic.head()

# 刪除無意義的變量,并檢查剩余自字是否含有缺失值
Titanic.drop(['PassengerId','Name','Ticket','Cabin'], axis = 1, inplace = True)
Titanic.isnull().sum(axis = 0)

# 對Sex分組,用各組乘客的平均年齡填充各組中的缺失年齡
fillna_Titanic = []
for i in Titanic.Sex.unique():
    update = Titanic.loc[Titanic.Sex == i,].fillna(value = {'Age': Titanic.Age[Titanic.Sex == i].mean()}, inplace = False)
    fillna_Titanic.append(update)
Titanic = pd.concat(fillna_Titanic)
# 使用Embarked變量的眾數(shù)填充缺失值
Titanic.fillna(value = {'Embarked':Titanic.Embarked.mode()[0]}, inplace=True)
Titanic.head()

# 將數(shù)值型的Pclass轉(zhuǎn)換為類別型,否則無法對其啞變量處理
Titanic.Pclass = Titanic.Pclass.astype('category')
# 啞變量處理
dummy = pd.get_dummies(Titanic[['Sex','Embarked','Pclass']])
# 水平合并Titanic數(shù)據(jù)集和啞變量的數(shù)據(jù)集
Titanic = pd.concat([Titanic,dummy], axis = 1)
# 刪除原始的Sex、Embarked和Pclass變量
Titanic.drop(['Sex','Embarked','Pclass'], inplace=True, axis = 1)
Titanic.head()

讀入數(shù)據(jù)清洗結(jié)果:

In [2]: # 導(dǎo)入第三方模塊
   ...: import pandas as pd
   ...: # 讀入數(shù)據(jù)
   ...: Titanic = pd.read_csv('./Titanic.csv')
   ...: Titanic.head()
Out[2]:
   PassengerId  Survived  Pclass  ...     Fare Cabin  Embarked
0            1         0       3  ...   7.2500   NaN         S
1            2         1       1  ...  71.2833   C85         C
2            3         1       3  ...   7.9250   NaN         S
3            4         1       1  ...  53.1000  C123         S
4            5         0       3  ...   8.0500   NaN         S

[5 rows x 12 columns]

In [3]: # 刪除無意義的變量,并檢查剩余自字是否含有缺失值
   ...: Titanic.drop(['PassengerId','Name','Ticket','Cabin'], axis = 1, inplace
   ...: = True)
   ...: Titanic.isnull().sum(axis = 0)
   ...:
Out[3]:
Survived      0
Pclass        0
Sex           0
Age         177
SibSp         0
Parch         0
Fare          0
Embarked      2
dtype: int64

In [4]: # 對Sex分組,用各組乘客的平均年齡填充各組中的缺失年齡
   ...: fillna_Titanic = []
   ...: for i in Titanic.Sex.unique():
   ...:     update = Titanic.loc[Titanic.Sex == i,].fillna(value = {'Age': Titan
   ...: ic.Age[Titanic.Sex == i].mean()}, inplace = False)
   ...:     fillna_Titanic.append(update)
   ...: Titanic = pd.concat(fillna_Titanic)
   ...: # 使用Embarked變量的眾數(shù)填充缺失值
   ...: Titanic.fillna(value = {'Embarked':Titanic.Embarked.mode()[0]}, inplace=
   ...: True)
   ...: Titanic.head()
Out[4]:
   Survived  Pclass   Sex        Age  SibSp  Parch     Fare Embarked
0         0       3  male  22.000000      1      0   7.2500        S
4         0       3  male  35.000000      0      0   8.0500        S
5         0       3  male  30.726645      0      0   8.4583        Q
6         0       1  male  54.000000      0      0  51.8625        S
7         0       3  male   2.000000      3      1  21.0750        S

In [5]: # 將數(shù)值型的Pclass轉(zhuǎn)換為類別型,否則無法對其啞變量處理
   ...: Titanic.Pclass = Titanic.Pclass.astype('category')
   ...: # 啞變量處理
   ...: dummy = pd.get_dummies(Titanic[['Sex','Embarked','Pclass']])
   ...: # 水平合并Titanic數(shù)據(jù)集和啞變量的數(shù)據(jù)集
   ...: Titanic = pd.concat([Titanic,dummy], axis = 1)
   ...: # 刪除原始的Sex、Embarked和Pclass變量
   ...: Titanic.drop(['Sex','Embarked','Pclass'], inplace=True, axis = 1)
   ...: Titanic.head()
Out[5]:
   Survived        Age  SibSp  Parch  ...  Embarked_S  Pclass_1  Pclass_2  Pclass_3
0         0  22.000000      1      0  ...           1         0         0         1
4         0  35.000000      0      0  ...           1         0         0         1
5         0  30.726645      0      0  ...           0         0         0         1
6         0  54.000000      0      0  ...           1         1         0         0
7         0   2.000000      3      1  ...           1         0         0         1

[5 rows x 13 columns]
# 導(dǎo)入第三方包
from sklearn import model_selection
# 取出所有自變量名稱
predictors = Titanic.columns[1:]
# 將數(shù)據(jù)集拆分為訓(xùn)練集和測試集,且測試集的比例為25%
X_train, X_test, y_train, y_test = model_selection.train_test_split(Titanic[predictors], Titanic.Survived, 
  test_size = 0.25, random_state = 1234)
  
# 導(dǎo)入第三方模塊
from sklearn.model_selection import GridSearchCV
from sklearn import tree
# 預(yù)設(shè)各參數(shù)的不同選項值
max_depth = [2,3,4,5,6]
min_samples_split = [2,4,6,8]
min_samples_leaf = [2,4,8,10,12]
# 將各參數(shù)值以字典形式組織起來
parameters = {'max_depth':max_depth, 'min_samples_split':min_samples_split, 'min_samples_leaf':min_samples_leaf}
# 網(wǎng)格搜索法,測試不同的參數(shù)值
grid_dtcateg = GridSearchCV(estimator = tree.DecisionTreeClassifier(), param_grid = parameters, cv=10)
# 模型擬合
grid_dtcateg.fit(X_train, y_train)
# 返回最佳組合的參數(shù)值
grid_dtcateg.best_params_

# 導(dǎo)入第三方模塊
from sklearn import metrics
# 構(gòu)建分類決策樹
CART_Class = tree.DecisionTreeClassifier(max_depth=3, min_samples_leaf = 4, min_samples_split=2)
# 模型擬合
decision_tree = CART_Class.fit(X_train, y_train)
# 模型在測試集上的預(yù)測
pred = CART_Class.predict(X_test)
# 模型的準(zhǔn)確率
print('模型在測試集的預(yù)測準(zhǔn)確率:\n',metrics.accuracy_score(y_test, pred))

在ipython中的結(jié)果:

In [6]: # 導(dǎo)入第三方包
   ...: from sklearn import model_selection
   ...: # 取出所有自變量名稱
   ...: predictors = Titanic.columns[1:]
   ...: # 將數(shù)據(jù)集拆分為訓(xùn)練集和測試集,且測試集的比例為25%
   ...: X_train, X_test, y_train, y_test = model_selection.train_test_split(Tita
   ...: nic[predictors], Titanic.Survived,
   ...:   test_size = 0.25, random_state = 1234)

In [7]: # 導(dǎo)入第三方模塊
   ...: from sklearn.model_selection import GridSearchCV
   ...: from sklearn import tree
   ...: # 預(yù)設(shè)各參數(shù)的不同選項值
   ...: max_depth = [2,3,4,5,6]
   ...: min_samples_split = [2,4,6,8]
   ...: min_samples_leaf = [2,4,8,10,12]
   ...: # 將各參數(shù)值以字典形式組織起來
   ...: parameters = {'max_depth':max_depth, 'min_samples_split':min_samples_spl
   ...: it, 'min_samples_leaf':min_samples_leaf}
   ...: # 網(wǎng)格搜索法,測試不同的參數(shù)值
   ...: grid_dtcateg = GridSearchCV(estimator = tree.DecisionTreeClassifier(), p
   ...: aram_grid = parameters, cv=10)
   ...: # 模型擬合
   ...: grid_dtcateg.fit(X_train, y_train)
   ...: # 返回最佳組合的參數(shù)值
   ...: grid_dtcateg.best_params_
Out[7]: {'max_depth': 6, 'min_samples_leaf': 8, 'min_samples_split': 4}

In [8]: # 導(dǎo)入第三方模塊
   ...: from sklearn import metrics
   ...: # 構(gòu)建分類決策樹
   ...: CART_Class = tree.DecisionTreeClassifier(max_depth=3, min_samples_leaf =
   ...:  4, min_samples_split=2)
   ...: # 模型擬合
   ...: decision_tree = CART_Class.fit(X_train, y_train)
   ...: # 模型在測試集上的預(yù)測
   ...: pred = CART_Class.predict(X_test)
   ...: # 模型的準(zhǔn)確率
   ...: print('模型在測試集的預(yù)測準(zhǔn)確率:\n',metrics.accuracy_score(y_test, pred
   ...: ))
模型在測試集的預(yù)測準(zhǔn)確率:
 0.8295964125560538

繪圖:

# 導(dǎo)入第三方包
import matplotlib.pyplot as plt
y_score = CART_Class.predict_proba(X_test)[:,1]
fpr,tpr,threshold = metrics.roc_curve(y_test, y_score)
# 計算AUC的值
roc_auc = metrics.auc(fpr,tpr)

# 繪制面積圖
plt.stackplot(fpr, tpr, color='steelblue', alpha = 0.5, edgecolor = 'black')
# 添加邊際線
plt.plot(fpr, tpr, color='black', lw = 1)
# 添加對角線
plt.plot([0,1],[0,1], color = 'red', linestyle = '--')
# 添加文本信息
plt.text(0.5,0.3,'ROC curve (area = %0.2f)' % roc_auc)
# 添加x軸與y軸標(biāo)簽
plt.xlabel('1-Specificity')
plt.ylabel('Sensitivity')
# 顯示圖形
plt.show()  
Figure_1.png

Titanic幸存分類--隨機森林

需要在電腦中安裝Graphviz,在下面的鏈接中下載適合自己電腦的版本
https://graphviz.gitlab.io/download/
mac下的Graphviz安裝及使用參考:https://blog.csdn.net/qq_36847641/article/details/78224910
windows下Graphviz安裝及入門教程:https://www.cnblogs.com/onemorepoint/p/8310996.html

Titanic幸存分類--決策樹

# 需要在電腦中安裝Graphviz,在下面的鏈接中下載適合自己電腦的版本
# https://graphviz.gitlab.io/download/
# 然后將解壓文件中的bin設(shè)置到環(huán)境變量中
# 導(dǎo)入第三方模塊
from sklearn.tree import export_graphviz
from IPython.display import Image
import pydotplus
from io import StringIO
# 繪制決策樹
dot_data = StringIO()
export_graphviz(
    decision_tree,
    out_file=dot_data,  
    feature_names=predictors,
    class_names=['Unsurvived','Survived'],  
    # filled=True,
    rounded=True,  
    special_characters=True
)
# 決策樹展現(xiàn)
graph = pydotplus.graph_from_dot_data(dot_data.getvalue())
Image(graph.create_png()) 
image.png
# 導(dǎo)入第三方包
from sklearn import ensemble
# 構(gòu)建隨機森林
RF_class = ensemble.RandomForestClassifier(n_estimators=200, random_state=1234)
# 隨機森林的擬合
RF_class.fit(X_train, y_train)
# 模型在測試集上的預(yù)測
RFclass_pred = RF_class.predict(X_test)
# 模型的準(zhǔn)確率
print('模型在測試集的預(yù)測準(zhǔn)確率:\n',metrics.accuracy_score(y_test, RFclass_pred))


# 計算繪圖數(shù)據(jù)
y_score = RF_class.predict_proba(X_test)[:,1]
fpr,tpr,threshold = metrics.roc_curve(y_test, y_score)
roc_auc = metrics.auc(fpr,tpr)
# 繪圖
plt.stackplot(fpr, tpr, color='steelblue', alpha = 0.5, edgecolor = 'black')
plt.plot(fpr, tpr, color='black', lw = 1)
plt.plot([0,1],[0,1], color = 'red', linestyle = '--')
plt.text(0.5,0.3,'ROC curve (area = %0.2f)' % roc_auc)
plt.xlabel('1-Specificity')
plt.ylabel('Sensitivity')
plt.show()
Figure_1.png

構(gòu)建隨機森林

# 變量的重要性程度值
importance = RF_class.feature_importances_
# 構(gòu)建含序列用于繪圖
Impt_Series = pd.Series(importance, index = X_train.columns)
# 對序列排序繪圖
Impt_Series.sort_values(ascending = True).plot(kind='barh')
plt.show()
image.png
# 讀入數(shù)據(jù)
NHANES = pd.read_excel('./NHANES.xlsx')
NHANES.head()
print(NHANES.shape)

# 取出自變量名稱
predictors = NHANES.columns[:-1]
# 將數(shù)據(jù)集拆分為訓(xùn)練集和測試集
X_train, X_test, y_train, y_test = model_selection.train_test_split(NHANES[predictors], NHANES.CKD_epi_eGFR, 
                                                                    test_size = 0.25, random_state = 1234)
                                                                    
# 預(yù)設(shè)各參數(shù)的不同選項值
max_depth = [18,19,20,21,22]
min_samples_split = [2,4,6,8]
min_samples_leaf = [2,4,8]
parameters = {'max_depth':max_depth, 'min_samples_split':min_samples_split, 'min_samples_leaf':min_samples_leaf}
# 網(wǎng)格搜索法,測試不同的參數(shù)值
grid_dtreg = GridSearchCV(estimator = tree.DecisionTreeRegressor(), param_grid = parameters, cv=10)
# 模型擬合
grid_dtreg.fit(X_train, y_train)
# 返回最佳組合的參數(shù)值
grid_dtreg.best_params_


# 構(gòu)建用于回歸的決策樹
CART_Reg = tree.DecisionTreeRegressor(max_depth = 20, min_samples_leaf = 2, min_samples_split = 4)
# 回歸樹擬合
CART_Reg.fit(X_train, y_train)
# 模型在測試集上的預(yù)測
pred = CART_Reg.predict(X_test)
# 計算衡量模型好壞的MSE值
metrics.mean_squared_error(y_test, pred)


# 構(gòu)建用于回歸的隨機森林
RF = ensemble.RandomForestRegressor(n_estimators=200, random_state=1234)
# 隨機森林?jǐn)M合
RF.fit(X_train, y_train)
# 模型在測試集上的預(yù)測
RF_pred = RF.predict(X_test)
# 計算模型的MSE值
metrics.mean_squared_error(y_test, RF_pred)

# 構(gòu)建變量重要性的序列
importance = pd.Series(RF.feature_importances_, index = X_train.columns)
# 排序并繪圖
importance.sort_values().plot(kind='barh')
plt.show()
image.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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