1. 程式人生 > >機器學習實戰學習記錄--決策樹

機器學習實戰學習記錄--決策樹

決策樹中演算法採用的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'}}}}

結果為多層巢狀的葉節點