決策樹是一類常見的機器學習方法,利用決策樹來進行決策的過程很像人類在面臨決策問題時的一種思考模式。舉個生活中的例子,假如我們要判斷一個沒剖開的西瓜是不是好瓜,有經驗的瓜農可能會首先看看西瓜的顏色,再看看西瓜的根蒂形狀,如果還沒得出結論,可能還會敲打西瓜,聽聽是什麼聲音。上述過程用決策樹表示如下。
那麼我們的問題來了,給你一份帶分類標籤的數據,你怎麼訓練出一棵決策樹。再次回顧我們是怎樣利用決策樹進行判定的,在決策過程中每提出的一個問題其實都是對某個屬性的測試,然後沿着測試結果的分支繼續測試,直到走到最終的分類結果。在每一步的測試中,我們都想通過這個測試就能得到最終的分類結果,一個極端的例子,如果能通過判斷西瓜色澤是青綠色就得出是好瓜的結論最好。
所以我們的目標是儘可能進行少的屬性測試就能得到分類結果,換句話說就是每次測試都選擇最優的屬性測試,最優的含義就是通過這個測試能把數據集中的樣本結果盡多的確定。
這樣問題就清晰了,在構建決策樹的過程中就是每次都選擇一個最優的屬性。那麼我們通過什麼辦法來確定一個屬性是最優屬性呢,下面就引入信息增益的概念。
首先什麼是信息,信息能否度量?香農在他的著作《通信的數學原理》提出一個名詞“信息熵”。信息熵是用來消除事件不確定性所需的信息量的度量,我們可以這麼理解,一個事件越不確定,我們就需要越多的信息來確定它,它的信息熵就越大。比如我說明天會是世界末日,這個事件是真的還是假的,很難確定,所以它的信息熵很大。
回到我們的數據集上,如果我們的數據集的類別種類很多,我們要確定一個樣本到底屬於哪個類別,需要的信息量就越大,就表明這份數據集的信息熵就越大。數據集的信息熵計算公式如下:
其中D是數據集,|y|是類別個數,Pk是第k類樣本所佔的比率。
前面我們說了,我們每次都是選擇最優的屬性進行測試,也就是利用數據樣本在屬性上的取值不同將數據集分爲D1,D2,...,Dv,v爲屬性上不同值的個數,我們希望劃分後的數據集的信息熵是較小的,也就是希望原數據集和劃分後的數據集的信息熵的差值較大。這就是信息增益的含義,信息增益計算公式如下:
基於信息增益構建決策樹的算法被稱爲ID3算法。但我們仔細想想,會發現信息增益有一個偏好,就是每次都傾向於選擇可取值數目較多的屬性,因爲通常利用可取值數目較多的屬性劃分數據集後得到的信息增益較大。
但有時選擇這個屬性會帶來不好的影響。舉個簡單的例子,在一個數據集中,假設每個數據樣本都有唯一的ID,如果利用這個ID進行判斷,當然能一步得出結論,但這並不是我們想要的,因爲ID沒有任何的實際含義,它只是一個數據樣本的唯一標識。
爲了解決這個問題,C4.5算法就在ID3算法的基礎上進行了改進,C4.5算法對一個屬性的信息增益利用屬性的可取值數目進行了懲罰。C4.5算法利用增益率來選擇最優屬性,增益率的計算公式如下:
一般來說,屬性a的可取值數目越多,IV(a)的值就越大。增益率就可以理解爲在信息增益的基礎對屬性的可取值數目進行了懲罰。值得注意的一點是:C4.5算法並不是直接選擇增益率最大的那個屬性,而是先在候選屬性中找出那些信息增益大於平均值的屬性,再從這些屬性中選擇增益率最大的屬性。
最後還有一個指標可以用來選擇最優屬性,那就是基尼指數,CART(Classification And Regression Tree)決策樹就是使用基尼指數來選擇最優屬性的。
可以想象,當我們從數據集中隨機取兩個樣本,當這兩個樣本屬於同一分類的概率越大,這個數據集的純度越高,反之如果兩個樣本屬於不同分類的概率越大,則數據集的純度越低。基尼值就是表明隨機取兩個樣本屬於不同分類的概率,基尼值越大,數據集純度越低。這和信息熵的作用類似。基尼值的計算公式如下:
其中K爲數據集分類的個數,Pk爲第一個分類所佔的比率。
我們希望選擇一個屬性,經過這個屬性的劃分後,數據集的純度高,也就是數據集的基尼值小。用屬性a劃分數據集後的基尼值計算公式如下:
到此爲止我們知道了利用信息增益選擇屬性的ID3算法,利用增益率選擇屬性的C4.5算法,利用基尼指數選擇屬性的CART算法。下面我們來看下sklearn上的DecisionTreeClassifier是怎樣實現決策樹的。
一個簡單的例子如下:
from sklearn.datasets import load_iris
from sklearn import tree
iris = load_iris()
clf = tree.DecisionTreeClassifier()
clf = clf.fit(iris.data, iris.target)
DecisionTreeClassifier的相關參數說明:
Parameters:
criterion : string, optional (default=”gini”)
指定用哪種指標來選擇最優劃分屬性。”gini”:基尼指數,“entropy”:信息增益。
splitter : string, optional (default=”best”)
當一個屬性的值爲連續時,指定如何劃分數據集。"best"是求出最好的劃分點進行劃分,"random"是隨機選擇一個劃分點進行劃分。
選擇建議:當樣本很大時,選擇"random",因爲樣本很大時選擇一個最佳劃分點計算開銷較大。
max_depth : int or None, optional (default=None)
設置樹的最大深度。當爲None時,就是不限制樹的深度。在數據樣本大的情況下建議設置樹的深度爲10-100,因爲這可以有效的緩解過擬合問題。
min_samples_split : int, float, optional (default=2)
設置子樹可以繼續劃分所需的最小樣本數。當數據集較大時,可以適當加大這個值。
min_samples_leaf : int, float, optional (default=1)
設置葉子結點所需的最小樣本數。如果當前的葉子結點樣本數小於該值,則該葉子結點會和兄弟結點一起被剪枝。
max_features : int, float, string or None, optional (default=None)
設置選擇最優屬性時所參考的候選屬性個數。當爲None時,就是在所有屬性中選擇最優的,當爲"auto"或"sqrt"時,候選屬性個數爲。
max_leaf_nodes : int or None, optional (default=None)
設置決策樹葉子結點的最大個數。合適的值也可以緩解過擬合問題。
presort : bool, optional (default=False)
數據是否預排序。當數據集較少的時候,預排序可以使選擇最佳劃分點加快,但數據量大時反而不好。
Methods:
fit
(X, y[, sample_weight, check_input, …])
利用數據樣本X,訓練決策樹。
predict
(X[, check_input])
預測樣本X的分類。
predict_proba
(X[, check_input])
返回每個數據樣本屬於每個分類的概率。
score
(X, y[, sample_weight])
返回數據樣本X的預測正確率。
相關文章: