1. 程式人生 > 實用技巧 >sklearn中的決策樹

sklearn中的決策樹

一、sklearn中的決策樹模組:sklearn.tree

1、sklearn中決策樹的類都在‘tree’這個模組之下。這個模組 總共包含五個類:

2、sklearn的基本建模流程

3、下面對sklearn.tree這個模組之下的決策樹類進行逐個說明:

3.1、分類樹:tree.DecisionTreeClassifier()

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=False)

重要引數:

(1)criterion:

Criterion這個引數正是用來決定不純度的計算方法的。sklearn提供了兩種選擇:
1)輸入”entropy“,使用資訊熵(Entropy)
2)輸入”gini“,使用基尼係數(Gini Impurity)

(2)random_state & splitter:

random_state用來設定分枝中的隨機模式的引數,預設為None,設定的話,是為了保證每次隨機生成的數是一致的(即使是隨機的);

如果不設定,那麼每次生成的隨機數都是不同的,也就是說決策樹其實是隨機的(可以通過多執行幾次score測試下)。

  splitter也是用來控制決策樹中的隨機選項的,有兩種輸入值:

    1)輸入”best",決策樹在分枝時雖然隨機,但是還是會優先選擇更重要的特徵進行分枝。重要性可以通過屬性feature_importances_檢視。

    2)輸入“random",決策樹在分枝時會更加隨機,樹會因為含有更多的不必要資訊而更深更大,並因這些不必要資訊而降低對訓練集的擬合。這也是防止過擬合的一種方式。

當你預測到你的模型會過擬合,用這兩個引數來幫助你降低樹建成之後過擬合的可能性。當然,樹一旦建成,我們依然是使用剪枝引數來防止過擬合。

(3)剪枝引數:

  註釋:不加限制時,決策樹會生長到沒有更多的特徵可用為止,但這樣往往會造成過擬合,既訓練集上表現很好,測試集上表現卻很差。因此為了讓模型有更好的泛化性,我們需要

對決策樹進行剪枝。

  1)剪枝引數1:max_depth

  目的:限制樹的最大深度,超過設定深度的樹枝全部剪掉。在高緯度低樣本量時非常有效,決策樹每多生長一層,對樣本的需求量會增加一倍。所以限制樹的深度有利於防止過擬合。

  建議:實際使用時,建議從=3開始嘗試,看看擬合的效果在決定是否增加深度。

  2)剪枝引數2:min_samples_leaf & min_samples_split

  min_samples_leaf : 該引數限定,一個節點在分枝後的每個子節點都必須包含至少min_samples_leaf個訓練樣本,否則分支就不會發生。

建議:該引數設定的太小會引起過擬合,太大會阻止模型學習資料,一般搭配max_depth使用。

  min_samples_split : 該引數限定,一個節點必須包含至少min_samples_split個訓練樣本,這個節點才允許被分枝,否則分支就不會發生。

  3)剪枝引數3:max_features & min_impurity_decrease

  max_features : 該引數限定,分枝時需考慮的特徵個數,超過限制個數的特徵都會被捨棄。該引數是用來限制高緯度資料的過擬合的剪枝引數。

  min_impurity_decrease : 該引數限定資訊增益的大小,資訊增益小於設定數值的分枝不會發生。為0.19版本中更新的功能,0.19版本之前使用的時min_impurity_split。

  4)確定最優的剪枝引數的時候,可以採取如下方式:

import matplotlib.pyplot as plt
test = []
for i in range(10):
  clf = tree.DecisionTreeClassifier(max_depth=i+1
                         ,criterion="entropy"
                         ,random_state=30
                         ,splitter="random"
                                         )
  clf = clf.fit(Xtrain, Ytrain)
  score = clf.score(Xtest, Ytest)
  test.append(score)
plt.plot(range(1,11),test,color="red",label="max_depth")
plt.legend()
plt.show()

(4)目標權重引數:

  1)class_weight & min_weight_fraction_leaf

  class_weight :

    該引數預設為None,表示自動給資料集中所有標籤相同的權重

    該引數為‘blanced’時,每個類別的權重為該類別樣本數的倒數。個人覺得懲罰項就用樣本量的倒數未嘗不可,因為乘以樣本量都是1,相當於'balanced'這裡是多乘以了一個常數.

    也可手動輸入權重,程式碼舉例如下:     

import numpy as np

y = [0,0,0,0,0,0,0,0,1,1,1,1,1,1,2,2]  #標籤值,一共16個樣本

from sklearn.utils.class_weight import compute_class_weight 
class_weight = {0:1,1:3,2:5}   # {class_label_1:weight_1, class_label_2:weight_2, class_label_3:weight_3}
classes = np.array([0, 1, 2])  #標籤類別
weight = compute_class_weight(class_weight, classes, y)
print(weight)   # 輸出:[1. 3. 5.],也就是字典中設定的值

  min_weight_fraction_leaf : 有了權重之後,樣本量就不再是單純地記錄數目,而是受輸入的權重影響了,因此這時候剪枝,就需要搭配min_weight_fraction_leaf這個基於權重的剪枝引數來使用。

附::tree.DecisionTreeClassifier中的重要屬性與介面如下:

#對資料進行擬合
clf.fit(Xtrain,Ytrain)

#求得測試集的準確率
clf.score(Xtest,Ytest)

#apply返回每個測試樣本所在的葉子節點的索引
clf.apply(Xtest)

#predict返回每個測試樣本的分類/迴歸結果
clf.predict(Xtest)

總結:分類樹需要掌握的八個引數,一個屬性,四個介面:

八個引數:Criterion,兩個隨機性相關的引數(random_state,splitter),五個剪枝引數(max_depth,
min_samples_split,min_samples_leaf,max_feature,min_impurity_decrease)
一個屬性(該引數用於檢視哪個特徵對預測結果貢獻最大):feature_importances_
四個介面:fit,score,apply,predict

3.2、tree.DecisionTreeRegressor

class 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=False)

註釋:幾乎所有引數,屬性及介面都和分類樹一樣,但要注意的是,迴歸樹中沒有標籤分佈是否均衡的問題,依次沒有class_weight這樣的引數。

3.2.1重要引數屬性及介面:

(1)criterion:

   1)輸入‘mse’ : 使用均方誤差。mse的公式如下:

其中N是樣本數量,i是每一個數據樣本,fi是模型迴歸出的數值,yi是樣本點i實際的數值標籤。MSE的本質是樣本真實資料與迴歸結果的差異。

   2)輸入‘friedman_mse’ : 使用費爾德曼均方誤差。

   3)輸入‘mae’ : 使用絕對平均誤差MAE(mean absolute error)

(2)重要屬性:最重要的依然是feature_importances_

(3)重要介面:依然是apply,fit,pridect,score最核心。

3.2.2 介面score

  迴歸樹的介面score返回的是R平方,並不是MSE。R平方被定義如下:

其中u是殘差平方和(MSE*N),v是總平方和,N是樣本數量,i是每一個數據樣本,fi是模型迴歸出的數值,yi是樣本點i實際的數值標籤,y帽是真實數值標籤

的平均數。R平方可以為正也可為負,當模型的殘差平方和遠遠大於模型的總平方和,模型非常糟糕,R平方就會為負,而均方誤差永遠為正。但在sklearn中,

雖然均方誤差永遠為正,但是sklearn當中使用軍方誤差作為評判標準時,卻是計算的‘負均方誤差’,這是因為sklearn在計算模型評估指標的時候,會考慮指標本身的性質,

均方誤差本身是一種誤差,所以被sklearn劃分為模型的一種損失(loss),因此在sklearn當中,都以負數表示。真正的均方誤差MSE的數值,其實就是neg_mean_squared_error

去掉負號的數字。

例項:

from sklearn.datasets import load_boston
from sklearn.model_selection import cross_val_score
from sklearn.tree import DecisionTreeRegressor
boston = load_boston()
regressor = DecisionTreeRegressor(random_state=0)
cross_val_score(regressor, boston.data, boston.target, cv=10,
        scoring = "neg_mean_squared_error")

3.3、tree.export_graphviz()

目的:繪圖專用,將生成的決策樹轉化為dot格式,方便視覺化。

例項:

例1:

feature_name = ['酒精','蘋果酸','','灰的鹼性','','總酚','類黃酮','非黃烷類酚類','花青素','顏色強度','色調','od280/od315稀釋葡萄酒','脯氨酸']
import graphviz
dot_data = tree.export_graphviz(clf
                                ,feature_names= feature_name
                                ,class_names=["琴酒","雪莉","貝爾摩德"] # 標籤名字
                                ,filled=True        # 到底填不填充顏色,顏色越深,代表不純度越低,且葉子節點的每個顏色代表一個類別。
                                ,rounded=True       # 框的形狀
                                ,out_file=None
                               )
graph = graphviz.Source(dot_data)     # 將我們畫的樹給匯出來
graph

例2:

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 = graphviz.Source(dot_data)  
graph

其中,out_file為dot輸出的目錄;

   feature_names為特徵的名字;

   class_names為標籤的名字;

   filled=True,到底填補填充顏色,顏色越深,代表不純度越低,且葉子節點的每個顏色代表一個類別。

   rounded=True,為框的形狀。

高隨機版本的分類樹和迴歸樹暫時先不記筆記。