決策樹C4.5了解一下[微笑]


決策樹遵循“分而治之”策略,是一種樹形結構,其中每個內部結點表示在一個屬性上的測試,每個分支代表一個測試輸出,每個葉結點代表一種類別,目的是產生一顆泛化能力強,即處理未見示例能力強的決策樹。

優點:可以自學習

缺點:過擬合、泛化能力弱,生成的樹不一定全局最優

划分選擇:決策樹學習的關鍵是如何划分屬性,使得結點的“純度”越來越高,具體的可按照三種划分標准。

1.信息增益(ID3決策樹學習算法):表示得知特征A的信息而使得類X的信息的不確定性減少的程度。信息增益越大,意味着使用屬性來進行划分所獲得的純度提升越大。

信息熵 = 經驗熵H(D) – 經驗條件熵(H(D|A))

2.增益率(C4.5決策樹算法):信息增益可能對數目較多的屬性有偏好,為減少這種偏好使用增益率。C4.5算法是先從划分屬性中找出信息增益高於平均水平的屬性,然后在選擇增益率最高的。

3.基尼指數(CART決策樹算法):Gini(D)反映了從數據集中隨機抽取兩個樣本,其類別標記不一致的概率,Gini(D)越小,數據集D的純度越高。在選擇划分屬性時,我們選擇基尼指數最小的屬性作為最優划分屬性。

下面是未剪枝C4.5python實現的代碼:

  1 import math
  2 import operator
  3 import xlrd
  4 #功能:導入數據表
  5 #功能:計算熵
  6 def calcShannonEnt (dataSet):
  7     num = len(dataSet)#實例的個數
  8     labelCounts = {}#類標簽
  9     for featVec in dataSet:
 10         currentLabel = featVec[-1]#最后一列的數值
 11         if currentLabel not in labelCounts.keys():#如果在labelCounts中沒出現
 12             labelCounts[currentLabel] = 0#就把currentLabel鍵加入labelCounts中,值為0
 13         labelCounts[currentLabel] += 1#labelCounts對應的值就加一
 14     #計算香農熵H(D)
 15     ShannonEnt = 0.0
 16     for key in labelCounts:
 17         prob = float(labelCounts[key]) / num#計算p(Xi)概率
 18         ShannonEnt -= prob * math.log(prob, 2) 
 19     return ShannonEnt
 20 
 21 #功能:按照給定特征划分數據集
 22 #輸入:數據集、划分數據集的特征、需要返回的特征的值
 23 #返回:划分后的數據集
 24 def splitDataSet(dataSet, axis, value):
 25     newdataSet = []
 26     for featVec in dataSet:
 27         if featVec[axis] == value:
 28             reducedFeatVec = featVec[:axis]
 29             reducedFeatVec.extend(featVec[axis+1:])
 30             newdataSet.append(reducedFeatVec)
 31     return newdataSet
 32 
 33 #功能:選取最好的數據集划分方式
 34 #返回:最佳特征下標(增益率最大)
 35 def chooseBestFeatureTosplit(dataSet):
 36     numFeatures = len(dataSet[0]) - 1#特征個數
 37     baseEntropy = calcShannonEnt(dataSet)#原始香農熵H(D)
 38     bestInfoGainrate = 0.0; bestFeature = -1#信息增益和最好的特征
 39     #遍歷特征
 40     for i in range(numFeatures):
 41         featureSet = set([example[i] for example in dataSet])#第i個特征取值集合
 42         newEntropy = 0.0
 43         splitinfo = 0.0
 44         for value in featureSet:
 45             subDataSet = splitDataSet(dataSet, i, value)
 46             prob = len(subDataSet)/float(len(dataSet))
 47             newEntropy += prob * calcShannonEnt(subDataSet)#經驗條件熵H(D|A)
 48             splitinfo -= prob * math.log(prob,2)#經驗熵HA(D)
 49         #當概率為1或者0時(因為經驗熵要做被除數):
 50         if not splitinfo:
 51             splitinfo = -0.99 * math.log(0.99,2) - 0.01 * math.log(0.01,2)
 52         infoGain = baseEntropy - newEntropy#信息增益=H(D)-H(D|A)
 53         infoGainrate = float(infoGain) / float(splitinfo)#增益率=信息增益/經驗熵
 54         if infoGainrate > bestInfoGainrate:
 55             bestInfoGainrate = infoGainrate
 56             bestFeature = i
 57     return bestFeature
 58 
 59 #功能:多數表決決定葉子結點
 60 #使用分類名稱的列表,創建鍵值為classList中唯一值的數據字典,字典對象存儲了classList每個類標簽出現的頻率
 61 #返回:出現次數最多的分類名稱
 62 def majorityCnt(classList):
 63     classCount = {}
 64     for vote in classList:
 65         if vote not in classCount.keys(): 
 66             classCount[vote] = 0
 67         classCount[vote] += 1
 68     sortedClassCount = sorted(ClassCount.iteritems(),key = operator.itemgetter(1), reverse = True)
 69     return sortedClassCount[0][0]
 70 
 71 #功能:創建樹
 72 #輸入數據集和類標簽
 73 #返回字典樹
 74 def createTree(dataSet, labels):
 75     classList = [example[-1] for example in dataSet]#數據集的所有類標簽
 76     if classList.count(classList[0]) == len(classList):#停止條件是所有的類標簽完全相同
 77         return classList[0]
 78     if len(dataSet[0]) == 1:#當使用完了所有特征,還不能將數據集划分成僅包含唯一類別的分組
 79         return majorityCnt(classList)#挑選出出現次數最多的類別作為返回值
 80     #開始創建樹
 81     bestFeat = chooseBestFeatureTosplit(dataSet)#當前數據集選取的最好特征
 82     bestFeatLabel = labels[bestFeat]
 83     myTree = {bestFeatLabel:{}}
 84     #得到列表包含的所有屬性值
 85     #賦值當前特征標簽列表,防止改變原始列表的內容
 86     subLabels = labels[:]
 87     #刪除屬性列表中當前分類數據集特征
 88     del(subLabels[bestFeat])
 89     #獲取數據集中最優特征所在列
 90     featValues = [example[bestFeat] for example in dataSet]
 91     #采用set集合性質,獲取特征的所有的唯一取值
 92     uniqueVals = set(featValues)
 93     for value in uniqueVals:
 94         myTree[bestFeatLabel][value] = createTree(splitDataSet(dataSet, bestFeat, value),subLabels)
 95     return myTree
 96 
 97 '''    功能:決策樹分類函數
 98     思路:
 99     執行數據分類時,使用決策樹以及用於構造決策樹的標簽向量。
100     比較測試數據與決策樹上的數值
101     遞歸執行該過程直到進入葉子結點
102     將測試數據定義為葉子結點所屬的類型
103 '''
104 def classify(inputTree, featLabels, testVec):
105     #將標簽字符串轉換為索引
106     firstSides = list(inputTree.keys())
107     firstStr = firstSides[0]
108     secondDict = inputTree[firstStr]
109     featIndex = featLabels.index(firstStr)
110     #-----------------------------------
111     for key in secondDict.keys():
112         if testVec[featIndex] == key:
113             if type(secondDict[key]).__name__ =='dict':
114                 classLabel = classify(secondDict[key], featLabels, testVec)
115             else:    classLabel = secondDict[key]
116     return classLabel
117 
118 #功能:后剪枝
119 def 
120 
121 #功能:觀察決策樹的分類率
122 def getAccuracy(dataSet,testDatas,testLabels,myTree):
123     count = 0#分類正確的數量
124     print('數據量:',len(testDatas))
125     print('屬性數量:',len(testLabels))
126     num = 0#分類正確的數量
127     for testData in testDatas: 
128         i = 0
129         a = classify(myTree, testLabels,testData)
130         if a == dataSet[i][-1]:
131             count += 1
132         i += 1
133     print("分類正確的數量是: ",count)
134     accuracy = count / len(testDatas)
135     print("決策樹分類器的正確率為:",accuracy)

 


免責聲明!

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



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