1. 程式人生 > >第4章 決策樹演算法【分類】(五 決策樹sklearn總結和視覺化總結)

第4章 決策樹演算法【分類】(五 決策樹sklearn總結和視覺化總結)

4.7 決策樹sklearn總結

參考文件:
中文連結
英文連結
API:
中文連結
英文連結

scikit-learn決策樹演算法類庫內部實現是使用了調優過的CART樹演算法,既可以做分類,又可以做迴歸。分類決策樹的類對應的是DecisionTreeClassifier。
sklearn.tree模組提供了決策樹模型,用於解決分類問題和迴歸問題。方法如下所示:

在這裡插入圖片描述

我們先看下DecisionTreeClassifier這個函式,一共有12個引數:

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)

引數說明如下:

  • criterion:特徵選擇標準,可選引數,預設是gini,可以設定為entropy。gini是基尼不純度,是將來自集合的某種結果隨機應用於某一資料項的預期誤差率,是一種基於統計的思想。entropy是夏農熵,也就是上篇文章講過的內容,是一種基於資訊理論的思想。Sklearn把gini設為預設引數,應該也是做了相應的斟酌的,精度也許更高些?ID3演算法使用的是entropy,CART演算法使用的則是gini。
  • splitter:特徵劃分點選擇標準,可選引數,預設是best,可以設定為random。每個結點的選擇策略。best引數是根據演算法選擇最佳的切分特徵,例如gini、entropy。random隨機的在部分劃分點中找區域性最優的劃分點。預設的”best”適合樣本量不大的時候,而如果樣本資料量非常大,此時決策樹構建推薦”random”。
  • max_features:劃分時考慮的最大特徵數,可選引數,預設是None。尋找最佳切分時考慮的最大特徵數(n_features為總共的特徵數),有如下6種情況:
    如果max_features是整型的數,則考慮max_features個特徵;
    如果max_features是浮點型的數,則考慮int(max_features * n_features)個特徵;
    如果max_features設為auto,那麼max_features = sqrt(n_features);
    如果max_features設為sqrt,那麼max_featrues = sqrt(n_features),跟auto一樣;
    如果max_features設為log2,那麼max_features = log2(n_features);
    如果max_features設為None,那麼max_features = n_features,也就是所有特徵都用。
    一般來說,如果樣本特徵數不多,比如小於50,我們用預設的”None”就可以了,如果特徵數非常多,我們可以靈活使用剛才描述的其他取值來控制劃分時考慮的最大特徵數,以控制決策樹的生成時間。
  • max_depth:決策樹最大深,可選引數,預設是None。這個引數是這是樹的層數的。層數的概念就是,比如在貸款的例子中,決策樹的層數是2層。如果這個引數設定為None,那麼決策樹在建立子樹的時候不會限制子樹的深度。一般來說,資料少或者特徵少的時候可以不管這個值。或者如果設定了min_samples_slipt引數,那麼直到少於min_smaples_split個樣本為止。如果模型樣本量多,特徵也多的情況下,推薦限制這個最大深度,具體的取值取決於資料的分佈。常用的可以取值10-100之間。
  • min_samples_split:內部節點再劃分所需最小樣本數,可選引數,預設是2。這個值限制了子樹繼續劃分的條件。如果min_samples_split為整數,那麼在切分內部結點的時候,min_samples_split作為最小的樣本數,也就是說,如果樣本已經少於min_samples_split個樣本,則停止繼續切分。如果min_samples_split為浮點數,那麼min_samples_split就是一個百分比,ceil(min_samples_split * n_samples),數是向上取整的。如果樣本量不大,不需要管這個值。如果樣本量數量級非常大,則推薦增大這個值。
  • min_weight_fraction_leaf:葉子節點最小的樣本權重和,可選引數,預設是0。這個值限制了葉子節點所有樣本權重和的最小值,如果小於這個值,則會和兄弟節點一起被剪枝。一般來說,如果我們有較多樣本有缺失值,或者分類樹樣本的分佈類別偏差很大,就會引入樣本權重,這時我們就要注意這個值了。
  • max_leaf_nodes:最大葉子節點數,可選引數,預設是None。通過限制最大葉子節點數,可以防止過擬合。如果加了限制,演算法會建立在最大葉子節點數內最優的決策樹。如果特徵不多,可以不考慮這個值,但是如果特徵分成多的話,可以加以限制,具體的值可以通過交叉驗證得到。
  • class_weight:類別權重,可選引數,預設是None,也可以字典、字典列表、balanced。指定樣本各類別的的權重,主要是為了防止訓練集某些類別的樣本過多,導致訓練的決策樹過於偏向這些類別。類別的權重可以通過{class_label:weight}這樣的格式給出,這裡可以自己指定各個樣本的權重,或者用balanced,如果使用balanced,則演算法會自己計算權重,樣本量少的類別所對應的樣本權重會高。當然,如果你的樣本類別分佈沒有明顯的偏倚,則可以不管這個引數,選擇預設的None。
  • random_state:可選引數,預設是None。隨機數種子。如果是證書,那麼random_state會作為隨機數生成器的隨機數種子。隨機數種子,如果沒有設定隨機數,隨機出來的數與當前系統時間有關,每個時刻都是不同的。如果設定了隨機數種子,那麼相同隨機數種子,不同時刻產生的隨機數也是相同的。如果是RandomState instance,那麼random_state是隨機數生成器。如果為None,則隨機數生成器使用np.random。
  • min_impurity_split:節點劃分最小不純度,可選引數,預設是1e-7。這是個閾值,這個值限制了決策樹的增長,如果某節點的不純度(基尼係數,資訊增益,均方差,絕對差)小於這個閾值,則該節點不再生成子節點。即為葉子節點 。
  • presort:資料是否預排序,可選引數,預設為False,這個值是布林值,預設是False不排序。一般來說,如果樣本量少或者限制了一個深度很小的決策樹,設定為true可以讓劃分點選擇更加快,決策樹建立的更加快。如果樣本量太大的話,反而沒有什麼好處。

除了這些引數要注意以外,其他在調參時的注意點有:

  • 當樣本數量少但是樣本特徵非常多的時候,決策樹很容易過擬合,一般來說,樣本數比特徵數多一些會比較容易建立健壯的模型
  • 如果樣本數量少但是樣本特徵非常多,在擬合決策樹模型前,推薦先做維度規約,比如主成分分析(PCA),特徵選擇(Losso)或者獨立成分分析(ICA)。這樣特徵的維度會大大減小。再來擬合決策樹模型效果會好。
  • 推薦多用決策樹的視覺化,同時先限制決策樹的深度,這樣可以先觀察下生成的決策樹裡資料的初步擬合情況,然後再決定是否要增加深度。
    -在訓練模型時,注意觀察樣本的類別情況(主要指分類樹),如果類別分佈非常不均勻,就要考慮用class_weight來限制模型過於偏向樣本多的類別。
    -決策樹的陣列使用的是numpy的float32型別,如果訓練資料不是這樣的格式,演算法會先做copy再執行。
  • 如果輸入的樣本矩陣是稀疏的,推薦在擬合前呼叫csc_matrix稀疏化,在預測前呼叫csr_matrix稀疏化。

4.8決策樹視覺化環境搭建與使用總結

scikit-learn中決策樹的視覺化一般需要安裝graphviz。首先需要安裝Graphviz,筆者使用的是Anaconda整合環境,只需在在終端視窗輸入:
conda install python-graphviz
pip3 install graphviz

筆者使用兩種方式。
方式一:
用graphviz的dot命令生成決策樹的視覺化檔案,敲完這個命令後當前目錄就可以看到決策樹的視覺化檔案iris.pdf.開啟可以看到決策樹的模型圖。
需要在程式碼中新增如下程式碼。

   with open("iris.dot", 'w') as f:
        f = tree.export_graphviz(clf, out_file=f)

執行成功後會在目錄下生成Infor_Gain.dot的檔案,需要轉化dot檔案至pdf視覺化決策樹。
dot -Tpdf iris.dot -o output.pdf

方式二:可以直接生成pdf

"""
    dot_data = tree.export_graphviz(clf, out_file=None) 

    """
    #高階配置
    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.render("tree")

【完整程式碼參考附件6.DT_Iris_Visual-sklearn\D6.DT_Iris_Visual-sklearn.py】

本章參考程式碼
點選進入