之前對決策樹的算法原理做了總結,包括決策樹算法原理(上)和決策樹算法原理(下)。今天就從實踐的角度來介紹決策樹算法,主要是講解使用scikit-learn來跑決策樹算法,結果的可視化以及一些參數調參的關鍵點。
1.?scikit-learn決策樹算法類庫介紹
scikit-learn決策樹算法類庫內部實現是使用了調優過的CART樹算法,既可以做分類,又可以做回歸。分類決策樹的類對應的是DecisionTreeClassifier,而回歸決策樹的類對應的是DecisionTreeRegressor。兩者的參數定義幾乎完全相同,但是意義不全相同。下面就對DecisionTreeClassifier和DecisionTreeRegressor的重要參數做一個總結,重點比較兩者參數使用的不同點和調參的注意點。
2.?DecisionTreeClassifier和DecisionTreeClassifier 重要參數調參注意點
為了便于比較,這里我們用表格的形式對DecisionTreeClassifier和DecisionTreeRegressor重要參數要點做一個比較。
參數 | DecisionTreeClassifier | DecisionTreeRegressor |
特征選擇標準criterion | 可以使用"gini"或者"entropy",前者代表基尼系數,后者代表信息增益。一般說使用默認的基尼系數"gini"就可以了,即CART算法。除非你更喜歡類似ID3, C4.5的最優特征選擇方法。? | ?可以使用"mse"或者"mae",前者是均方差,后者是和均值之差的絕對值之和。推薦使用默認的"mse"。一般來說"mse"比"mae"更加精確。除非你想比較二個參數的效果的不同之處。 |
特征劃分點選擇標準splitter | 可以使用"best"或者"random"。前者在特征的所有劃分點中找出最優的劃分點。后者是隨機的在部分劃分點中找局部最優的劃分點。 默認的"best"適合樣本量不大的時候,而如果樣本數據量非常大,此時決策樹構建推薦"random"? | |
劃分時考慮的最大特征數max_features | 可以使用很多種類型的值,默認是"None",意味著劃分時考慮所有的特征數;如果是"log2"意味著劃分時最多考慮$log_2N$個特征;如果是"sqrt"或者"auto"意味著劃分時最多考慮$\sqrt{N}$個特征。如果是整數,代表考慮的特征絕對數。如果是浮點數,代表考慮特征百分比,即考慮(百分比xN)取整后的特征數。其中N為樣本總特征數。 一般來說,如果樣本特征數不多,比如小于50,我們用默認的"None"就可以了,如果特征數非常多,我們可以靈活使用剛才描述的其他取值來控制劃分時考慮的最大特征數,以控制決策樹的生成時間。 | |
決策樹最大深max_depth | ?決策樹的最大深度,默認可以不輸入,如果不輸入的話,決策樹在建立子樹的時候不會限制子樹的深度。一般來說,數據少或者特征少的時候可以不管這個值。如果模型樣本量多,特征也多的情況下,推薦限制這個最大深度,具體的取值取決于數據的分布。常用的可以取值10-100之間。 | |
內部節點再劃分所需最小樣本數min_samples_split | 這個值限制了子樹繼續劃分的條件,如果某節點的樣本數少于min_samples_split,則不會繼續再嘗試選擇最優特征來進行劃分。?默認是2.如果樣本量不大,不需要管這個值。如果樣本量數量級非常大,則推薦增大這個值。我之前的一個項目例子,有大概10萬樣本,建立決策樹時,我選擇了min_samples_split=10。可以作為參考。 | |
葉子節點最少樣本數min_samples_leaf | ?這個值限制了葉子節點最少的樣本數,如果某葉子節點數目小于樣本數,則會和兄弟節點一起被剪枝。?默認是1,可以輸入最少的樣本數的整數,或者最少樣本數占樣本總數的百分比。如果樣本量不大,不需要管這個值。如果樣本量數量級非常大,則推薦增大這個值。之前的10萬樣本項目使用min_samples_leaf的值為5,僅供參考。 | |
葉子節點最小的樣本權重和min_weight_fraction_leaf | 這個值限制了葉子節點所有樣本權重和的最小值,如果小于這個值,則會和兄弟節點一起被剪枝。?默認是0,就是不考慮權重問題。一般來說,如果我們有較多樣本有缺失值,或者分類樹樣本的分布類別偏差很大,就會引入樣本權重,這時我們就要注意這個值了。 | |
最大葉子節點數max_leaf_nodes | ?通過限制最大葉子節點數,可以防止過擬合,默認是"None”,即不限制最大的葉子節點數。如果加了限制,算法會建立在最大葉子節點數內最優的決策樹。如果特征不多,可以不考慮這個值,但是如果特征分成多的話,可以加以限制,具體的值可以通過交叉驗證得到。 | |
類別權重class_weight | 指定樣本各類別的的權重,主要是為了防止訓練集某些類別的樣本過多,導致訓練的決策樹過于偏向這些類別。這里可以自己指定各個樣本的權重,或者用“balanced”,如果使用“balanced”,則算法會自己計算權重,樣本量少的類別所對應的樣本權重會高。當然,如果你的樣本類別分布沒有明顯的偏倚,則可以不管這個參數,選擇默認的"None" | ?不適用于回歸樹 |
節點劃分最小不純度min_impurity_split | ?這個值限制了決策樹的增長,如果某節點的不純度(基尼系數,信息增益,均方差,絕對差)小于這個閾值,則該節點不再生成子節點。即為葉子節點?。 | |
數據是否預排序presort | 這個值是布爾值,默認是False不排序。一般來說,如果樣本量少或者限制了一個深度很小的決策樹,設置為true可以讓劃分點選擇更加快,決策樹建立的更加快。如果樣本量太大的話,反而沒有什么好處。問題是樣本量少的時候,我速度本來就不慢。所以這個值一般懶得理它就可以了。 |
除了這些參數要注意以外,其他在調參時的注意點有:
1)當樣本少數量但是樣本特征非常多的時候,決策樹很容易過擬合,一般來說,樣本數比特征數多一些會比較容易建立健壯的模型
2)如果樣本數量少但是樣本特征非常多,在擬合決策樹模型前,推薦先做維度規約,比如主成分分析(PCA),特征選擇(Losso)或者獨立成分分析(ICA)。這樣特征的維度會大大減小。再來擬合決策樹模型效果會好。
3)推薦多用決策樹的可視化(下節會講),同時先限制決策樹的深度(比如最多3層),這樣可以先觀察下生成的決策樹里數據的初步擬合情況,然后再決定是否要增加深度。
4)在訓練模型先,注意觀察樣本的類別情況(主要指分類樹),如果類別分布非常不均勻,就要考慮用class_weight來限制模型過于偏向樣本多的類別。
5)決策樹的數組使用的是numpy的float32類型,如果訓練數據不是這樣的格式,算法會先做copy再運行。
6)如果輸入的樣本矩陣是稀疏的,推薦在擬合前調用csc_matrix
稀疏化,在預測前調用csr_matrix稀疏化。
3. scikit-learn決策樹結果的可視化
決策樹可視化化可以方便我們直觀的觀察模型,以及發現模型中的問題。這里介紹下scikit-learn中決策樹的可視化方法。
完整代碼見我的github: https://github.com/ljpzzz/machinelearning/blob/master/classic-machine-learning/decision_tree_classifier.ipynb
3.1 決策樹可視化環境搭建
scikit-learn中決策樹的可視化一般需要安裝graphviz。主要包括graphviz的安裝和python的graphviz插件的安裝。
第一步是安裝graphviz。下載地址在:http://www.graphviz.org/。如果你是linux,可以用apt-get或者yum的方法安裝。如果是windows,就在官網下載msi文件安裝。無論是linux還是windows,裝完后都要設置環境變量,將graphviz的bin目錄加到PATH,比如我是windows,將C:/Program Files (x86)/Graphviz2.38/bin/加入了PATH
第二步是安裝python插件graphviz:?pip install graphviz
第三步是安裝python插件pydotplus。這個沒有什么好說的: pip install pydotplus
這樣環境就搭好了,有時候python會很笨,仍然找不到graphviz,這時,可以在代碼里面加入這一行:
os.environ["PATH"] += os.pathsep + 'C:/Program Files (x86)/Graphviz2.38/bin/'
注意后面的路徑是你自己的graphviz的bin目錄。
3.2 決策樹可視化的三種方法
這里我們有一個例子講解決策樹可視化。
首先載入類庫:
from sklearn.datasets import load_iris from sklearn import tree import sys import os os.environ["PATH"] += os.pathsep + 'C:/Program Files (x86)/Graphviz2.38/bin/'
接著載入sciki-learn的自帶數據,有決策樹擬合,得到模型:
iris = load_iris() clf = tree.DecisionTreeClassifier() clf = clf.fit(iris.data, iris.target)
現在可以將模型存入dot文件iris.dot。
with open("iris.dot", 'w') as f:f = tree.export_graphviz(clf, out_file=f)
這時候我們有3種可視化方法,第一種是用graphviz的dot命令生成決策樹的可視化文件,敲完這個命令后當前目錄就可以看到決策樹的可視化文件iris.pdf.打開可以看到決策樹的模型圖。
#注意,這個命令在命令行執行 dot -Tpdf iris.dot -o iris.pdf
第二種方法是用pydotplus
生成iris.pdf。這樣就不用再命令行去專門生成pdf文件了。
import pydotplus dot_data = tree.export_graphviz(clf, out_file=None) graph = pydotplus.graph_from_dot_data(dot_data) graph.write_pdf("iris.pdf")
第三種辦法是個人比較推薦的做法,因為這樣可以直接把圖產生在ipython的notebook。代碼如下:
from IPython.display import Image dot_data = tree.export_graphviz(clf, out_file=None, feature_names=iris.feature_names, class_names=iris.target_names, filled=True, rounded=True, special_characters=True) graph = pydotplus.graph_from_dot_data(dot_data) Image(graph.create_png())
在ipython的notebook生成的圖如下:
4.?DecisionTreeClassifier實例
這里給一個限制決策樹層數為4的DecisionTreeClassifier例子。
完整代碼見我的github: https://github.com/ljpzzz/machinelearning/blob/master/classic-machine-learning/decision_tree_classifier_1.ipynb
from itertools import productimport numpy as np import matplotlib.pyplot as pltfrom sklearn import datasets from sklearn.tree import DecisionTreeClassifier# 仍然使用自帶的iris數據 iris = datasets.load_iris() X = iris.data[:, [0, 2]] y = iris.target# 訓練模型,限制樹的最大深度4 clf = DecisionTreeClassifier(max_depth=4) #擬合模型 clf.fit(X, y)# 畫圖 x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1 y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1 xx, yy = np.meshgrid(np.arange(x_min, x_max, 0.1),np.arange(y_min, y_max, 0.1))Z = clf.predict(np.c_[xx.ravel(), yy.ravel()]) Z = Z.reshape(xx.shape)plt.contourf(xx, yy, Z, alpha=0.4) plt.scatter(X[:, 0], X[:, 1], c=y, alpha=0.8) plt.show()
得到的圖如下:
接著我們可視化我們的決策樹,使用了推薦的第三種方法。代碼如下:
from IPython.display import Image from sklearn import tree import pydotplus dot_data = tree.export_graphviz(clf, out_file=None, feature_names=iris.feature_names, class_names=iris.target_names, filled=True, rounded=True, special_characters=True) graph = pydotplus.graph_from_dot_data(dot_data) Image(graph.create_png())
生成的決策樹圖如下:
?
以上就是scikit-learn決策樹算法使用的一個總結,希望可以幫到大家。
?
(歡迎轉載,轉載請注明出處。歡迎溝通交流: liujianping-ok@163.com)?