上兩篇我們探討了決策樹ID3算法,C4.5算法以及CART算法。CART算法在ID3,C4.5的基礎上進行了不少優化,也是Scikit-learn決策樹庫使用的算法,是我們必須要掌握的算法之一。本篇我們基於上篇的算法原理,來探討下Scikit-learn決策樹算法庫的一些常用參數,以及決策樹的可視化,最後我們使用DecisionTreeClassifier做一個簡單的分類實踐。
1)Scikit-learn決策樹算法庫概述
Scikit-learn決策樹算法庫既可以做分類,又可以做迴歸。分類庫類對應DecisionTreeClassifier,迴歸庫類對應DecisionTreeRegressor,兩者的絕大多數參數都相同,下面按照參數重要性進行一一介紹。
2)DecisionTreeClassifier常用參數
Scikit-learn DecisionTreeClassifier類官方API:class sklearn.tree.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=‘deprecated’, ccp_alpha=0.0)[source]
-
criterion,不確定性的計算方式,默認“gini”
可以輸入“gini”和“entropy”,“gini”對應CART算法的基尼係數, “entropy”對應信息增益。在實際使用中,信息熵和基尼係數的效果基本相同,但信息熵涉及對數計算,模型會慢一些。實際使用時,大多保持默認“gini”設置。 -
splitter,特徵劃分方式,默認“best”
該參數爲特徵劃分的方式,“best”表示在特徵所有劃分中選擇最優的劃分點;“random”表示在隨機劃分中選擇最優的劃分點。實際使用時,大多保持默認“best”設置。 -
max_depth,樹的最大深度,默認“None”
該參數用來限制樹過擬合的剪枝參數,超過指定深度的樹枝全部被剪掉。當爲“None”是,決策樹將將會自由生長。決策樹首要調整的剪枝參數,實際使用時,在沒有經驗的情況下,可以參考從3開始調整。 -
min_samples_leaf,葉節點最小樣本個數,默認1
該參數用來限制樹過擬合的剪枝參數。如果葉節點樣本數目小於該參數的值,葉節點將會被剪枝。實際使用時,小樣本保持默認1設置,大樣本(10萬)時,需要設置該參數,可以參考從5開始調整。 -
min_samples_split,節點劃分所需的最小樣本個數,默認2
該參數用來限制樹過擬合的剪枝參數。如果節點樣本數小於該參數,節點將會不會再被劃分。實際使用時,小樣本保持默認設置,大樣本(10萬)時,可以參考從5開始調整。 -
ccp_alpha,最小剪枝係數,默認爲0
該參數用來限制樹過擬合的剪枝參數。對應上一篇決策樹原理中的,模型將會選擇小於輸入值最大。ccp_alpha=0時,決策樹不剪枝;ccp_alpha越大,越多的節點被剪枝。Scikit learn 0.22版本新增參數。 -
max_features,分枝時考慮的特徵個數,默認爲“None”
該參數用來限制樹過擬合的剪枝參數。max_features限制分枝時考慮的特徵個數,超過限制個數的特徵都會被捨棄。輸入爲“None”時,使用所有的特徵進行特徵選擇。否則設定指定數量的特徵,如平方根個特徵(sqrt),對數個特徵(log2)。設定指定數量的特徵可能會導致模型學習不足。 -
class_weight,類別權重參數,默認爲“None”
當樣本存在不平衡的情況下,需要設置該參數。 這裏可以自己指定各個樣本的權重,或者用‘balanced’,如果使用‘balanced’ ,則算法會自己計算權重,樣本量少的類別所對應的樣本權重會高。 -
min_weight_fraction_leaf,葉子節點最小的樣本權重和,默認爲0。
當設置了class_weight參數,樣本量就不再是單純地記錄數目,而是受輸入的權重影響了,因此這時候剪枝,就需要搭配min_ weight_fraction_leaf這個基於權重的剪枝參數來使用。 -
random_state,隨機種子,默認爲“None”
當輸入爲int型數值時,隨機數生成器使用的輸入值作爲種子;輸入爲None時,則隨機數生成器是所使用np.random產生的隨機數作爲種子。
3)DecisionTreeRegressor常用參數
sklearn.tree.DecisionTreeRegressor(criterion=‘mse’, 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, presort=‘deprecated’, ccp_alpha=0.0)[source]
DecisionTreeRegressor中的參數絕大多數參數和DecisionTreeClassifier相同,只有特徵選擇的方式不同。
- criterion,不確定性的計算方式,默認“mse”
可以輸入"mse"或者"mae",mse是均方差,mae是和均值之差的絕對值之和。實際使用時,使用默認的"mse"。
4)決策樹結果可視化
scikit-learn中決策樹的可視化使用Graphviz,Graphviz是一款開源圖形可視化軟件包。首先我們到官網下載對應版本的Graphviz進行安裝,設置環境變量,將graphviz的bin目錄加到PATH,比如我的graphviz的bin目錄爲:D:\Program Files (x86)\decisionTreeVersion_Graphviz\bin。然後,通過pip安裝可視化所需要的graphviz,pydotplus包。
注意:如果完成環境變量的設置,Python還提醒沒有將graphviz的bin目錄加到PATH,可使用代碼指定環境目錄:
import os
os.environ["PATH"] += os.pathsep +"D:/Program Files (x86)/decisionTreeVersion_Graphviz/bin/"
決策樹的可視化輸出有三種方式,我們放在案例中進行介紹。
5)決策樹算法庫使用經驗總結
- 在高維數據下,我們需要指定,否則每次調參時,隨機種子不一樣,建立的決策樹也不一樣,調參沒有意義。
- 如果你的數據集非常大,你已經預測到需要要剪枝,那提前設定一些剪枝參數來減少模型的複雜度,縮短模型運行的時間。
- 使用決策樹模型的屬性feature_importances_查看特徵重要性,以及特徵選擇。
- 使用grid_search和交叉驗證對剪枝參數進行選擇。
6)簡單實踐
下面我們使用決策樹算法,對鳶尾花數據進行分類,學習決策樹的可視化方式。完整代碼已經上傳到我的Github。
首先導入需要使用的Python包:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib as mpl
from sklearn import tree
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
import pydotplus
import os
設置Python一些環境:
#設置Graphviz環境變量
os.environ["PATH"] += os.pathsep +"D:/Program Files (x86)/decisionTreeVersion_Graphviz/bin/"
#中文可視化
mpl.rcParams['font.sans-serif'] = ['simHei']
mpl.rcParams['axes.unicode_minus'] = False
讀取鳶尾花數據。
iris_feature_E = 'sepal length', 'sepal width', 'petal length', 'petal width'
iris_feature = '花萼長度', '花萼寬度', '花瓣長度', '花瓣寬度'
iris_class = 'Iris-setosa', 'Iris-versicolor', 'Iris-virginica'
path = '..\\iris.data' # 數據文件路徑
data = pd.read_csv(path, header=None)
使用鳶尾花的花萼長與花萼寬進行模型構建,方便後面做可視化效果展示。
x = data.iloc[:,:4]
y = pd.Categorical(data[4]).codes
x = x.iloc[:, :2]
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.3, random_state=1)
model = DecisionTreeClassifier()
model.fit(x_train, y_train)
y_test_hat = model.predict(x_test) # 測試數據
print('accuracy_score:', accuracy_score(y_test, y_test_hat))
下面我們介紹決策樹的可視化,決策樹的可視化方法有三種。第一種和第二種方法都是生成.dot文件,利用graphviz打開或者通過系統命令轉成PNG進行查看。系統命令爲:
dot -Tpng iris.dot -o iris.png
第一種決策樹可視化方法和效果如下:
with open('iris1.dot', 'w') as f:
tree.export_graphviz(model, out_file=f)
第二種決策樹的可視化方法和第一種效果一樣:
tree.export_graphviz(model, out_file='iris2.dot')
我們可以看出上面兩種方法生成的決策樹沒有對應的字段名稱,不太利於解讀,因此我們實際應用中使用第三種方法:
dot_data = tree.export_graphviz(model, out_file=None, feature_names=iris_feature_E[0:2], class_names=iris_class,
filled=True, rounded=True, special_characters=True)
graph = pydotplus.graph_from_dot_data(dot_data)
graph.write_pdf('iris.pdf')
f = open('iris.png', 'wb')
f.write(graph.create_png())
f.close()
第三種可視化效果如下:
我們可視化決策樹的分類效果,從決策樹分類效果中可以看出,決策樹完全根據訓練數據進行生長。
# 畫圖
N, M = 50, 50 # 橫縱各採樣多少個值
x1_min, x2_min = x.min()
x1_max, x2_max = x.max()
t1 = np.linspace(x1_min, x1_max, N)
t2 = np.linspace(x2_min, x2_max, M)
x1, x2 = np.meshgrid(t1, t2) # 生成網格採樣點
x_show = np.stack((x1.flat, x2.flat), axis=1) # 測試點
cm_light = mpl.colors.ListedColormap(['#A0FFA0', '#FFA0A0', '#A0A0FF'])
cm_dark = mpl.colors.ListedColormap(['g', 'r', 'b'])
y_show_hat = model.predict(x_show) # 預測值
y_show_hat = y_show_hat.reshape(x1.shape) # 使之與輸入的形狀相同
plt.figure(facecolor='w')
plt.pcolormesh(x1, x2, y_show_hat, cmap=cm_light) # 預測值的顯示
plt.scatter(x_test[0], x_test[1], c=y_test.ravel(), edgecolors='k', s=100, zorder=10, cmap=cm_dark, marker='*') # 測試數據
plt.scatter(x[0], x[1], c=y.ravel(), edgecolors='k', s=20, cmap=cm_dark) # 全部數據
plt.xlabel(iris_feature[0], fontsize=13)
plt.ylabel(iris_feature[1], fontsize=13)
plt.xlim(x1_min, x1_max)
plt.ylim(x2_min, x2_max)
plt.grid(b=True, ls=':', color='#606060')
plt.title('鳶尾花數據的決策樹分類', fontsize=15)
plt.show()
# 訓練集上的預測結果
y_test = y_test.reshape(-1)
print(y_test_hat)
print(y_test)
result = (y_test_hat == y_test) # True則預測正確,False則預測錯誤
acc = np.mean(result)
print('準確度: %.2f%%' % (100 * acc))
下面看下樹的深度和過擬合之間的關係。
# 過擬合:錯誤率
depth = np.arange(1, 15)
err_list = []
for d in depth:
clf = DecisionTreeClassifier( max_depth=d)
clf.fit(x_train, y_train)
y_test_hat = clf.predict(x_test) # 測試數據
result = (y_test_hat == y_test) # True則預測正確,False則預測錯誤
err = 1 - np.mean(result)
err_list.append(err)
print(d, ' 錯誤率: %.2f%%' % (100 * err))
plt.figure(facecolor='w')
plt.plot(depth, err_list, 'ro-', markeredgecolor='k', lw=2)
plt.xlabel('決策樹深度', fontsize=13)
plt.ylabel('錯誤率', fontsize=13)
plt.title('決策樹深度與過擬合', fontsize=15)
plt.grid(b=True, ls=':', color='#606060')
plt.show()
到此,我們終於完成了決策樹算法系列的探討。希望大家有所思,有所悟。
(歡迎大家在評論區探討交流,也歡迎大家轉載,轉載請註明出處)
上篇:決策樹(Decision Tree)算法原理總結(二)
下篇:集成學習方法之Bagging,Boosting,Stacking