概要
基於 sklearn 包自帶的 iris 數據集,了解一下分類樹的各種參數設置以及代表的意義。
iris 數據集介紹
iris 數據集包含 150 個樣本,對應數據集的每行數據,每行數據包含每個樣本的四個特征(花萼長度、花萼寬度、花瓣長度、花瓣寬度)和樣本的類別信息,所以 iris 數據集是一個 150 行 5 列的二維表。
iris 數據集總共有三類:Iris Setosa(山鳶尾)、Iris Versicolour(雜色鳶尾),以及 Iris Virginica(維吉尼亞鳶尾),每類 50 個數據。其中的一個種類與另外兩個種類是線性可分離的,后兩個種類是非線性可分離的,具體地看后續實驗分析。
下邊這張圖片是在網上找的數據集示例,單位是 cm.
對其有了大概的認識,下邊就進行深入探究吧。
sklearn.tree.DecisionTreeClassifier
函數參數
該函數包含很多參數,具體如下:
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=False)
下面一一解釋。
criterion
參數 criterion 表示選擇特征的准則,默認是 'gini',也就是基尼系數了,sklearn 庫是使用的改良后的 CART 算法。當然你也可以設置成 'entropy',即信息增益,具體使用哪個,那就實驗看看模型效果唄。
下面我們使用默認的 'gini' 准則來生成決策樹:
# -*- coding: utf-8 -*-
"""
Created on Wed Apr 18 11:33:09 2018
@author: zhoukui
"""
from sklearn.datasets import load_iris
from sklearn import tree
from sklearn.externals.six import StringIO
import pydotplus
'''
StringIO 經常被用來作字符串的緩存,它的部分接口跟文件一樣,可以
認為是作為"內存文件對象",簡而言之,就是為了方便
'''
dot_data = StringIO()
iris = load_iris()
clf = tree.DecisionTreeClassifier() # 如果改用信息增益准則,就在括號中添加: criterion='entropy'
clf = clf.fit(iris.data, iris.target)
# print(clf.max_features_) # 輸出擬合樹的屬性
dot_data = tree.export_graphviz(clf, out_file=None,
feature_names=iris.feature_names,
class_names=iris.target_names,
filled=True,rounded=True,
impurity=False)
graph = pydotplus.graph_from_dot_data(dot_data)
graph.write_pdf("iris.pdf")
可視化如下:
圖 1:采用 'gini' 標准生成的決策樹
由圖可知,第一個選擇的特征是花瓣寬度(petal width),只要其值小於 0.8,就把所有的 setosa 類共 50 個全都找出來了,其它的分類可以自己繼續分析。
如果你選擇 'entropy' 准則,就會得到下面這樣的樹:
圖 2:采用 'entropy' 標准生成的決策樹
由圖可知,此時第一個選擇的特征改為了花瓣長度(petal length),其值小於 2.45,也能夠把 50 個 setosa 類全部分出來。仔細對比一下,這兩種准則生成的樹幾乎一樣,看來對於這個 iris 數據集對於准則的選擇並不敏感。
splitter
該參數是設置划分點的選擇標准,比方說圖 1 中第一個節點的 0.8 的選擇,默認是 'best',表示在所有特征中找最好的切分點。也可以選擇 'random',表示隨機地在部分特征中選擇最好的切分點(數據量大的時候),所以默認的 'best' 適合樣本量不大的時候,而如果樣本數據量非常大,可嘗試使用 'random' . 在本例中,如果選擇后者,會產生一個更加復雜的樹,顯然沒有 'best' 好。
max_depth
我們知道決策樹的一個大缺點就是過擬合,max_depth 參數就是設置決策樹的最大層數的,默認值是 None. 如果樹形比較簡單的話一般選擇默認就行了,如果樹形太過於復雜,可以設置一下最大層數。比方說對於 iris 數據,我們設置 max_depth = 3
,就會得到一個深度為 3 的樹,看下圖它的層數沒有算上根節點。anyway,知道什么意思就行了。實踐中如果模型樣本量、特征非常多的情況下,推薦限制這個最大深度,具體的取值取決於數據的分布,常用的可以取值10-100之間。
圖 3:限制 `max_depth = 3` 生成的決策樹 ### min_samples_split
該參數表示分裂所要求的最少樣本,默認值為 2,如果數量少於該值就不再分叉了,觀察圖 1 末尾的幾節點,可以發現存在樣本量為 3 時還在繼續分裂,這時候生成的模型也容易過擬合,如果我們設置 min_samples_split = 30
,就會生成下面的決策樹:
圖 4:限制 `min_samples_split = 30` 生成的決策樹
可以發現決策樹是簡潔了一點點。
另外該參數也支持浮點型,表示所占總樣本量的百分比,如果樣本量除以總樣本量低於這個值,便不再分裂。比方說我們令 min_samples_split = 0.2
(\(150*0.2=30\)),會生成和圖 4 一樣的樹。
min_samples_leaf=1
該參數表示每個決策樹的葉子節點上面的樣本數量,少於設置值就會被剪掉(當然包括兄弟結點)。該參數同樣也支持浮點型,意義同參數 min_samples_split,注意與 min_samples_split 的區別,如果設置了 min_samples_leaf 值,表示生成樹中沒有樣本量低於該值的葉子節點,而 min_samples_split 值表示低於該值便不再分裂。
min_weight_fraction_leaf
該值限制了葉子節點樣本量占所有樣本百分比(權重)的最小值,如果小於這個值,則會和兄弟節點一起剪掉,其和 min_samples_leaf 的百分比形式等價。 默認值是 0,就是不考慮權重問題。一般來說,如果我們有較多樣本有缺失值,或者分類樹樣本的分布類別偏差很大,就會引入樣本權重,這時我們就要注意這個值了。
max_features
該值確定參與分裂的特征數,默認值是 None,即全部特征都參與。其詳細取值如下:
- 如果是整型
int
,就作為所選取的特征數目:max_features - 如果是
float
類型,選取特征數目由所有特征乘以這個小數決定:n_features*max_features - 如果是 'auto',則特征數目為:sqrt(n_features)
- 如果是 'sqrt', 則特征數目也為:sqrt(n_features)
- 如果是 'log2',則特征數目為:\(log_2\)(n_features)
- 如果是 'None', 則特征數目為:n_features
random_state
這個也很好理解,如果是 int
,那么 random_state 是隨機數字發生器的種子。如果是 RandomState,那么 random_state 就是隨機數字發生器。如果是默認的 None,則表示隨機數字發生器是 np.random 使用的 RandomState instance.
max_leaf_nodes
該值限制了生成樹的葉子結點樹,默認是 None,表示沒有限制。如果加了限制,算法會建立在最大葉子節點數內最優的決策樹。如果特征不多,可以不考慮這個值,但是如果特征多的話,可以加以限制,具體的值可以通過交叉驗證得到。比如我們限制其值為 2,那么就會生成如下的決策樹:
圖 5:限制 `max_leaf_nodes = 2` 生成的決策樹
再強調一句,決策樹沒有奇數的葉子節點,如果你設置 max_leaf_nodes = 3
,那么就會生成具有 4 個葉子節點的決策樹。
min_impurity_decrease
最小不純度值減少的量,默認是 0.,一個節點只有在分裂后其不純度值減少的量大於該值時才會被分裂。
min_impurity_split
最小不純度值,默認是 None. 一個節點只有其不純度值大於該值時才會被分裂。
class_weight
指定樣本各類別的的權重,主要是為了防止訓練集某些類別的樣本過多導致訓練的決策樹過於偏向這些類別。默認值是 None,這里可以自己指定各個樣本的權重如果使用 'balanced',則算法會自己計算權重,樣本量少的類別所對應的樣本權重會高。 也可以自己定義權重,使用字典類型,詳細看官網。 ,
presort
該值表示對樣本是否進行預排序,默認是 False,即不排序。一般來說,如果樣本量少或者限制了一個深度很小的決策樹,設置為 True 可以讓划分點選擇更加快,決策樹建立的更加快。如果樣本量太大的話,反而沒有什么好處。
屬性
擬合數據后得到的模型有一些屬性,可以查看相關信息。
classes_
形狀為 [n_classes,] 的數組或者列表,表示預測的類。對 iris 數據集,因為共有三類,所以輸出 [0, 1, 2].
feature_importances_
形狀為 [n_classes,] 的數組或者列表,表示特征的重要度。值越大表示越重要,由於其生成樹過程中有一定的隨機性,所以每次運行該值並不唯一,如果固定了 random_state,那就確定了,其它參數默認,運行會發現,最后一個特征,即花瓣寬度最重要。
max_features_
參與生成樹的特征數目(個人還不太確定),對 iris 數據集,其輸出是 4. 如果創建樹時設置 max_features = 3
,其屬性 max_features_ 值就是 3,所以我應該沒有猜錯。
n_classes_
類的數目。對 iris 數據集,其輸出是 3.
n_features_
fit 函數產生的特征數目,對 iris 數據集,其輸出是 4.
n_outputs_
fit 函數輸出結果數目,對 iris 數據集(單值輸出),其輸出是 1.
tree_
生成的樹對象。
方法
擬合數據后得到的決策樹同樣有一些方法,可以用來查看一些信息,當然最重要的是預測。下面列出幾個比較重要的方法。
apply(X, check_input=True)
返回每個樣本的葉節點的預測序號。
decision_path(X, check_input=True)
返回決策樹的決策路徑 [n_samples, n_nodes].
fit(X, y, sample_weight=None, check_input=True, X_idx_sorted=None)
從訓練數據建立決策樹,返回一個對象。
predict(X, check_input=True)
預測X的分類或者回歸,返回 [n_samples].
predict_log_proba(X)
預測輸入樣本的對數概率,返回[n_samples, n_classes].
predict_proba(X, check_input=True)
預測輸入樣本的屬於各個類的概率[n_samples, n_classes].
score(X, y, sample_weight=None)
返回對於測試數據的平均准確率。
總結
- 從決策樹的各種參數設置可以發現,大多都和控制生成樹的規模有關,所以也反映出決策樹模型是一種很容易過擬合的模型
- 一般來說,樣本量過小時,容易過擬合,如果同時特征很多,此時應考慮降維
- 使用決策樹模型時,可以利用決策樹可視化的優點,探測性嘗試樹的深度