機器學習Sklearn系列:(三)決策樹

Neo0oeN發表於2021-07-16

決策樹

熵的定義

如果一個隨機變數X的可能取值為X={x1,x2,..,xk},其概率分佈為P(X=x)=pi(i=1,2,...,n),則隨機變數X的熵定義為\(H(x) = -\sum{p(x)logp(x)}=\sum{p(x)log{\frac{1}{p(x)}}}\)。需要注意的是,熵越大,隨機變數的不確定性就越大。

當n = 2的時候,\(H(p)=-plogp-(1-p)log(1-p)\)也就是交叉熵的損失函式。

條件熵

條件熵主要是用來計算,在莫一列資料X選中的條件下,其標籤Y的熵大小,這樣可以幫助計算,那一列資料對應的標籤更加簡潔易分。 條件熵計算公式如下,其中,\(p_i =P(X=x_i)\)

\[H(Y|X) = \sum_{i=1}^n p_iH(Y|X=x_i) \]

具體來說,條件熵公式如何使用到結構化的資料中來的,這裡的X表示的某一列的特徵,Xi表示該特徵的一個子類特徵,這裡\(H(Y_i)\)表示Xi這一類子特徵對應的標籤Y的熵。K表示標籤的類別,下面公式中,\(Y_{ik}\),表示第Xi類特徵對應的標籤\(Y_i\)的種類。

\[\begin{equation} \begin{aligned} H(Y|X) &= \sum^n_{i=1}\frac{|X_i|}{|X|}H(Y_i) \\ &= -\sum^n_{i=1}\frac{|X_i|}{|X|}(\sum^K_{k=1}\frac{|Y_{ik}|}{|Y_i|}log_2\frac{|Y_{ik}|}{|Y_i|}) \end{aligned} \end{equation} \]

舉個具體的例子:

特徵X 標籤Y
1 1
1 0
1 1
1 1
2 1
2 1
2 0

這對特徵Xi = 1的條件熵的計算如下:

\[H(Y|X_{i=1}) = -\frac{4}{7}(\frac{1}{4}log_2\frac{1}{4} + \frac{3}{4}log_2\frac{3}{4}) \]

資訊增益

資訊增益的計算方式如下,其中,由於H(D)是個固定值,H(D|A)越小,資訊增益就越大,這樣這個特徵就越簡潔,也就是說這個特徵能夠最大化的去區分label , 這裡 X代表的是莫一列特徵,Y代表的是資料集的標籤。

\[g(Y,X) = H(Y)-H(Y|X) \]

決策樹演算法

ID3

ID3 演算法和原理就是,使用資訊增益來挑選特徵,優先挑選資訊增益最大的特徵。其具體決策樹生成過程如下:

1. 首先計算所有特徵的資訊增益,挑選一個最大的特徵,作為節點的特徵
2. 對挑選出來的子節點遞迴呼叫方法 1
3. 當特徵資訊增益小於閾值,或者沒有特徵可以選擇,或者可選特徵小於閾值等,停止。

C4.5演算法

上述演算法有一個問題,假設特徵X有兩列特徵,其資訊增益差不多,但是某一列資料特別混亂,這個時候應該避免選擇這一列作為根結點,而C4.5演算法的核心就是通過給資訊增益下面,除一個這一列特徵的熵,從而減少這一列資料的資訊增益。也就是說,如果某一列特徵越混亂,那麼其最終得到的資訊增益就越小,從而避免了上述的問題。 具體公式為:

\[g_R(Y,X) = \frac{g(Y,X)}{H_X(Y)} \]

其中,n為

\[H_X(Y)=-\sum_{i=1}^n\frac{|X_i|}{|X|}log_2\frac{X_i}{X} \]

CART演算法

CART演算法的思路和上面兩個演算法是一樣的,只不過這裡用來評估特徵混亂度的方法是用的基尼指數。其中,基尼指數越大,不確定性越大,和熵是類似的。

基尼指數的定義如下:其中,\(p_k\)為樣本點屬於第k類的概率。

\[Gini(p) = \sum^K_{k=1}p_k(1-p_k)=1-\sum^K_{k=1}p_k^2 \]

如果將基尼指數用到結構化資料集中:

\[Gini(Y) = 1-\sum_{k=1}^K(\frac{|Y_k|}{Y})^2 \]

在特徵為X標籤為Y的條件下,其基尼指數為:其中,\(Y_1,Y_2\)表示,特徵X下的子類別\(X_1,X_2\)對應的標籤。

\[Gini(Y,X) = \frac{|X_1|}{|X|}Gini(Y_1)+\frac{|X_2|}{|X|}Gini(Y_2) \]

決策樹剪肢

決策樹減肢可以減輕決策樹的複雜度,同時確保決策樹能夠保持一定的正確率,剪肢的方法,一般是從最深的一層開始,減去節點,然後看accuracy,如果accuracy提升了,就可以減去。也可以使用其他基於閾值的方法,例如下一層的不純度低於某個閾值,就可以直接不分裂等等。

sklearn中決策樹的使用

引數

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, ccp_alpha=0.0)

criterion{“gini”, “entropy”}, default=”gini” 確定決策樹是基於基尼指數還是熵

max_depth 樹的層數,限制樹的最大深度,超過設定深度的樹枝全部剪掉,這是用得最廣泛的剪枝引數,在高維度低樣本量時非常有效。決策樹多生長一層,對樣本量的需求會增加一倍,所以限制樹深度能夠有效地限制過擬合。在整合演算法中也非常實用。實際使用時,建議從=3開始嘗試,看看擬合的效果再決定是否增加設定深度。實際層數為 max_depth +1 考慮根

min_impurity_decrease 限制決策樹的生長,如果節點的不純度(GINI,GAIN)小於這個閾值,就不在生成子節點

min_impurity_split :不純度必須大於這個值,不然不分裂

min_impurity_decrease限制資訊增益的大小,資訊增益小於設定數值的分枝不會發生。這是在0.19版本種更新的功能,在0.19版本之前時使用min_impurity_split。

random_state 隨機數種子,固定種子之後,訓練的模型是一樣的

class_weight 可以用來定義某一個類別的權重,讓這一個類比在計算的時候,資訊增益變得稍微大一些

splitter也是用來控制決策樹中的隨機選項的,有兩種輸入值,輸入”best",決策樹在分枝時雖然隨機,但是還是會優先選擇更重要的特徵進行分枝(重要性可以通過屬性feature_importances_檢視),輸入“random",決策樹在分枝時會更加隨機,樹會因為含有更多的不必要資訊而更深更大,並因這些不必要資訊而降低對訓練集的擬合。這也是防止過擬合的一種方式。當你預測到你的模型會過擬合,用這兩個引數來幫助你降低樹建成之後過擬合的可能性。當然,樹一旦建成,我們依然是使用剪枝引數來防止過擬合。所以要想泛化好,最好splitter設定成random。

和剪肢相關的引數:

min_samples_leaf ** ** 限定,一個節點在分枝後的每個子節點都必須包含至少min_samples_leaf個訓練樣本,否則分枝就不會發生,或者,分枝會朝著滿足每個子節點都包含min_samples_leaf個樣本的方向去發生

一般搭配max_depth使用,在迴歸樹中有神奇的效果,可以讓模型變得更加平滑。這個引數的數量設定得太小會引起過擬合,設定得太大就會阻止模型學習資料。一般來說,建議從=5開始使用。如果葉節點中含有的樣本量變化很大,建議輸入浮點數作為樣本量的百分比來使用。同時,這個引數可以保證每個葉子的最小尺寸,可以在迴歸問題中避免低方差,過擬合的葉子節點出現。對於類別不多的分類問題,=1通常就是最佳選擇。

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

max_features限制分枝時考慮的特徵個數,比如一個樣本特徵為13個,限制之後只能使用有限個特徵進行分類任務。超過限制個數的特徵都會被捨棄。和max_depth異曲同工,max_features是用來限制高維度資料的過擬合的剪枝引數,但其方法比較暴力,是直接限制可以使用的特徵數量而強行使決策樹停下的引數,在不知道決策樹中的各個特徵的重要性的情況下,強行設定這個引數可能會導致模型學習不足。如果希望通過降維的方式防止過擬合,建議使用PCA,ICA或者特徵選擇模組中的降維演算法。

class_weight 標籤權重,給某一類的標籤更大的權重,當樣本不均衡的時候,可以考慮使用

min_weight_fraction_leaf有了權重之後,樣本量就不再是單純地記錄數目,而是受輸入的權重影響了,因此這時候剪枝,就需要搭配min_ weight_fraction_leaf這個基於權重的剪枝引數來使用。另請注意,基於權重的剪枝引數(例如min_weight_ fraction_leaf)將比不知道樣本權重的標準(比如min_samples_leaf)更少偏向主導類。如果樣本是加權的,則使用基於權重的預修剪標準來更容易優化樹結構,這確保葉節點至少包含樣本權重的總和的一小部分。

注意在sklearn中實現的決策樹都是二叉樹

使用模型訓練資料:

model = tree.DecisionTreeClassifier()

model.fit(X,y)

model.predict(X_val)

sklearn中,可以輸出決策樹特徵的重要性

clf.feature_importances_

迴歸樹

在分類問題中決策樹的每一片葉子都代表的是一個 class;在迴歸問題中,決策樹的每一片葉子表示的是一個預測值,取值是連續的。

決策樹還可以做迴歸任務,迴歸樹種的引數和上面分類樹的引數是一模一樣的,唯一的區別是,迴歸樹沒有class_weight這個引數,因為沒有類別不平衡這個說法

X = [[0, 0], [2, 2]]
y = [0.5, 2.5]

clf = tree.DecisionTreeRegressor()
clf = clf.fit(X, y)
clf.predict([[1, 1]])


array([0.5])

決策樹視覺化

可以使用graphviz安裝包:pip install graphviz

一個例子:

這裡的引數,class_names 表示類別的名稱,filled表示填充顏色,rounded 表示框的形狀

feature_name = ["A","B","C"]
​
import graphviz

dot_data = tree.export_graphviz(clf
                                ,feature_names= feature_name
                                ,class_names=["1","2","3"]
                                ,filled=True
                                ,rounded=True
                                ,out_file=None
                               )
graph = graphviz.Source(dot_data)
graph

相關文章