決策樹的python實現


決策樹和KNN是機器學習的入門級別的算法,所以面試的時候都時常會有面試官要求將決策樹寫出來以用來檢驗面試者的算法基本素養。

1.信息熵

信息熵是表示數據的混亂程度(物理學當中就有熱熵來表示分子混亂程度)。信息熵表現為-log(信息的概率)

那么整體的信息熵的數學期望:對概率*-log(概率)求和,以下用代碼語言表述上面所說:

from  math import log
def shannonent(dic):
    mm = {}
    dicLen= len(dic)
    shannonent = 0.0
    for elm in dic:
        mm[elm]=mm.get(elm,0)+1
    for key in mm:
        prob = float(mm[key])/dicLen
        shannonent -= prob*log(prob,2)
    return shannonent

舉個例子:

>>> reload(thetree)
<module 'thetree' from 'thetree.py'>
>>> dic=['a','b','c','c','d','c','w','d','kd','kd','s','a']
>>> cc= thetree.shannonent(dic)
>>> cc
2.688721875540867
>>> 

第一層的數據划分:

做決策樹都知道最后的結果是一個樹形結構,從一個總的數據分開由某個屬性分開由此將數據集分散開來,出現了第一層,第二層....

有了這個基本思路的情況下,就像做數學題從往外面一層一層的剝開,那么剝開的規則是是的信息熵最小

綜合上面所說的基本思想,我們可以選取一些簡單的例子,先實現第一層的數據划分:

def splitdataSet(udata,xais,value):
    reDataset=[]
    for line in udata:
        if line[xais]==value:
            newdata=line[:,xais]
            newdata.extend(line[xais+1,:])
            reDataset.append(newdata)
    return reDataSet

一般實現都是一點點實現,選擇xais---表示某一列,value---表示某行的某個值,這些步驟都是實現層的分的必要步驟,下面就是要選擇第一層從哪一列剝開最合適:

def choiceBestW(dataSet):
    labels = [ elm[-1] for elm in data]
    origshannon = shannonent(lables)
    kuan = shape(dataSet)[1]-1
    chang  = shape(dataSet)[0]
    bestInforGain = 0.0;bestFeature = -1
    for i in range(kuan):
        featList = [elm[i] for elm in dataSet]
        uniVals = set(featList)
        for word in uniVals:
            newer = splitdataSet(dataSet,i,word)
            prob = len(newer)/len(dataSet)
            newEntropy +=prob*shannonent(newer)
        infoGain = origshannon - newEntorpy
        if (infoGain > bestInfoGain):
            bestInfoGain = infoGain
            bestFeature = i
    return bestFeature

將第一層的最優剝開維度確定后,就可以開始2層的剝開了(數學的數列運算一樣,如果是等差數列要知道前2個值才可以退出之后的N維數列),那么這個時候就要考慮這種決策樹什么時候可以停止剝開。初步總結有兩種情況:1、數據集中數據的類都是屬於同一個類;2、數據集中的各個維度都被分完了--這個也是超級無奈了。當遍歷了各個維度的時候結果中還是有多個類別混合在一起,那么這個要給這個分類定義一個類可以認為“少數服從多數”;

def majorityCnt(classlist):
    classCount = {}
    for vote in classlist:
        classCount[vote]=classCount.get(vote,0)+1
    sortedClass = sorted(classCount.iteritems,\
                         key=operator.itemgetter(1),reverse=Ture)
    return sortedClass[0][0]

接下來就是構建決策樹的開始: 

def creatmytree(oridata,lables):
    diclist = [elm[-1] for elm in oridata]
    if diclist.count(diclist[0])==len(diclist):
        return diclist[0]
    if len(oridata[0])==1:
        return majorityCnt(diclist)
    bestFeat = choiceBestW(oridata)
    bestFeatLabel = lables[bestFeat]
    mytree ={bestFeatLabel:{}}
    del(lables[bestFeat])
    bestline = [elm[bestFeat] for elm in oridata]
    uniqvals = set(bestline)
    for val in uniqvals:
        nlabels = lables[:]
        mytree[bestFeatLabel][val] = creatmytree(splitdataSet(oridata,bestFeat,val),nlabels)
    return mytree

一般到這對原有數據的分類模型已經出來了,但是其作為有預測功能的分類還是沒有出來,那么這個時候我們要將這個模型和一些未知分類的數據結合起來運用:

 

def classficate(testdata,trees,labels):
    firstStr = trees.keys()[0]
    secondDict = trees[firstStr]
    featIndex = featLabels.index(firstStr)
    for val in secondDict.keys():
        if testdata[featIndex] == val:
            if type(sencondDict[val])__name__ =='dict':
                classLabel = classficate(testdata,secondDict[keys],labels)
            else:
                classLabel = secondDict[key]
    return classLabel
#trees 是指上面得到的決策樹模型
#testdata 是測試數據向量(一條數據)
#labels 是指測量數據的指標

現在將上面的代碼合在一起就可以做出一些預測了,在機器學習實戰這本書里面是對配眼鏡流程的一個模仿,我們接下來會對數據進行一個實戰:

突然想到一個決策樹的一個應用場景:問卷設計方式(從科學的角度來說這是最快的方式)--通常在調查的過程中大家會有定性和定量結合起來,那么定性很多時候都是拍腦袋哪個先哪個后,個人感覺如果用樹結構去做份問卷調查顯然會高效很多。----我這個星期嘗試下:

考慮心理層面的因素,如果是問卷的話可以在前面加一些放松受訪者的受訪心理,然后通過趣味答題,測出想要的東西。


免責聲明!

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



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