運行平臺:?Windows?
Python版本:?Python3.x?
IDE:?pycharm
一、決策樹
決策樹是什么?決策樹(decision tree)是一種基本的分類與回歸方法。舉個通俗易懂的例子,如下圖所示的流程圖就是一個決策樹,長方形代表判斷模塊(decision block),橢圓形成代表終止模塊(terminating block),表示已經得出結論,可以終止運行。從判斷模塊引出的左右箭頭稱作為分支(branch),它可以達到另一個判斷模塊或者終止模塊。我們還可以這樣理解,分類決策樹模型是一種描述對實例進行分類的樹形結構。決策樹由結點(node)和有向邊(directed edge)組成。結點有兩種類型:內部結點(internal node)和葉結點(leaf node)。內部結點表示一個特征或屬性,葉結點表示一個類。如下圖所示的決策樹,長方形和橢圓形都是結點。長方形的結點屬于內部結點,橢圓形的結點屬于葉結點,從結點引出的左右箭頭就是有向邊。而最上面的結點就是決策樹的根結點(root node)。這樣,結點說法就與模塊說法對應上了,理解就好。
我們可以把決策樹看成一個if-then規則的集合,將決策樹轉換成if-then規則的過程是這樣的:由決策樹的根結點(root node)到葉結點(leaf node)的每一條路徑構建一條規則;路徑上內部結點的特征對應著規則的條件,而葉結點的類對應著規則的結論。決策樹的路徑或其對應的if-then規則集合具有一個重要的性質:互斥并且完備。這就是說,每一個實例都被一條路徑或一條規則所覆蓋,而且只被一條路徑或一條規則所覆蓋。這里所覆蓋是指實例的特征與路徑上的特征一致或實例滿足規則的條件。
?使用決策樹做預測需要以下過程:
收集數據:可以使用任何方法。比如想構建一個相親系統,我們可以從媒婆那里,或者通過參訪相親對象獲取數據。根據他們考慮的因素和最終的選擇結果,就可以得到一些供我們利用的數據了。
準備數據:收集完的數據,我們要進行整理,將這些所有收集的信息按照一定規則整理出來,并排版,方便我們進行后續處理。
分析數據:可以使用任何方法,決策樹構造完成之后,我們可以檢查決策樹圖形是否符合預期。
訓練算法:這個過程也就是構造決策樹,同樣也可以說是決策樹學習,就是構造一個決策樹的數據結構。
測試算法:使用經驗樹計算錯誤率。當錯誤率達到了可接收范圍,這個決策樹就可以投放使用了。
使用算法:此步驟可以使用適用于任何監督學習算法,而使用決策樹可以更好地理解數據的內在含義
二、構建決策樹
? 使用決策樹做預測的每一步驟都很重要,數據收集不到位,將會導致沒有足夠的特征讓我們構建錯誤率低的決策樹。數據特征充足,但是不知道用哪些特征好,將會導致無法構建出分類效果好的決策樹模型。從算法方面看,決策樹的構建是我們的核心內容。
????決策樹要如何構建呢?通常,這一過程可以概括為3個步驟:特征選擇、決策樹的生成和決策樹的修剪
特征選擇
特征選擇在于選取對訓練數據具有分類能力的特征。這樣可以提高決策樹學習的效率,如果利用一個特征進行分類的結果與隨機分類的結果沒有很大差別,則稱這個特征是沒有分類能力的。經驗上扔掉這樣的特征對決策樹學習的精度影響不大。通常特征選擇的標準是信息增益(information gain)或信息增益比,為了簡單,本文章使用信息增益作為選擇特征的標準。那么,什么是信息增益?在講解信息增益之前,讓我們看一組實例,貸款申請樣本數據表。
希望通過所給的訓練數據學習一個貸款申請的決策樹,用以對未來的貸款申請進行分類,即當新的客戶提出貸款申請時,根據申請人的特征利用決策樹決定是否批準貸款申請。
特征選擇就是決定用哪個特征來劃分特征空間。比如,我們通過上述數據表得到兩個可能的決策樹,分別由兩個不同特征的根結點構成。
?圖(a)所示的根結點的特征是年齡,有3個取值,對應于不同的取值有不同的子結點。圖(b)所示的根節點的特征是工作,有2個取值,對應于不同的取值有不同的子結點。兩個決策樹都可以從此延續下去。問題是:究竟選擇哪個特征更好些?這就要求確定選擇特征的準則。直觀上,如果一個特征具有更好的分類能力,或者說,按照這一特征將訓練數據集分割成子集,使得各個子集在當前條件下有最好的分類,那么就更應該選擇這個特征。信息增益就能夠很好地表示這一直觀的準則。
什么是信息增益呢?在劃分數據集之前之后信息發生的變化成為信息增益,知道如何計算信息增益,我們就可以計算每個特征值劃分數據集獲得的信息增益,獲得信息增益最高的特征就是最好的選擇。
香農熵
在可以評測哪個數據劃分方式是最好的數據劃分之前,我們必須學習如何計算信息增益。集合信息的度量方式成為香農熵或者簡稱為熵(entropy),這個名字來源于信息論之父克勞德·香農。
如果看不明白什么是信息增益和熵,請不要著急,因為他們自誕生的那一天起,就注定會令世人十分費解??藙诘隆は戕r寫完信息論之后,約翰·馮·諾依曼建議使用”熵”這個術語,因為大家都不知道它是什么意思。
熵定義為信息的期望值。在信息論與概率統計中,熵是表示隨機變量不確定性的度量。如果待分類的事務可能劃分在多個分類之中,則符號xi的信息定義為
其中p(xi)是選擇該分類的概率。有人可能會問,信息為啥這樣定義?。看鹪唬呵拜叺贸龅慕Y論。這就跟1+1等于2一樣,記住并且會用即可。上述式中的對數以2為底,也可以e為底(自然對數)。
通過上式,我們可以得到所有類別的信息。為了計算熵,我們需要計算所有類別所有可能值包含的信息期望值(數學期望),通過下面的公式得到:
其中n是分類的數目。熵越大,隨機變量的不確定性就越大。
當熵中的概率由數據估計(特別是最大似然估計)得到時,所對應的熵稱為經驗熵(empirical entropy)。什么叫由數據估計?比如有10個數據,一共有兩個類別,A類和B類。其中有7個數據屬于A類,則該A類的概率即為十分之七。其中有3個數據屬于B類,則該B類的概率即為十分之三。淺顯的解釋就是,這概率是我們根據數據數出來的。我們定義貸款申請樣本數據表中的數據為訓練數據集D,則訓練數據集D的經驗熵為H(D),|D|表示其樣本容量,及樣本個數。設有K個類Ck,k = 1,2,3,···,K,|Ck|為屬于類Ck的樣本個數,這經驗熵公式可以寫為:
根據此公式計算經驗熵H(D),分析貸款申請樣本數據表中的數據。最終分類結果只有兩類,即放貸和不放貸。根據表中的數據統計可知,在15個數據中,9個數據的結果為放貸,6個數據的結果為不放貸。所以數據集D的經驗熵H(D)為:
編寫程序計算經驗熵
在編寫代碼之前,我們先對數據集進行屬性標注。
年齡:0代表青年,1代表中年,2代表老年;
有工作:0代表否,1代表是;
有自己的房子:0代表否,1代表是;
信貸情況:0代表一般,1代表好,2代表非常好;
類別(是否給貸款):no代表否,yes代表是。
確定這些之后,我們就可以創建數據集,并計算經驗熵了,代碼編寫如下:
link:https://github.com/songshijun007/Decision-Tree/blob/master/calcShannonEntcalcShannonEnt.py
信息增益
在上面,我們已經說過,如何選擇特征,需要看信息增益。也就是說,信息增益是相對于特征而言的,信息增益越大,特征對最終的分類結果影響也就越大,我們就應該選擇對最終分類結果影響最大的那個特征作為我們的分類特征。
在講解信息增益定義之前,我們還需要明確一個概念,條件熵。
熵我們知道是什么,條件熵又是個什么鬼?條件熵H(Y|X)表示在已知隨機變量X的條件下隨機變量Y的不確定性,隨機變量X給定的條件下隨機變量Y的條件熵(conditional entropy) H(Y|X),定義X給定條件下Y的條件概率分布的熵對X的數學期望:
其中,
同理,當條件熵中的概率由數據估計(特別是極大似然估計)得到時,所對應的條件熵成為條件經驗熵(empirical conditional entropy)。
明確了條件熵和經驗條件熵的概念。接下來,讓我們說說信息增益。前面也提到了,信息增益是相對于特征而言的。所以,特征A對訓練數據集D的信息增益g(D,A),定義為集合D的經驗熵H(D)與特征A給定條件下D的經驗條件熵H(D|A)之差,即
? 一般地,熵H(D)與條件熵H(D|A)之差成為互信息(mutual information)。決策樹學習中的信息增益等價于訓練數據集中類與特征的互信息。
設特征A有n個不同的取值{a1,a2,···,an},根據特征A的取值將D劃分為n個子集D1,D2,···,Dn,|Di|為Di的樣本個數。記子集Di中屬于Ck的樣本的集合為Dik,即Dik = Di ∩ Ck,|Dik|為Dik的樣本個數。于是經驗條件熵的公式可以些為:
以貸款申請樣本數據表為例進行說明。看下年齡這一列的數據,也就是特征A1,一共有三個類別,分別是:青年、中年和老年。我們只看年齡是青年的數據,年齡是青年的數據一共有5個,所以年齡是青年的數據在訓練數據集出現的概率是十五分之五,也就是三分之一。同理,年齡是中年和老年的數據在訓練數據集出現的概率也都是三分之一。現在我們只看年齡是青年的數據的最終得到貸款的概率為五分之二,因為在五個數據中,只有兩個數據顯示拿到了最終的貸款,同理,年齡是中年和老年的數據最終得到貸款的概率分別為五分之三、五分之四。所以計算年齡的信息增益,過程如下:
?最后,比較特征的信息增益,由于特征A3(有自己的房子)的信息增益值最大,所以選擇A3作為最優特征。
編寫程序計算信息增益
link:
決策樹生成和修剪
已經學習了從數據集構造決策樹算法所需要的子功能模塊,包括經驗熵的計算和最優特征的選擇,其工作原理如下:得到原始數據集,然后基于最好的屬性值劃分數據集,由于特征值可能多于兩個,因此可能存在大于兩個分支的數據集劃分。第一次劃分之后,數據集被向下傳遞到樹的分支的下一個結點。在這個結點上,我們可以再次劃分數據。因此我們可以采用遞歸的原則處理數據集。
構建決策樹的算法有很多,比如C4.5、ID3和CART,這些算法在運行時并不總是在每次劃分數據分組時都會消耗特征。由于特征數目并不是每次劃分數據分組時都減少,因此這些算法在實際使用時可能引起一定的問題。目前我們并不需要考慮這個問題,只需要在算法開始運行前計算列的數目,查看算法是否使用了所有屬性即可。
決策樹生成算法遞歸地產生決策樹,直到不能繼續下去未為止。這樣產生的樹往往對訓練數據的分類很準確,但對未知的測試數據的分類卻沒有那么準確,即出現過擬合現象。過擬合的原因在于學習時過多地考慮如何提高對訓練數據的正確分類,從而構建出過于復雜的決策樹。解決這個問題的辦法是考慮決策樹的復雜度,對已生成的決策樹進行簡化。
ID3算法構建決策樹
ID3算法的核心是在決策樹各個結點上對應信息增益準則選擇特征,遞歸地構建決策樹。具體方法是:從根結點(root node)開始,對結點計算所有可能的特征的信息增益,選擇信息增益最大的特征作為結點的特征,由該特征的不同取值建立子節點;再對子結點遞歸地調用以上方法,構建決策樹;直到所有特征的信息增益均很小或沒有特征可以選擇為止。最后得到一個決策樹。ID3相當于用極大似然法進行概率模型的選擇。
由于特征A3(有自己的房子)的信息增益值最大,所以選擇特征A3作為根結點的特征。它將訓練集D劃分為兩個子集D1(A3取值為"是")和D2(A3取值為"否")。由于D1只有同一類的樣本點,所以它成為一個葉結點,結點的類標記為“是”。
對D2則需要從特征A1(年齡),A2(有工作)和A4(信貸情況)中選擇新的特征,計算各個特征的信息增益:
g(D2,A1) = H(D2) - H(D2 | A1) = 0.251
g(D2,A2) = H(D2) - H(D2 | A2) = 0.918
g(D2,A3) = H(D2) - H(D2 | A3) = 0.474
????根據計算,選擇信息增益最大的特征A2(有工作)作為結點的特征。由于A2有兩個可能取值,從這一結點引出兩個子結點:一個對應”是”(有工作)的子結點,包含3個樣本,它們屬于同一類,所以這是一個葉結點,類標記為”是”;另一個是對應”否”(無工作)的子結點,包含6個樣本,它們也屬于同一類,所以這也是一個葉結點,類標記為”否”。
????這樣就生成了一個決策樹,該決策樹只用了兩個特征(有兩個內部結點),生成的決策樹如下圖所示。
這樣我們就使用ID3算法構建出來了決策樹,接下來,讓我們看看如何進行代實現。
編寫代碼構建決策樹
我們使用字典存儲決策樹的結構,比如上小節我們分析出來的決策樹,用字典可以表示為:
{'有自己的房子': {0: {'有工作': {0: 'no', 1: 'yes'}}, 1: 'yes'}}
創建函數majorityCnt統計classList中出現此處最多的元素(類標簽),創建函數createTree用來遞歸構建決策樹。編寫代碼如下: