Scikit-learn決策樹算法庫總結與簡單實踐

       上兩篇我們探討了決策樹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
           該參數用來限制樹過擬合的剪枝參數。對應上一篇決策樹原理中的α\alpha,模型將會選擇小於輸入值最大α\alpha。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)決策樹算法庫使用經驗總結

  • 在高維數據下,我們需要指定random_staterandom\_state,否則每次調參時,隨機種子不一樣,建立的決策樹也不一樣,調參沒有意義。
  • 如果你的數據集非常大,你已經預測到需要要剪枝,那提前設定一些剪枝參數來減少模型的複雜度,縮短模型運行的時間。
  • 使用決策樹模型的屬性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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章