通俗地說決策樹算法(三)sklearn決策樹實戰


前情提要

通俗地說決策樹算法(一)基礎概念介紹

通俗地說決策樹算法(二)實例解析

上面兩篇介紹了那么多決策樹的知識,現在也是時候來實踐一下了。Python有一個著名的機器學習框架,叫sklearn。我們可以用sklearn來運行前面說到的賴床的例子。不過在這之前,我們需要介紹一下sklearn中訓練一顆決策樹的具體參數。

另外sklearn中訓練決策樹的默認算法是CART,使用CART決策樹的好處是可以用它來進行回歸和分類處理,不過這里我們只進行分類處理。

一. sklearn決策樹參數詳解

我們都知道,一個模型中很重要的一步是調參。在sklearn中,模型的參數是通過方法參數來決定的,以下給出sklearn中,決策樹的參數:

DecisionTreeClassifier(criterion="gini",
                 splitter="best",
                 max_depth=None,
                 min_samples_split=2,
                 min_samples_leaf=1,
                 min_weight_fraction_leaf=0.,
                 max_features=None,
                 random_state=None,
                 max_leaf_nodes=None,
                 min_impurity_decrease=0.,
                 min_impurity_split=None,
                 class_weight=None,
                 presort=False)

參數含義:
1.criterion:string, optional (default="gini")
            (1).criterion='gini',分裂節點時評價准則是Gini指數。
            (2).criterion='entropy',分裂節點時的評價指標是信息增益。
2.max_depth:int or None, optional (default=None)。指定樹的最大深度。
            如果為None,表示樹的深度不限。直到所有的葉子節點都是純凈的,即葉子節點
            中所有的樣本點都屬於同一個類別。或者每個葉子節點包含的樣本數小於min_samples_split。
3.splitter:string, optional (default="best")。指定分裂節點時的策略。
           (1).splitter='best',表示選擇最優的分裂策略。
           (2).splitter='random',表示選擇最好的隨機切分策略。
4.min_samples_split:int, float, optional (default=2)。表示分裂一個內部節點需要的做少樣本數。
           (1).如果為整數,則min_samples_split就是最少樣本數。
           (2).如果為浮點數(0到1之間),則每次分裂最少樣本數為ceil(min_samples_split * n_samples)
5.min_samples_leaf: int, float, optional (default=1)。指定每個葉子節點需要的最少樣本數。
           (1).如果為整數,則min_samples_split就是最少樣本數。
           (2).如果為浮點數(0到1之間),則每個葉子節點最少樣本數為ceil(min_samples_leaf * n_samples)
6.min_weight_fraction_leaf:float, optional (default=0.)
           指定葉子節點中樣本的最小權重。
7.max_features:int, float, string or None, optional (default=None).
           搜尋最佳划分的時候考慮的特征數量。
           (1).如果為整數,每次分裂只考慮max_features個特征。
           (2).如果為浮點數(0到1之間),每次切分只考慮int(max_features * n_features)個特征。
           (3).如果為'auto'或者'sqrt',則每次切分只考慮sqrt(n_features)個特征
           (4).如果為'log2',則每次切分只考慮log2(n_features)個特征。
           (5).如果為None,則每次切分考慮n_features個特征。
           (6).如果已經考慮了max_features個特征,但還是沒有找到一個有效的切分,那么還會繼續尋找
           下一個特征,直到找到一個有效的切分為止。
8.random_state:int, RandomState instance or None, optional (default=None)
           (1).如果為整數,則它指定了隨機數生成器的種子。
           (2).如果為RandomState實例,則指定了隨機數生成器。
           (3).如果為None,則使用默認的隨機數生成器。
9.max_leaf_nodes: int or None, optional (default=None)。指定了葉子節點的最大數量。
           (1).如果為None,葉子節點數量不限。
           (2).如果為整數,則max_depth被忽略。
10.min_impurity_decrease:float, optional (default=0.)
         如果節點的分裂導致不純度的減少(分裂后樣本比分裂前更加純凈)大於或等於min_impurity_decrease,則分裂該節點。
         加權不純度的減少量計算公式為:
         min_impurity_decrease=N_t / N * (impurity - N_t_R / N_t * right_impurity
                            - N_t_L / N_t * left_impurity)
         其中N是樣本的總數,N_t是當前節點的樣本數,N_t_L是分裂后左子節點的樣本數,
         N_t_R是分裂后右子節點的樣本數。impurity指當前節點的基尼指數,right_impurity指
         分裂后右子節點的基尼指數。left_impurity指分裂后左子節點的基尼指數。
11.min_impurity_split:float
         樹生長過程中早停止的閾值。如果當前節點的不純度高於閾值,節點將分裂,否則它是葉子節點。
         這個參數已經被棄用。用min_impurity_decrease代替了min_impurity_split。
12.class_weight:dict, list of dicts, "balanced" or None, default=None
         類別權重的形式為{class_label: weight}
         (1).如果沒有給出每個類別的權重,則每個類別的權重都為1。
         (2).如果class_weight='balanced',則分類的權重與樣本中每個類別出現的頻率成反比。
         計算公式為:n_samples / (n_classes * np.bincount(y))
         (3).如果sample_weight提供了樣本權重(由fit方法提供),則這些權重都會乘以sample_weight。
13.presort:bool, optional (default=False)
        指定是否需要提前排序數據從而加速訓練中尋找最優切分的過程。設置為True時,對於大數據集
        會減慢總體的訓練過程;但是對於一個小數據集或者設定了最大深度的情況下,會加速訓練過程。

雖然看起來參數眾多,但通常參數都會有默認值,我們只需要調整其中較為重要的幾個參數就行。

通常來說,較為重要的參數有:

  1. criterion:用以設置用信息熵還是基尼系數計算。
  2. splitter:指定分支模式
  3. max_depth:最大深度,防止過擬合
  4. min_samples_leaf:限定每個節點分枝后子節點至少有多少個數據,否則就不分枝

二. sklearn決策樹實戰

2.1 准備數據及讀取

數據就是上次說到的賴床特征,

季節 時間已過 8 點 風力情況 要不要賴床
spring no breeze yes
winter no no wind yes
autumn yes breeze yes
winter no no wind yes
summer no breeze yes
winter yes breeze yes
winter no gale yes
winter no no wind yes
spring yes no wind no
summer yes gale no
summer no gale no
autumn yes breeze no

將它存儲成 csv 文件

spring,no,breeze,yes
winter,no,no wind,yes
autumn,yes,breeze,yes
winter,no,no wind,yes
summer,no,breeze,yes
winter,yes,breeze,yes
winter,no,gale,yes
winter,no,no wind,yes
spring,yes,no wind,no
summer,yes,gale,no
summer,no,gale,no
autumn,yes,breeze,no

2.2 決策樹的特征向量化DictVectorizer

sklearn的DictVectorizer能對字典進行向量化。什么叫向量化呢?比如說你有季節這個屬性有[春,夏,秋,冬]四個可選值,那么如果是春季,就可以用[1,0,0,0]表示,夏季就可以用[0,1,0,0]表示。不過在調用DictVectorizer它會將這些屬性打亂,不會按照我們的思路來運行,但我們也可以一個方法查看,我們看看代碼就明白了。

import pandas as pd
from sklearn.feature_extraction import DictVectorizer
from sklearn import tree
from sklearn.model_selection import train_test_split

#pandas 讀取 csv 文件,header = None 表示不將首行作為列
data = pd.read_csv('data/laic.csv',header =None)
#指定列
data.columns = ['season','after 8','wind','lay bed']

#sparse=False意思是不產生稀疏矩陣
vec=DictVectorizer(sparse=False)
#先用 pandas 對每行生成字典,然后進行向量化
feature = data[['season','after 8','wind']]
X_train = vec.fit_transform(feature.to_dict(orient='record'))
#打印各個變量
print('show feature\n',feature)
print('show vector\n',X_train)
print('show vector name\n',vec.get_feature_names())

我們來看看打印的結果:

show feature
     season after 8     wind
0   spring      no   breeze
1   winter      no  no wind
2   autumn     yes   breeze
3   winter      no  no wind
4   summer      no   breeze
5   winter     yes   breeze
6   winter      no     gale
7   winter      no  no wind
8   spring     yes  no wind
9   summer     yes     gale
10  summer      no     gale
11  autumn     yes   breeze
show vector
 [[1. 0. 0. 1. 0. 0. 1. 0. 0.]
 [1. 0. 0. 0. 0. 1. 0. 0. 1.]
 [0. 1. 1. 0. 0. 0. 1. 0. 0.]
 [1. 0. 0. 0. 0. 1. 0. 0. 1.]
 [1. 0. 0. 0. 1. 0. 1. 0. 0.]
 [0. 1. 0. 0. 0. 1. 1. 0. 0.]
 [1. 0. 0. 0. 0. 1. 0. 1. 0.]
 [1. 0. 0. 0. 0. 1. 0. 0. 1.]
 [0. 1. 0. 1. 0. 0. 0. 0. 1.]
 [0. 1. 0. 0. 1. 0. 0. 1. 0.]
 [1. 0. 0. 0. 1. 0. 0. 1. 0.]
 [0. 1. 1. 0. 0. 0. 1. 0. 0.]]
show vector name
 ['after 8=no', 'after 8=yes', 'season=autumn', 'season=spring', 'season=summer', 'season=winter', 'wind=breeze', 'wind=gale', 'wind=no wind']

通過DictVectorizer,我們就能夠把字符型的數據,轉化成0 1的矩陣,方便后面進行運算。額外說一句,這種轉換方式其實就是one-hot編碼

2.4 決策樹訓練

可以發現在向量化的時候,屬性都被打亂了,但我們也可以通過get_feature_names()這個方法查看對應的屬性值。有了數據后,就可以來訓練一顆決策樹了,用sklearn很方便,只需要很少的代碼

#划分成訓練集,交叉集,驗證集,不過這里我們數據量不夠大,沒必要
#train_x, test_x, train_y, test_y = train_test_split(X_train, Y_train, test_size = 0.3)
#訓練決策樹
clf = tree.DecisionTreeClassifier(criterion='gini')
clf.fit(X_train,Y_train)

#保存成 dot 文件,后面可以用 dot out.dot -T pdf -o out.pdf 轉換成圖片
with open("out.dot", 'w') as f :
    f = tree.export_graphviz(clf, out_file = f,
            feature_names = vec.get_feature_names())

2.5 決策樹可視化

當完成一棵樹的訓練的時候,我們也可以讓它可視化展示出來,不過sklearn沒有提供這種功能,它僅僅能夠讓訓練的模型保存到dot文件中。但我們可以借助其他工具讓模型可視化,先看保存到dot的代碼:

from sklearn import tree
with open("out.dot", 'w') as f :
    f = tree.export_graphviz(clf, out_file = f,
            feature_names = vec.get_feature_names())

決策樹可視化我們用Graphviz這個東西。當然需要先用pip安裝對應的庫類。然后再去官網下載它的一個發行版本,用以將dot文件轉化成pdf圖片。

官網下載方式如下:

然后進入到上面保存好的dot所在目錄,打開cmd運行dot out.dot -T pdf -o out.pdf 命令,pdf 圖片就會出現了。

小結:

今天我們介紹了sklearn,決策樹模型的各個參數,並且使用sklearn模型對上一節中的例子訓練出一個決策樹模型,然后用Graphviz讓決策樹模型可視化。到此,決策樹算法算是講完啦。

以上


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM