1. 程式人生 > 實用技巧 >決策樹與隨機森林

決策樹與隨機森林

資訊熵

熵原本是物理學中的⼀個定義,後來⾹農將其引申到了資訊理論領域,⽤來表示資訊量的⼤⼩。
資訊量越⼤(分類越不“純淨”),對應的熵值就越⼤,反之亦然。

資訊增益率

決策樹中的ID3演算法使⽤資訊增益指標實現根節點或中間節點的欄位選擇,但是該指標存在⼀個⾮
常明顯的缺點,即資訊增益會偏向於取值較多的欄位。
為了克服資訊增益指標的缺點,提出了資訊增益率的概念,它的思想很簡單,就是在資訊增益的
基礎上進⾏相應的懲罰。

基尼指數

決策樹中的C4.5演算法使⽤資訊增益率指標實現根節點或中間節點的欄位選擇,但該演算法與ID3演算法⼀
致,都只能針對離散型因變數進⾏分類,對於連續型的因變數就顯得束⼿⽆策了。
為了能夠讓決策樹預測連續型的因變數,Breiman等⼈在1984年提出了CART演算法,該演算法也稱為分
類迴歸樹,它所使⽤的欄位選擇指標是基尼指數。

決策樹模型

DecisionTreeClassifier(criterion='gini', splitter='best',
max_depth=None,min_samples_split=2,
min_samples_leaf=1,max_leaf_nodes=None,
class_weight=None)

criterion:⽤於指定選擇節點欄位的評價指標,對於分類決策樹,預設為'gini',表示採⽤基尼指數選
擇節點的最佳分割欄位;對於迴歸決策樹,預設為'mse',表示使⽤均⽅誤差選擇節點的最佳分割欄位
splitter:⽤於指定節點中的分割點選擇⽅法,預設為'best',表示從所有的分割點中選擇最佳分割點;
如果指定為'random',則表示隨機選擇分割點
max_depth:⽤於指定決策樹的最⼤深度,預設為None,表示樹的⽣⻓過程中對深度不做任何限制
min_samples_split:⽤於指定根節點或中間節點能夠繼續分割的最⼩樣本量, 預設為2
min_samples_leaf:⽤於指定葉節點的最⼩樣本量,預設為1
max_leaf_nodes:⽤於指定最⼤的葉節點個數,預設為None,表示對葉節點個數不做任何限制
class_weight:⽤於指定因變數中類別之間的權重,預設為None,表示每個類別的權重都相等;如果
為balanced,則表示類別權重與原始樣本中類別的⽐例成反⽐;還可以通過字典傳遞類別之間的權重
差異,其形式為{class_label:weight}

隨機森林的思想

隨機森林建立了多個決策樹,並將它們合併在一起以獲得更準確和穩定的預測。
隨機森林的一大優勢在於它既可用於分類,也可用於迴歸問題,這兩類問題恰
好構成了當前的大多數機器學習系統所需要面對的。

隨機森林模型

RandomForestClassifier(n_estimators=10, criterion='gini', max_depth=None,
min_samples_split=2, min_samples_leaf=1,
max_leaf_nodes=None, bootstrap=True, class_weight=None)

n_estimators:⽤於指定隨機森林所包含的決策樹個數
criterion:⽤於指定每棵決策樹節點的分割欄位所使⽤的度量標準,⽤於分類的隨機森林,預設的
criterion值為'gini';⽤於迴歸的隨機森林,預設的criterion值為'mse'
max_depth:⽤於指定每棵決策樹的最⼤深度,預設不限制樹的⽣⻓深度
min_samples_split:⽤於指定每棵決策樹根節點或中間節點能夠繼續分割的最⼩樣本量, 預設為2
min_samples_leaf:⽤於指定每棵決策樹葉節點的最⼩樣本量,預設為1
max_leaf_nodes:⽤於指定每棵決策樹最⼤的葉節點個數,預設為None,表示對葉節點個數不做任
何限制
bootstrap:bool型別引數,是否對原始資料集進⾏bootstrap抽樣,⽤於⼦樹的構建,預設為True
class_weight:⽤於指定因變數中類別之間的權重,預設為None,表示每個類別的權重都相等

程式碼演示

# 匯入第三方模組
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn import model_selection
from sklearn import linear_model

# 讀⼊資料
Titanic = pd.read_csv(r'Titanic.csv')
# 刪除⽆意義的變數,並檢查剩餘變數是否含有缺失值
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變數的眾數填充缺失值
Titanic.fillna(value = {'Embarked':Titanic.Embarked.mode()[0]}, inplace=True)

# 將數值型的Pclass轉換為類別型,否則⽆法對其啞變數處理
Titanic.Pclass = Titanic.Pclass.astype('category')
# 啞變數處理
dummy = pd.get_dummies(Titanic[['Sex','Embarked','Pclass']])
# ⽔平合併Titanic資料集和啞變數的資料集
Titanic = pd.concat([Titanic,dummy], axis = 1)
# 刪除原始的Sex、Embarked和Pclass變數
Titanic.drop(['Sex','Embarked','Pclass'], inplace=True, axis = 1)
# 取出所有⾃變數名稱
predictors = Titanic.columns[1:]

# 將資料集拆分為訓練集和測試集,且測試集的⽐例為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)

# 匯入第三方模組
from sklearn.model_selection import GridSearchCV
from sklearn import tree
# 預設各引數的不同選項值
max_depth = [2,3,4,5,6]
min_samples_split = [2,4,6,8]
min_samples_leaf = [2,4,8,10,12]
# 將各引數值以字典形式組織起來
parameters = {'max_depth':max_depth, 'min_samples_split':min_samples_split,
'min_samples_leaf':min_samples_leaf}
# ⽹格搜尋法,測試不同的引數值
grid_dtcateg = GridSearchCV(estimator = tree.DecisionTreeClassifier(), param_grid = parameters, cv=10)
# 模型擬合
grid_dtcateg.fit(X_train, y_train)
# 返回最佳組合的引數值
grid_dtcateg.best_params_

'''分類決策樹'''
# 匯入第三方模組
from  sklearn import metrics
# 構建分類決策樹
CART_Class = tree.DecisionTreeClassifier(max_depth=3,min_samples_leaf=4,min_samples_split=2)
# 模型擬合
decision_tree = CART_Class.fit(X_train,y_train)
# 模型在測試集上的預測
pred = CART_Class.predict(X_test)
# 模型的準確率
print('模型在測試集的預測準確率:\n',metrics.accuracy_score(y_test,pred))
print('模型在訓練集的預測準確率:\n',
metrics.accuracy_score(y_train,CART_Class.predict(X_train)))

'''隨機森林'''
# 匯入第三方包
from sklearn import ensemble
# 構建隨機森林
RF_class = ensemble.RandomForestClassifier(n_estimators=200, random_state=1234)
# 隨機森林的擬合
RF_class.fit(X_train, y_train)
# 模型在測試集上的預測
RFclass_pred = RF_class.predict(X_test)
# 模型的準確率
print('模型在測試集的預測準確率:\n',metrics.accuracy_score(y_test, RFclass_pred))

'''挑出重要因素'''
# 變數的重要性程度值
importance = RF_class.feature_importances_
# 構建含序列⽤於繪圖
Impt_Series = pd.Series(importance, index = X_train.columns)
# 對序列排序繪圖
Impt_Series.sort_values(ascending = True).plot('barh')
# 顯示圖形
plt.show()