機器學習-決策樹

jiangjiane發表於2017-08-21

決策樹

李鵬-南開百度聯合實驗室

決策樹

基本介紹

決策樹是一個樹結構,它既可以是二叉樹,也可以是多叉樹。
它的每一個非葉子節點代表對某一個屬性的測試,而每一個葉子節點存放具體的類別。
它的決策從根節點開始,根據分支節點來測試屬性並進入到樹的下層相應的分支,直到抵達葉子節點得到類別。
決策樹是基於樹結構進行決策的,這符合我們對問題的決策方案,可解釋性較強。
當我們判斷一個人能不能償還債務的時候,我們需要關注這個人的收入情況,這個人的家庭的財產狀況(例如是否有房子可以抵押)等等。
在經過一系列的屬性判斷決策之後,我們會得到判斷他能不能償還債務。

優點:
模型可以直接視覺化,可解釋性強,既可以用於分類也可以用於迴歸,演算法複雜度低,既可以處理離散屬性,也可以處理連續性屬性。

缺點:樹的結果不宜過度複雜,容易過擬合。可以限制樹的深度,葉子節點樣本的數量等剪枝策略來緩解過擬合。
隨機森林中使用多顆決策樹以及隨機選擇屬性的方式來降低過擬合的風險。
不過這個屬於bagging的範疇,後面會單獨出一章來講解bagging和boosting的相關內容。

引用一個例子,來源(2)

先看一個根據房產,婚姻以及年收入來判斷是否能夠償還債務的資料表格:

fig-example.png,

Fig. 1: 不同人是否可以償還債務的資料集

通過該資料,構建的決策樹如下:

fig-example-tree.png,

Fig. 2: 根據上述資料表格構建的決策樹

根據構建的決策樹,對於新來的樣本就可以順著決策樹的的分支來確定他是否可以償還債務。

訓練

決策樹的訓練過程就是樹以及分支節點測試條件進行構建的過程。
我們首先從根節點開始,採用貪心演算法來選擇某一個屬性的某一種值進行劃分成幾(二叉樹的話為2)個部分,形成它的子分支;對於它的子分支,遞迴進行此劃分操作。
這引出兩個問題:(1) 如何劃分屬性,(2)如何選擇屬性

如何劃分屬性

對於一個人的收入狀況,如果是用連續的值表示,那我們該如何對收入進行劃分呢?如果是用離散的”高”,”中等”或者”低”,該如何劃分呢?具體請參見Section屬性劃分。

如何選擇屬性

回顧我們的樹構建過程。它從根節點貪心的選擇一個屬性的最優劃分,然後劃分成子分支。那麼對屬性或者劃分進行貪心選擇的目的是什麼呢?
讓它的各個子分支儘可能的”純”,或者說使它的各個子分支的所屬類別儘可能的相同。
這很容易引出一個問題,如何定義一個分支的純度呢?具體請參見Section純度的界定,Section貪心選擇

屬性劃分

  1. 屬性的取值離散,且不要求是二叉樹,可以直接用屬性的各個值形成不同的分支。例如一個人的收入屬性有”高”,”中等”和”低”三種類別,那麼按照收入劃分的話,就可以直接劃分為3個分支

  2. 屬性的取值離散,且要求是二叉樹,那就需要把屬性的取值劃分成兩個集合,並分別測試哪種劃分效果最好。例如收入屬性可以嘗試”高,中等”和”低”這種劃分

  3. 屬性的取值連續,且要求是二叉樹,這時候需要選擇連續值的某一個值point為分界點,以>point

    >point
    <=point
    <=point
    分成兩部分。為了選取point,可以將全部樣本的這列屬性的值排序,然後不斷嘗試連續的兩個值的中值作為分界點。

  4. 屬性的取值連續,且不要求是二叉樹,很少會有,可以採用將連續的值域範圍切成幾個塊,然後每個塊分到一個分支中。

“純度”的界定

本節主要包括純度的定義,以及經過某一次劃分後純度提升的”“量。這個”量”有多種衡量的標準,從而有了以下三種演算法:

ID3演算法

對於一個資料集合,如何定義它的”純度”呢?回憶上一章中”熵”的定義,熵衡量了傳輸資訊所需要的最小的資料量。資訊越純,它含有的資訊量越小。因此我們可以直接用熵=

=
純度,也就是它的資訊量。

D

D
表示使用樣本的類別,也就是樣本的值對樣本進行的劃分,則D
D
的熵為

H(D)=ipilogpi
H(D) = -\sum_{i} p_i \log p_i

其中pi
p_i
為第i
i
個類別的在訓練樣本中出現的概率,它可以使用第i
i
個類別的樣本數除以總的樣本數來求得。

有了純度的定義,對於給定的一個劃分,我們來計算經過這次劃分後它的純度的度量。
我們假定通過屬性A進行劃分,那麼劃分後的熵為

HA(D)=j=1v|Dj||D|H(Dj)
H_A(D) = \sum_{j=1}^{v} \frac{|D_j|}{|D|} H(D_j)

其中Dj
D_j
表示屬性A的值為j
j
的樣本,|Dj|
|D_j|
表示的是樣本數。也就是說通過屬性A
A
對訓練樣本集合D
D
劃分成了v
v
個分支,HA(D)
H_A(D)
表達的是各個分支的熵的期望平均值(各個分支的熵乘以各個分支所佔的樣本比例)。

利用劃分前的熵H(D)

H(D)
,以及劃分後的HA(D)
H_A(D)
,我們有經過這次劃分後的資訊增益:

Gain(D,A)=H(D)HA(D)
Gain(D, A) = H(D) - H_A(D)

C4.5演算法

ID3演算法有一個明顯的不足,它一般會優先選擇有較多屬性值得feature,即|v|

|v|
比較大的feature。
例如資料集合D有一列屬性叫ID
ID
,它是各個樣本的唯一標識,且在各個訓練樣本中都不相同,因此通過ID
ID
進行劃分後,每個子分支都只有一個樣本,且最純,即每一個子分支的熵都為0
0
。這樣劃分之後的資訊熵為達到最小值0
0
,也就是說
我們獲得了最大的資訊增益。然而,我們知道ID
ID
原本就不具有分類的意義。

C4.5演算法就是為了克服這種多值屬性的不足而出現的。如同我們的預期,我們可以對這樣的值比較多的屬性增加懲罰項,我們的懲罰項用分裂資訊(split
information)來衡量,它記錄的是各個子分支中樣本數量的純度。即

SplitInfo(D,A)=i=1v|Di||D|log|Di||D|
SplitInfo(D, A) = -\sum_{i=1}^{v} \frac{|D_i|}{|D|} \log \frac{|D_i|}{|D|}

根據熵的概念,我們可以知道v
v
越大,即值越多,SplitInfo越大;|Di|
|D_i|
之間相差越小,SplitInfo越大。從而,對於前面所說的ID
ID
分割的問題,我們很容易有懲罰項SplitInfo非常大。

有了懲罰項,很顯然,它應該跑到資訊增益的分母上來進行懲罰,從而我們有資訊增益率

Gainratio(D,A)=Gain(D,A)SplitInfo(D,A)
Gain_{ratio}(D, A) = \frac{Gain(D, A)}{SplitInfo(D,A)}

CART演算法

ID3和C4.5演算法中在使用一個屬性後,
這個屬性就不再被使用了,這種快速切割的方式會影響演算法的效果。CART是一顆二叉樹,對於每一個分支節點都會有兩個孩子。CART使用的表述純度的概念的是Gini值,同樣是資料越純,Gini值越小。

Gini(D)=1i(|Di||D|)2=1ip2i
Gini(D) = 1- \sum_{i} (\frac{|D_i|}{|D|})^2 = 1- \sum_{i} p_i^2

劃分後的基尼係數為

Gini(D,A)=j=1v|Dj||D|Gini(Dj)
\begin{aligned} Gini(D, A) = \sum_{j=1}^{v} \frac{|D_j|}{|D|} Gini(D_j)\end{aligned}

從而它的增益為

GainGini(D,A)=Gini(D)Gini(D,A)
Gain_{Gini}(D, A) = Gini(D) - Gini(D, A)

貪心選擇

針對上述的每一個演算法,樹在構造的時候,會遍歷候選屬性的每一個劃分,然後選擇能夠最大化增益的屬性以及劃分。
在實際演算法執行的時候,並不需要每次都計算增益,由於在進行劃分之前的純度值是固定的,採用不同的劃分後的純度值是不定的,我們最大化資訊增益相當於最小化劃分後的純度值。
對應於上述的三種演算法,相當於最小化Gain(D,A)

Gain(D,A)
,Gainratio(D,A)
Gain_{ratio}(D,A)
,
以及GainGini(D,A)
Gain_{Gini}(D,A)

決策樹演算法

我們引用一個書中的演算法來解釋一下決策樹的構造過程。

fig-c45.png,

Fig. 3: C4.5演算法,選自機器學習一書

步驟1

1
2
2
為停止條件: (a)
(a)

當前節點已經足夠的純,全部屬於一個類別,(b)
(b)
當前屬性已經全部用完,無法再進行下一步劃分

步驟3

3
為貪心選擇的過程,我們找到一個最優屬性的最優劃分。

步驟4

4
這個是額外的步驟,主要是為了給劃分進行一定的限制,要求達到一定的資訊增益。

步驟5

5
為按照屬性Ag
A_g
劃分的過程,裡面進行類別的話為廢話,這個明顯可以通過第6
6
步的下一輪遞迴搞定。

步驟6

6
才是遞迴的核心,它應該和第5
5
步合併。

額外注意事項

剪枝

剪枝有前剪枝和後剪枝,演算法C4.5中第4

4
步描述的是前剪枝演算法。後剪枝是當樹構建完畢後,遞迴的從樹的葉子節點向上回縮的過程,如果滿足一定條件,將葉子節點與它的父節點合併一個葉子節點(應該還有很多內容,後續待補充!!)。

缺失值

有些樣本有缺失值,一種方法是直接刪除樣本,但會損失樣本資訊,第二種方法是對缺失的樣本補充其均值等,第三種方法是概率化樣本,引用知乎的一段話:

其實缺失值問題可以從三個方面來考慮1.
在選擇分裂屬性的時候,訓練樣本存在缺失值,如何處理?假如你使用ID3演算法,那麼選擇分類屬性時,就要計算所有屬性的熵增(資訊增益,Gain)。假設10個樣本,屬性是a,b,c。在計算a屬性熵時發現,第10個樣本的a屬性缺失,那麼就把第10個樣本去掉,前9個樣本組成新的樣本集,在新樣本集上按正常方法計算a屬性的熵增。然後結果乘0.9(新樣本佔raw樣本的比例),就是a屬性最終的熵。2.
分類屬性選擇完成,對訓練樣本分類,發現屬性缺失怎麼辦?比如該節點是根據a屬性劃分,但是待分類樣本a屬性缺失,怎麼辦呢?假設a屬性離散,有1,2兩種取值,那麼就把該樣本分配到兩個子節點中去,但是權重由1變為相應離散值個數佔樣本的比例。然後計算錯誤率的時候,注意,不是每個樣本都是權重為1,存在分數。3.
訓練完成,給測試集樣本分類,有缺失值怎麼辦?這時候,就不能按比例分配了,因為你必須給該樣本一個確定的label,而不是薛定諤的label。這時候根據投票來確定,或者填充缺失值。

分類和迴歸

實際應用中,決策樹有分類樹和迴歸樹兩種,前者用於預測類別,例如是否健康,能否償還貸款,後者用於預測實數值,例如溫度,健康程度等。

分類樹:
樹在構建過程中或者按照閾值設定,或者按照類別將樣本劃分到多個子分支中,直到某一個分支中的所有樣本屬於同一個類別,即最純,或者屬性已經用完了,或者達到預先設定的條件,這個分支就停止劃分了,併成為葉子節點,它的類別採用的是多人投票法,即哪種類別最多,即為那個類別。

迴歸樹:
迴歸樹與分類樹類似,不過由於預測的值為連續值,沒有類別的概念,也就是說我們無法計算分支節點的純度,因此我們不再使用最大化資訊增益來作為劃分選擇,而是採用最小化均方誤差(回想前面所講的線性迴歸中的公式)

J=1mi=1m(yi¯¯¯y)2
J = \frac{1}{m}\sum_{i=1}^{m} (\overline{y_i} - y) ^2

其中yi¯¯¯
\overline{y_i}
為預測值,y
y
為實際值,m
m
為樣本數,J
J
為誤差。

我們對於每一個分支節點都計算了一個預測值,它為這個分支節點所有預測值的平均值。
分枝時窮舉每一個feature的每個閾值找最好的分割點,以最小化均方誤差。當進行預測的時候,以該節點所有人的平均年齡作為該節點的預測值。

參考資料

https://www.cnblogs.com/wxquare/p/5379970.html

https://www.cnblogs.com/bourneli/p/2961568.html

http://blog.csdn.net/dark_scope/article/details/13168827

https://www.cnblogs.com/leoo2sk/archive/2010/09/19/decision-tree.html

https://www.zhihu.com/question/34867991/answer/151775210

相關文章