決策樹

決策樹定義

  • 概念:決策樹可以近似于一個流程圖,長方形代表判斷模塊,橢圓形代表終止模塊,表示已經(jīng)得出結(jié)論,可以終止運行。從判斷模塊引出的左右箭頭稱作分支,它可以到達另一個判斷模塊或者終止模塊。


    決策樹
  • 優(yōu)點:計算復雜度不高,輸出結(jié)果易于理解,對中間值的缺失不敏感,可以處理不相關特征數(shù)據(jù)

  • 缺點:可能會產(chǎn)生過度匹配問題

  • 應用難點:很難確定特征

  • 適用數(shù)據(jù)類型:數(shù)值型和標稱型

  • 如何創(chuàng)建樹的分支?

Function createBranch():
檢測數(shù)據(jù)集中的每個子集是否屬于同一分類
    If so return 類標簽;
    Else
        尋找劃分數(shù)據(jù)集的最好特征
        劃分數(shù)據(jù)集
        創(chuàng)建分支節(jié)點
            for 每個劃分的子集
                調(diào)用函數(shù)createBranch()并增加返回結(jié)果到分支節(jié)點中
        return 分支節(jié)點
  • 信息增益:劃分數(shù)據(jù)之前之后的變化稱為信息增益,通過計算每個特征值劃分數(shù)據(jù)集獲得的信息增益,獲得信息增益最高的特征就是最好的選擇。香農(nóng)提出的了熵用于計算信息增益,信息增益=原來的熵-變化后的熵
  • 信息的定義:l(xi)=-log2p(xi),p(xi)表示選擇xi類別的概率
  • 熵:信息的期望值,計算一個樣本集合中的數(shù)據(jù)是純潔的還是不純潔的,公式(n是分類的數(shù)目):
H=-\sum_{i=1}^{n}p(x_i)log_2p(x_i)

決策樹的程序?qū)崿F(xiàn)

  • 計算給定數(shù)據(jù)集的香農(nóng)熵的實現(xiàn)代碼:
from math import log
def calcShannonEnt(dataset):
    numEntries = len(dataset)
    labelCounts ={}
    # 求出各個類別的樣本總數(shù),用來計算p(xi)
    for featVec in dataset:
        currentLabel = featVec[-1]
        if currentLabel not in labelCounts.keys():
            labelCounts[currentLabel] = 0
        labelCounts[currentLabel] += 1
    shannoEnt = 0.0
    #利用公式計算熵
    for key in labelCounts:
        prob = float(labelCounts[key])/numEntries
        shannoEnt -= prob*log(prob,2)
    return shannoEnt
#按照給定特征劃分數(shù)據(jù)集
#extend() 函數(shù)用于在列表末尾一次性追加另一個序列中的多個值
#輸入:待劃分的數(shù)據(jù)集,劃分數(shù)據(jù)集的特征,需要返回的特征的值
#a[i:j]:表示取從第i+1位到第j個元素
def splitDataSet(dataSet,axis,value):
    retDataSet =[]
    for featVec in dataSet:
        if featVec[axis] == value:
            # 從數(shù)據(jù)元組去掉該特征值
            reduceFeatVec =featVec[:axis]
            reduceFeatVec.extend(featVec[axis+1:])
            retDataSet.append(reduceFeatVec)
    return retDataSet
  • 選擇最好的數(shù)據(jù)集劃分方法
#選擇最好的數(shù)據(jù)集劃分方式
def chooseBestFeatureToSplit(dataSet):
    #計算列數(shù)得到特征數(shù)
    numFeatures = len(dataSet) - 1
    baseEntropy = calcShannonEnt(dataSet)
    bestInfoGain = 0.0
    bestFeatures = -1
    for i in range(numFeatures):
        #循環(huán)取出dataset的元組,然后取出元組中的第i列的所有取值
        featList = [example[i] for example in dataSet]
        uniqueVals = set(featList)
        #計算每個特征的所有特征值作為劃分子節(jié)點時的熵
        for values in uniqueVals:
            subDataSet =splitDataSet(dataSet, i ,value)
            prob = len(subDataSet)/float(len(dataSet))
            newEntropy += prob*calcShannonEnt(subDataSet)
        infoGain = baseEntropy - newEntropy
        #找到最好的特征值的,增益值越大分類效果越好
        if(infoGain>bestInfoGain):
            bestInfoGain = infoGain
            bestFeatures = i
    return bestFeatures
  • 數(shù)據(jù)具有多個標簽時如何處理?
    • 采用多數(shù)表決的方法決定該子節(jié)點的分類
#當出現(xiàn)多個類標簽結(jié)果時,采用投票表決的方法決定最終類標簽
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(i),reverse=True)
    return sortedClassCount[0][0]
  • 構(gòu)建決策樹
#創(chuàng)建樹的函數(shù)代碼
def createTree(dataSet, labels):
    classList=[example[-1]  for example in dataSet]
    #觀察當前分組的分類標簽是否一致
    if(classList.count(classList[0])==len(classList)):
        return classList[0]
    #特征已經(jīng)遍歷完
    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
  • 使用前面構(gòu)造好的算法得到?jīng)Q策樹,對測試數(shù)據(jù)執(zhí)行分類:
#使用決策樹執(zhí)行分類
#輸入:決策樹,特征表,測試數(shù)據(jù)
def classify(inputTree, feaLabels, testVec):
    #取出第一個鍵值,即根
    firstStr = inputTree.keys()[0]
    #獲得根對應的子節(jié)點
    secondDict = inputTree[firstStr]
    #找到第一個鍵值在實際數(shù)據(jù)存儲中的列位置
    featIndex = feaLabels.index(firstStr)
    for key in secondDict.keys():
        #找到下一步要到達的節(jié)點
        if testVec[featIndex]==key:
            if type(secondDict[key])._name_== 'dict':
                classLabel=classify(secondDict[key],feaLabels,testVec)
            else:
                classLabel=secondDict[key]
    return classLabel
  • 如何存儲決策樹?使用pickle包,pickle提供了一個簡單的持久化功能。可以將對象以文件的形式存放在磁盤上。
def storeTree(inputTree, filename):
    import pickle
    fw = open(filename, 'w')
    pickle.dump(inputTree, fw)
    fw.close()


def grabTree(filename):
    import pickle
    fr = open(filename)
    return pickle.load(fr)
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

  • 運行平臺:Windows Python版本:Python3.x IDE:pycharm 一、決策樹 決策樹是什么?...
    ghostdogss閱讀 2,282評論 0 1
  • 決策樹理論在決策樹理論中,有這樣一句話,“用較少的東西,照樣可以做很好的事情。越是小的決策樹,越優(yōu)于大的決策樹”。...
    制杖灶灶閱讀 6,067評論 0 25
  • ??決策樹(Decision Tree)是一種基本的分類與回歸方法,其模型呈樹狀結(jié)構(gòu),在分類問題中,表示基于特征對...
    殉道者之花火閱讀 4,938評論 2 2
  • 先來看個例子一個女孩的母親要給這個女孩介紹男朋友,于是有了下面的對話:女兒:多大年紀了?母親:26。女兒:長的帥不...
    ColleenKuang閱讀 827評論 0 0
  • 善人之道 “善”在這里是動詞,指不斷地完善自己,使自己成為“善人”??鬃诱f:“不踐跡,亦不入于室?!边@就是使自己完...
    夢之荒原閱讀 978評論 0 1

友情鏈接更多精彩內(nèi)容