以前對決策樹的算法原理作了總結,包括決策樹算法原理(上)和決策樹算法原理(下)。今天就從實踐的角度來介紹決策樹算法,主要是講解使用scikit-learn來跑決策樹算法,結果的可視化以及一些參數調參的關鍵點。html
scikit-learn決策樹算法類庫內部實現是使用了調優過的CART樹算法,既能夠作分類,又能夠作迴歸。分類決策樹的類對應的是DecisionTreeClassifier,而回歸決策樹的類對應的是DecisionTreeRegressor。二者的參數定義幾乎徹底相同,可是意義不全相同。下面就對DecisionTreeClassifier和DecisionTreeRegressor的重要參數作一個總結,重點比較二者參數使用的不一樣點和調參的注意點。node
爲了便於比較,這裏咱們用表格的形式對DecisionTreeClassifier和DecisionTreeRegressor重要參數要點作一個比較。python
參數 | DecisionTreeClassifier | DecisionTreeRegressor |
特徵選擇標準criterionlinux |
可使用"gini"或者"entropy",前者表明基尼係數,後者表明信息增益。通常說使用默認的基尼係數"gini"就能夠了,即CART算法。除非你更喜歡相似ID3, C4.5的最優特徵選擇方法。 git |
可使用"mse"或者"mae",前者是均方差,後者是和均值之差的絕對值之和。推薦使用默認的"mse"。通常來講"mse"比"mae"更加精確。除非你想比較二個參數的效果的不一樣之處。 |
特徵劃分點選擇標準splittergithub |
可使用"best"或者"random"。前者在特徵的全部劃分點中找出最優的劃分點。後者是隨機的在部分劃分點中找局部最優的劃分點。算法 默認的"best"適合樣本量不大的時候,而若是樣本數據量很是大,此時決策樹構建推薦"random" windows |
|
劃分時考慮的最大特徵數max_features數組 |
可使用不少種類型的值,默認是"None",意味着劃分時考慮全部的特徵數;若是是"log2"意味着劃分時最多考慮$log_2N$個特徵;若是是"sqrt"或者"auto"意味着劃分時最多考慮$\sqrt{N}$個特徵。若是是整數,表明考慮的特徵絕對數。若是是浮點數,表明考慮特徵百分比,即考慮(百分比xN)取整後的特徵數。其中N爲樣本總特徵數。dom 通常來講,若是樣本特徵數很少,好比小於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稀疏化。
決策樹可視化化能夠方便咱們直觀的觀察模型,以及發現模型中的問題。這裏介紹下scikit-learn中決策樹的可視化方法。
完整代碼見個人github: https://github.com/ljpzzz/machinelearning/blob/master/classic-machine-learning/decision_tree_classifier.ipynb
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目錄。
這裏咱們有一個例子講解決策樹可視化。
首先載入類庫:
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例子。
完整代碼見個人github: https://github.com/ljpzzz/machinelearning/blob/master/classic-machine-learning/decision_tree_classifier_1.ipynb
from itertools import product import numpy as np import matplotlib.pyplot as plt from 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)