1. 程式人生 > >筆記:機器學習之決策樹

筆記:機器學習之決策樹

目錄

決策樹概述

特徵選擇

生成決策樹

剪枝

特徵選擇

生成決策樹

剪枝

決策樹概述

決策樹(decision tree)是功能強大的且非常好用的的分類和預測方法,它是一種有監督的學習演算法。以樹狀圖為基礎,故稱為決策樹。這裡以分類為主題。對於離散值,決策樹中的每一個非葉節點都是資料的一個特徵,葉節點是資料的分類,決策樹從根節點沿著不同的特徵分支最終到達葉節點。

無

決策樹的構建

決策樹的構建主要分為3大步驟

  • 特徵選擇

  • 生成決策樹

  • 剪枝

特徵選擇

特徵選擇就是選取有較強分類能力的特徵,其評判標準主要有資訊增益、資訊增益率和基尼係數來判定。

熵是度量資料純度最常用的一種指標。假設,樣本集合D中的第k類樣本的概率是{p_k{}^{}}(k=1,2,3...|y|),則D的資訊熵為

                                                                  E(D)=-\sum_{k=1}^{|y|}{p_klog_2}p_k

E(D)值越小則資料純度越高

條件熵

                                                                             E(D∣A)

表示在給定特徵A的條件下,D的條件熵

                                                       E(D|A)=\sum_{i=1}^{n}P_A(A=a_i)E(D|A=a_i)

                    

其中

                                                          P_A(A=a_i)=\sum_{D}^{ }P(A=a_i,D)

資訊增益

資訊增益表示:已知集合D的經驗熵E(D),給定特徵A下D的經驗條件熵為E(D∣A)的差

                                                             g(D,A)=E(D)-E(D|A)

例如,以西瓜資料為例

                                                                 西瓜資料表(表來自周志華老師的機器學習)

     

集合D中有兩類樣本,既好瓜和壞瓜。故|y|=2,。其中好瓜有8個樣本,壞瓜有9個樣本,因此,資訊熵為

E(D)=-\sum_{k=1}^{|y|}{p_klog_2}p_k=-(\frac{8}{17}log_2\frac{8}{17}+\frac{9}{17}log_2\frac{9}{17})=0.998

然後計算特徵集合{色澤,根蒂,敲聲,紋理....},以特徵“色澤”為例對集合D進行劃分,則有3個子集合分別是D^{1}“色澤=青綠”,D^{2}“色澤=烏黑”,D^{3}“色澤=淺白”,樣本數量分別為6、6、5,好瓜樣本為3、4、1.因此,以“色澤”劃分得到的3個節點的資訊熵分別為

因此,特徵“色澤”的資訊增益為

同理可計算出其他特徵的資訊增益

由此可知,特徵是紋理的資訊增益最大,故選紋理作為決策樹的根節點,再以同樣的方法選取其餘的特徵作為節點,最終得出完整的一課決策樹

               

增益率

值得注意的是,以資訊增益作為訓練集的特徵選取方案,存在偏向於選取值較多的特徵問題。極端情況下,特徵以特徵A劃分的節點,每一個節點有且僅有一個樣本時,其條件熵等於0(log1=0),此時資訊增益最大,但是A並不是最佳的選擇。例如,以西瓜資料表為例,“編號”將產生17個節點分支,並且每個分支只包括一個樣本,這時其資料純度最高等於1,資訊增益達到最大。但是顯然,以“編號”’劃分對決策樹的泛化能力無意義。為減少這種不利的影響。C4.5演算法採用增益率來選擇最優劃分特徵。增益率定義為

基尼係數

CART演算法使用基尼係數來選取特徵劃分,基尼係數與熵一樣,都是描述資料純度的指標,基尼係數越大,則不確定性越大,資料純度越低。

                                                               Gini(p)=\sum_{k=1}^{|y|}p_k(1-p_k)=1-\sum_{k=1}^{|y|}p_k^2

特徵a的基尼係數

                                                              Gini\_index(p)=\sum_{k=1}^{|y|}\tfrac{|D^v|}{|D|}Gini(D^v)

生成決策樹

輸入

      訓練資料集D

      特徵集A

      特徵資訊增益閾值\varepsilon >0

輸出:決策樹

演算法步驟

      若D中所有例項均屬於同一類,則T為單節點樹,並將該類作為該節點的類標誌,返回T。

      若特徵集A為空,則T為單節點樹,將D中例項數最大的類作為該節點的類標誌,返回T

      否則計算g(D,A_i),選擇信心增益最大的特徵A_g

      判斷A_g的信心增益

            若g(D,A_i) < \varepsilon​​​​,則置T為單節點樹,將D中例項數最大的類作為該節點的類標誌,返回T

            若g(D,A_i) >= \varepsilon,則對​​​​A_g特徵的每個可能取值a_j,根據A_g=a_j將D劃分為若干個非空子集D_i,將D_i中例項數最大                          的類作為標誌,構建子節點,由子節點及其子節點構成樹T,返回T

      對第i個子節點,以D_i為訓練集,以A-\{A_g\}為特徵集,遞迴地呼叫前面的步驟,得到子樹T_i,返回T_i

剪枝

剪枝是處理決策樹“過擬合”的有效手段。剪枝包括預剪枝和後剪枝。預剪枝是指在生成決策樹的過程中,對每個節點劃分之前預先做判斷,若當前節點劃分不能給提高決策樹的泛化效能,則當前節點不繼續劃分。後剪枝是指在訓練集中生成一棵完整的決策樹再對非葉子結點自下向上進行判斷,若將當前節點對應的子樹以當前節點作為葉子結點能提升決策樹的泛化效能,則以該節點變為葉子結點。對於決策樹的泛化效能的評估,一般來說,將資料分成訓練集和測試集,以測試集對決策樹泛化效能的評估。

            

預剪枝

根據資訊增益,對於表4.2,選擇“臍部”作為根節點,測試集中編號為{4,5,8}的是好瓜,其餘為壞瓜,則準確度為3/7*100%=42.9%.

特徵“臍部”劃分之後,分支分別為“凹陷”、“稍凹”、“平坦”分別包含編號為{1,2,3,14}、{6,7,15,17}、{10,16},而其對應的節點分別為“好瓜”、“好瓜”、“壞瓜”。這時,測試集中編號為{4,5,8,11,12}正確分類出來,此時的準確度為5/7*100%=71.4%>42.9%.因此,特徵“臍部”應該劃分。對剩下的特徵用同樣的方法進行處理,最終得到的結果是

                     

從中可以看出,預剪枝的樹少了很多分支,這可以減少決策樹的“過擬合”的風險,還可以減少訓練和測試的時間開銷。但是同時,預剪枝導致有很多資訊沒有用到,雖然在當前節點上劃分不會對決策樹的泛化效能有所提高,但是在其基礎上的後續劃分則有可能大幅度提高決策樹的泛化效能。

後剪枝

看節點6,若講其分支剪掉,即以其自身作為葉節點,則替換後的葉節點包括編號為{7,15}的訓練樣本,將其類別歸為“好瓜”,此時準確度為57.1%比未剪枝的準確度42.9%要高,因此,後剪枝策略決定剪掉該節點的分支。對於其他節點,以同樣的方法進行比較,最終得出

可知,後剪枝得到的決策樹要比預剪枝得到的樹的分支要多,其泛化效能一般會優於預剪枝,但是後剪枝是在生成一棵完整的決策樹之後再進行評估判斷的,因此,其時間花銷要比預剪枝要大。

用決策樹對鳶尾花的預測

from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import train_test_split
from sklearn import datasets
from sklearn.tree import export_graphviz
import pydot

def load_data():
    iris = datasets.load_iris()
    X_train = iris.data
    y_train = iris.target
    return train_test_split(X_train,y_train,test_size=0.25,random_state=0,stratify=y_train) #採用分成取樣

def test_DecisionTreeClassifier(*data):
    X_train, X_test, y_train, y_test=data
    clf = DecisionTreeClassifier()
    clf.fit(X_train,y_train)
    print('Training score:%f' %(clf.score(X_train,y_train)))
    print('Testing score:%f' %(clf.score(X_test,y_test)))
    export_graphviz(clf,out_file='tree.dot') #將圖轉換為點檔案
    (graph,) = pydot.graph_from_dot_file('tree.dot')#建立一個圖
    graph.write_png('tree.png')#將圖轉換為圖片

X_train, X_test, y_train, y_test=load_data()
test_DecisionTreeClassifier(X_train, X_test, y_train, y_test)

輸出

Training score:1.000000

Testing score:0.973684

注:圖片主要來源於周志華老師的機器學習

參考文獻:[1]周志華.機器學習[M].

                  [2]華校專,王正林.python大戰機器學習[M].電子工業出版社