Python實現——決策樹(部分函數/連續數據)


由於上一例的實現中只針對了離散數據,為了擴充處理范圍,我實現了一下對線性數據的簡單處理,在其中我選擇用中位數作為指標,平均數、眾數等等其他數據在我看來異曲同工,最終也都會有較相似的結構。

  • 求連續數據的香農熵
def calcLinerData(dataSet):
    num=len(dataSet)
    count={1:0,0:0}
    shannonEnt=0.0
    for i in range(num):
        feature = [ example[-1] for example in dataSet]
        feature2 = sorted( feature )
    flag = feature[int(num/2)]
    for i in range(num):
        if feature[i]>= flag:
            feature[i]=1
            count[1]+=1
        else:
            feature[i]=0
            count[0]+=1
    for i in [0,1]:
        prob = float(count[i])/num
        shannonEnt -= prob * log(prob,2)
    return shannonEnt

與離散數據的處理極其相似,不過在我看來使用上並不會太多,畢竟我們在分類的時候一般不會還是在用如此繁瑣連續的數據進行比對。
簡單來說,就是建立一個字典,把通過指標分類的數據分別計數(在這里是大於等於指標一類,剩余為另一類),最后再使用計算香農熵的方法正常計算,變化並不大,只是有了中間一步分類的過度。

  • 求連續數據指標:中位數
def getLinerFlag(dataSet,axis):
    num=len(dataSet)
    for i in range(num):
        feature = [ example[axis] for example in dataSet]
        feature2 = sorted( feature )
    flag = feature[int(num/2)]
    return flag

這個函數並不重要啟示,畢竟實際上有更多更好的衡量分類指標,這里只是一個簡單和偷懶的衡量方法。其他方法在我看來整體結構上應該類似,可能只是公式不同。

  • 線性划分
def splitDataSet(dataset, axis, value):
    retDataSet = []
    for featVec in dataset:
        if featVec[axis] == value:
            reducedFeatVec = featVec[:axis]
            reducedFeatVec.extend(featVec[axis+1:])
            retDataSet.append(reducedFeatVec)
    return retDataSet

依舊有着相似的性質,主要取決於采取的衡量方法,我覺得連續數據的划分方法比較不同的可能就是指標選取的數目,這里只有一個,所以較輕松。如果有多個,可以從低到高依次抽取,並刪除選取過的,當然或許有更多的,需要完全不同方式的衡量方式,我目前還沒有考慮到。

  • 加入判斷連續以及離散數據的最優划分求解
def chooseLinerSplit(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]
        uniqueVals=set(featList)
        newEntropy = 0.0
        if len(uniqueVals)>5:
            f=getLinerFlag(dataSet,i)
            datah,datal=LinerSplit(dataSet,i,f)
            newEntropy = len(datal)/float(len(dataSet))*calcShannonEnt(datah)+\
            len(datah)/float(len(dataSet))*calcShannonEnt(datal)
        else:
            for value 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
            bestFeature = i
    return bestFeature

畢竟離散數據連續數據混用應該是常態,這里我索性就綜合的進行了架構。其中我對於連續以及離散的判斷非常簡單,就是一個屬性的分類如果超過了5個,就判定為線性(或者說還得是數字?),可能不是那么的科學,不過...先這樣吧。

f=getLinerFlag(dataSet,i)
            datah,datal=LinerSplit(dataSet,i,f)
            newEntropy = len(datal)/float(len(dataSet))*calcShannonEnt(datah)+\
            len(datah)/float(len(dataSet))*calcShannonEnt(datal)

理解起來應該也非常通俗易懂,先求得大於等於以及小於划分指標的兩個集合,之后計算此划分的香農熵,就可以正常比對了。


免責聲明!

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



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