決策樹ID3算法--python實現


參考:

統計學習方法》第五章決策樹】   http://pan.baidu.com/s/1hrTscza

決策樹的python實現     有完整程序    
 

  1 #coding:utf-8
  2 # ID3算法,建立決策樹
  3 import numpy as np
  4 import math
  5 import uniout
  6 '''
  7 #創建數據集
  8 def creatDataSet():
  9     dataSet = np.array([[1,1,'yes'],
 10                         [1,1,'yes'],
 11                         [1,0,'no'],
 12                         [0,1,'no'],
 13                         [0,1,'no']])
 14     features = ['no surfaceing', 'fippers']
 15     return dataSet, features
 16 '''
 17 
 18 #創建數據集
 19 def createDataSet():
 20     dataSet = np.array([['青年', '', '', ''],
 21                   ['青年', '', '', ''],
 22                   ['青年', '', '', ''],
 23                   ['青年', '', '', ''],
 24                   ['青年', '', '', ''],
 25                   ['中年', '', '', ''],
 26                   ['中年', '', '', ''],
 27                   ['中年', '', '', ''],
 28                   ['中年', '', '', ''],
 29                   ['中年', '', '', ''],
 30                   ['老年', '', '', ''],
 31                   ['老年', '', '', ''],
 32                   ['老年', '', '', ''],
 33                   ['老年', '', '', ''],
 34                   ['老年', '', '', '']])
 35     features = ['年齡', '有工作', '有自己房子']
 36     return dataSet, features
 37 
 38 #計算數據集的熵
 39 def calcEntropy(dataSet):
 40     #先算概率
 41     labels = list(dataSet[:,-1])
 42     prob = {}
 43     entropy = 0.0
 44     for label in labels:
 45         prob[label] = (labels.count(label) / float(len(labels)))
 46     for v in prob.values():
 47         entropy = entropy + (-v * math.log(v,2))
 48     return entropy
 49 
 50 #划分數據集
 51 def splitDataSet(dataSet, i, fc):
 52     subDataSet = []
 53     for j in range(len(dataSet)):
 54         if dataSet[j, i] == str(fc):
 55             sbs = []
 56             sbs.append(dataSet[j, :])
 57             subDataSet.extend(sbs)
 58     subDataSet = np.array(subDataSet)
 59     return np.delete(subDataSet,[i],1)
 60 
 61 #計算信息增益,選擇最好的特征划分數據集,即返回最佳特征下標
 62 def chooseBestFeatureToSplit(dataSet):
 63     labels = list(dataSet[:, -1])
 64     bestInfoGain = 0.0   #最大的信息增益值
 65     bestFeature = -1   #*******
 66     #摘出特征列和label列
 67     for i in range(dataSet.shape[1]-1):     #
 68         #計算列中,各個分類的概率
 69         prob = {}
 70         featureCoulmnL = list(dataSet[:,i])
 71         for fcl in featureCoulmnL:
 72             prob[fcl] = featureCoulmnL.count(fcl) / float(len(featureCoulmnL))
 73         #計算列中,各個分類的熵
 74         new_entrony = {}    #各個分類的熵
 75         condi_entropy = 0.0   #特征列的條件熵
 76         featureCoulmn = set(dataSet[:,i])   #特征列
 77         for fc in featureCoulmn:
 78             subDataSet = splitDataSet(dataSet, i, fc)
 79             prob_fc = len(subDataSet) / float(len(dataSet))
 80             new_entrony[fc] = calcEntropy(subDataSet)   #各個分類的熵
 81             condi_entropy = condi_entropy + prob[fc] * new_entrony[fc]    #特征列的條件熵
 82         infoGain = calcEntropy(dataSet) - condi_entropy     #計算信息增益
 83         if infoGain > bestInfoGain:
 84             bestInfoGain = infoGain
 85             bestFeature = i
 86     return bestFeature
 87 
 88 #若特征集features為空,則T為單節點,並將數據集D中實例樹最大的類label作為該節點的類標記,返回T
 89 def majorityLabelCount(labels):
 90     labelCount = {}
 91     for label in labels:
 92         if label not in labelCount.keys():
 93             labelCount[label] = 0
 94         labelCount[label] += 1
 95     return max(labelCount)
 96 
 97 #建立決策樹T
 98 def createDecisionTree(dataSet, features):
 99     labels = list(dataSet[:,-1])
100     #如果數據集中的所有實例都屬於同一類label,則T為單節點樹,並將類label作為該結點的類標記,返回T
101     if len(set(labels)) == 1:
102         return labels[0]
103     #若特征集features為空,則T為單節點,並將數據集D中實例樹最大的類label作為該節點的類標記,返回T
104     if len(dataSet[0]) == 1:
105         return majorityLabelCount(labels)
106     #否則,按ID3算法就計算特征集中各特征對數據集D的信息增益,選擇信息增益最大的特征beatFeature
107     bestFeatureI = chooseBestFeatureToSplit(dataSet)  #最佳特征的下標
108     bestFeature = features[bestFeatureI]    #最佳特征
109     decisionTree = {bestFeature:{}} #構建樹,以信息增益最大的特征beatFeature為子節點
110     del(features[bestFeatureI])    #該特征已最為子節點使用,則刪除,以便接下來繼續構建子樹
111     bestFeatureColumn = set(dataSet[:,bestFeatureI])
112     for bfc in bestFeatureColumn:
113         subFeatures = features[:]
114         decisionTree[bestFeature][bfc] = createDecisionTree(splitDataSet(dataSet, bestFeatureI, bfc), subFeatures)
115     return decisionTree
116 
117 #對測試數據進行分類
118 def classify(testData, features, decisionTree):
119     for key in decisionTree:
120         index = features.index(key)
121         testData_value = testData[index]
122         subTree = decisionTree[key][testData_value]
123         if type(subTree) == dict:
124             result = classify(testData,features,subTree)
125             return result
126         else:
127             return subTree
128 
129 
130 if __name__ == '__main__':
131     dataSet, features = createDataSet()     #創建數據集
132     decisionTree = createDecisionTree(dataSet, features)   #建立決策樹
133     print 'decisonTree:',decisionTree
134 
135     dataSet, features = createDataSet()
136     testData = ['老年', '', '']
137     result = classify(testData, features, decisionTree)  #對測試數據進行分類
138     print '是否給',testData,'貸款:',result

 

相關理論:

決策樹

概念原理

決策樹是一種非參數的監督學習方法,它主要用於分類和回歸。決策樹的目的是構造一種模型,使之能夠從樣本數據的特征屬性中,通過學習簡單的決策規則——IF THEN規則,從而預測目標變量的值。

決策樹學習步驟:1 特征選擇 2 決策樹的生成 3 決策樹的修剪

那么如何進行特征選擇

由於特征選擇的方法不同,衍生出了三種決策樹算法:ID3、C4.5、CART

ID3信息增益

熵越大,隨機變量的不確定性越大。

條件熵H(Y|X)表示在已知隨機變量X的條件下隨機變量Y的不確定性。

在信息增益中,衡量標准是看特征能夠為分類系統帶來多少信息,帶來的信息越多,該特征越重要。對一個特征而言,系統有它和沒它時信息量將發生變化,而前后信息量的差值就是這個特征給系統帶來的信息量。所謂信息量,就是熵。

C4.5信息增益比

CART 基尼指數

基尼指數越大,樣本的不確定性就越大

 

 

三個算法的優缺點

ID3算法

C4.5算法

CART算法(Classification and Regression Tree)

以信息增益為准則選擇信息增益最大的屬性。
缺點:1)信息增益對可取值數目較多的屬性有所偏好,比如通過ID號可將每個樣本分成一類,但是沒有意義。

2)ID3只能對離散屬性的數據集構造決策樹。
鑒於以上缺點,后來出現了C4.5算法。

以信息增益率為准則選擇屬性;在信息增益的基礎上對屬性有一個懲罰,抑制可取值較多的屬性,增強泛化性能。
其他優點

1)在樹的構造過程中可以進行剪枝,緩解過擬合;

2)能夠對連續屬性進行離散化處理(二分法);

3)能夠對缺失值進行處理;
缺點:構造樹的過程需要對數據集進行多次順序掃描和排序,導致算法低效;
剛才我們提到 信息增益對可取值數目較多的屬性有所偏好;而信息增益率對可取值數目較少的屬性有所偏好!OK,兩者結合一下就好了!
解決方法:先從候選屬性中找出信息增益高於平均水平的屬性,再從中選擇增益率最高的。而不是大家常說的 直接選擇信息增益率最高的屬性!

顧名思義,可以進行分類和回歸,可以處理離散屬性,也可以處理連續的。
分類樹使用GINI指數來選擇划分屬性:在所有候選屬性中,選擇划分后GINI指數最小的屬性作為優先划分屬性。回歸樹就用最小平方差。

 

ID3、C4.5、CART區別   參考:https://www.zhihu.com/question/27205203?sort=created

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM