機器學習實戰學習記錄--決策樹
阿新 • • 發佈:2018-12-11
決策樹中演算法採用的ID3.劃分資料集基於 特徵。其中採用分類依據為資訊理論中的資訊增益和資訊熵(夏農熵)。
機器學習中夏農熵計算公式為:
其中xi表示分類,p(xi)表示xi分類的概率。
首先,建立資料集及計算夏農熵
from math import log
def calcShannonEnt(dataset): #夏農熵計算函式
numEnts=len(dataset)
labelCounts={} #記錄標籤及對應的個數
for featVec in dataset:
currentLabel=featVec[-1] #取出陣列中最後一項‘n’或者‘y’的作為標籤
if currentLabel not in labelCounts.keys(): #如果當前標籤在labelCounts中無記錄,則新增
labelCounts[currentLabel]=0
labelCounts[currentLabel]+=1 #標籤對應數量計數
shannonEnt=0.0
print(labelCounts)#輸出標籤及對應個數
for key in labelCounts:
prob=float(labelCounts[key])/numEnts #同標籤出現的概率,即p(xi)
shannonEnt-=prob*log(prob,2) #計算夏農熵 -p(xi)*log2(p(xi))的加和
return shannonEnt
def createDataset(): #資料集建立函式
dataset=[
[1,1,'y'],
[1,1,'y'],
[1,0,'n'],
[0,1,'n'],
[0,1,'n']
]
labels=["no serfacing","flippers"]
return dataset,labels
myData,labels=createDataset()
myData[0 ][-1]='maybe'#修改資料集中第一個的標籤為 maybe
print(myData)
print(calcShannonEnt(myData))
輸出結果為
[[1, 1, 'maybe'], [1, 1, 'y'], [1, 0, 'n'], [0, 1, 'n'], [0, 1, 'n']]
{'maybe': 1, 'y': 1, 'n': 3}
1.3709505944546687
得到熵,下一步按照最大資訊增益的方法劃分資料集。
原理是取各屬性進行熵的計算。取最高資訊增益的屬性為最佳屬性。
def chooseBestFeatureToSplit(dataset):
numFeatures=len(dataset[0])-1
baseEntropy =calcShannonEnt(dataset) #計算原始熵值
bestInfoGain=0.0
bestFeature=-1
for i in range(numFeatures):
featList=[example[i] for example in dataset] #遍歷獲取該列所有值
print("featList:",featList)
uniqueVals=set(featList) #從列表中建立集合,得到不重複的所有可能取值
print("uniquevals",uniqueVals)
newEntropy=0.0
for value in uniqueVals:
subDataset=splitDataSet(dataset,i,value)
print("subDataset:",subDataset)
prob=len(subDataset)/float(len(dataset))
newEntropy+=prob*calcShannonEnt(subDataset)
print("%d 列屬性的熵為:"%i,newEntropy)
infoGain=baseEntropy-newEntropy #計算每一個屬性值對應的熵值並求和。結果與原始熵值的差即為資訊增益。增益越大說明所佔決策權越大
print("inforgain:",infoGain)
if(infoGain>bestInfoGain):
bestInfoGain=infoGain
bestFeature=i
return bestFeature
print("bestFeature:",chooseBestFeatureToSplit(myData))
輸出結果為:
featList: [1, 1, 1, 0, 0]
uniquevals {0, 1}
subDataset: [[1, 'n'], [1, 'n']]
{'n': 2}
subDataset: [[1, 'y'], [1, 'y'], [0, 'n']]
{'y': 2, 'n': 1}
0 列屬性的熵為: 0.5509775004326937
inforgain: 0.4199730940219749
featList: [1, 1, 0, 1, 1]
uniquevals {0, 1}
subDataset: [[1, 'n']]
{'n': 1}
subDataset: [[1, 'y'], [1, 'y'], [0, 'n'], [0, 'n']]
{'y': 2, 'n': 2}
1 列屬性的熵為: 0.8
inforgain: 0.17095059445466854
bestFeature: 0
下面構建決策樹
程式碼如下:
def majorityCnt(classList): #返回出現次數最多的分類名稱
classCount={}
for vote in classList:
if vote not in classCount.keys():classCount[vote]=0 #建立分類(即字典)並計數
classCount[vote]+=1
sortedClassCount=sorted(classCount.items(),key=operator.itemgetter(1),reverse=True) #排序,True升序
return sortedClassCount[0][0]
def createTree(dataSet,labels):
classList=[example[-1] for example in dataSet]
if classList.count(classList[0])==len(classList): #所有的都是一個類,停止劃分
return classList[0]
if len(dataSet[0])==1: # #遍歷完所有特徵值時(僅剩一列)返回出現次數最多的
return majorityCnt(classList)
bestFeat=chooseBestFeatureToSplit(dataSet)
bestFeatLabel=labels[bestFeat]
myTree={bestFeatLabel:{}} #字典的建立
del(labels[bestFeat]) #刪除最佳屬性
featValues=[example[bestFeat] for example in dataSet] #得到所有屬性值
uniqueVals=set(featValues) #得到不重複的所有屬性值
for value in uniqueVals:
subLabels=labels[:]
myTree[bestFeatLabel][value]=createTree(splitDataSet(dataSet,bestFeat,value),subLabels) #遞迴
return myTree
print("createtree:",createTree(myData,labels))
最終輸出結果:
createtree: {'no serfacing': {0: 'n', 1: {'flippers': {0: 'n', 1: 'y'}}}}
結果為多層巢狀的葉節點