Python機器學習之決策樹算法實例詳解
本文實例講述了Python機器學習之決策樹算法。分享給大家供大家參考,具體如下:
決策樹學習是應用最廣泛的歸納推理算法之一,是一種逼近離散值目標函數(shù)的方法,在這種方法中學習到的函數(shù)被表示為一棵決策樹。決策樹可以使用不熟悉的數(shù)據(jù)集合,并從中提取出一系列規(guī)則,機器學習算法最終將使用這些從數(shù)據(jù)集中創(chuàng)造的規(guī)則。決策樹的優(yōu)點為:計算復雜度不高,輸出結(jié)果易于理解,對中間值的缺失不敏感,可以處理不相關(guān)特征數(shù)據(jù)。缺點為:可能產(chǎn)生過度匹配的問題。決策樹適于處理離散型和連續(xù)型的數(shù)據(jù)。
在決策樹中最重要的就是如何選取用于劃分的特征
在算法中一般選用ID3,D3算法的核心問題是選取在樹的每個節(jié)點要測試的特征或者屬性,希望選擇的是最有助于分類實例的屬性。如何定量地衡量一個屬性的價值呢?這里需要引入熵和信息增益的概念。熵是信息論中廣泛使用的一個度量標準,刻畫了任意樣本集的純度。
假設(shè)有10個訓練樣本,其中6個的分類標簽為yes,4個的分類標簽為no,那熵是多少呢?在該例子中,分類的數(shù)目為2(yes,no),yes的概率為0.6,no的概率為0.4,則熵為 :
其中value(A)是屬性A所有可能值的集合,是S中屬性A的值為v的子集,即
。上述公式的第一項為原集合S的熵,第二項是用A分類S后熵的期望值,該項描述的期望熵就是每個子集的熵的加權(quán)和,權(quán)值為屬于的樣本占原始樣本S的比例
。所以Gain(S, A)是由于知道屬性A的值而導致的期望熵減少。
完整的代碼:
# -*- coding: cp936 -*- from numpy import * import operator from math import log import operator def createDataSet(): dataSet = [[1,1,'yes'], [1,1,'yes'], [1,0,'no'], [0,1,'no'], [0,1,'no']] labels = ['no surfacing','flippers'] return dataSet, labels def calcShannonEnt(dataSet): numEntries = len(dataSet) labelCounts = {} # a dictionary for feature for featVec in dataSet: currentLabel = featVec[-1] if currentLabel not in labelCounts.keys(): labelCounts[currentLabel] = 0 labelCounts[currentLabel] += 1 shannonEnt = 0.0 for key in labelCounts: #print(key) #print(labelCounts[key]) prob = float(labelCounts[key])/numEntries #print(prob) shannonEnt -= prob * log(prob,2) return shannonEnt #按照給定的特征劃分數(shù)據(jù)集 #根據(jù)axis等于value的特征將數(shù)據(jù)提出 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 #選取特征,劃分數(shù)據(jù)集,計算得出最好的劃分數(shù)據(jù)集的特征 def chooseBestFeatureToSplit(dataSet): numFeatures = len(dataSet[0]) - 1 #剩下的是特征的個數(shù) baseEntropy = calcShannonEnt(dataSet)#計算數(shù)據(jù)集的熵,放到baseEntropy中 bestInfoGain = 0.0;bestFeature = -1 #初始化熵增益 for i in range(numFeatures): featList = [example[i] for example in dataSet] #featList存儲對應特征所有可能得取值 uniqueVals = set(featList) newEntropy = 0.0 for value in uniqueVals:#下面是計算每種劃分方式的信息熵,特征i個,每個特征value個值 subDataSet = splitDataSet(dataSet, i ,value) prob = len(subDataSet)/float(len(dataSet)) #特征樣本在總樣本中的權(quán)重 newEntropy = prob * calcShannonEnt(subDataSet) infoGain = baseEntropy - newEntropy #計算i個特征的信息熵 #print(i) #print(infoGain) if(infoGain > bestInfoGain): bestInfoGain = infoGain bestFeature = i return bestFeature #如上面是決策樹所有的功能模塊 #得到原始數(shù)據(jù)集之后基于最好的屬性值進行劃分,每一次劃分之后傳遞到樹分支的下一個節(jié)點 #遞歸結(jié)束的條件是程序遍歷完成所有的數(shù)據(jù)集屬性,或者是每一個分支下的所有實例都具有相同的分類 #如果所有實例具有相同的分類,則得到一個葉子節(jié)點或者終止快 #如果所有屬性都已經(jīng)被處理,但是類標簽依然不是確定的,那么采用多數(shù)投票的方式 #返回出現(xiàn)次數(shù)最多的分類名稱 def majorityCnt(classList): classCount = {} for vote in classList: if vote not in classCount.keys():classCount[vote] = 0 classCount[vote] += 1 sortedClassCount = sorted(classCount.iteritems(),key=operator.itemgetter(1), reverse=True) return sortedClassCount[0][0] #創(chuàng)建決策樹 def createTree(dataSet,labels): classList = [example[-1] for example in dataSet]#將最后一行的數(shù)據(jù)放到classList中,所有的類別的值 if classList.count(classList[0]) == len(classList): #類別完全相同不需要再劃分 return classList[0] if len(dataSet[0]) == 1:#這里為什么是1呢?就是說特征數(shù)為1的時候 return majorityCnt(classList)#就返回這個特征就行了,因為就這一個特征 bestFeat = chooseBestFeatureToSplit(dataSet) print('the bestFeatue in creating is :') print(bestFeat) bestFeatLabel = labels[bestFeat]#運行結(jié)果'no surfacing' myTree = {bestFeatLabel:{}}#嵌套字典,目前value是一個空字典 del(labels[bestFeat]) featValues = [example[bestFeat] for example in dataSet]#第0個特征對應的取值 uniqueVals = set(featValues) for value in uniqueVals: #根據(jù)當前特征值的取值進行下一級的劃分 subLabels = labels[:] myTree[bestFeatLabel][value] = createTree(splitDataSet(dataSet,bestFeat,value),subLabels) return myTree #對上面簡單的數(shù)據(jù)進行小測試 def testTree1(): myDat,labels=createDataSet() val = calcShannonEnt(myDat) print 'The classify accuracy is: %.2f%%' % val retDataSet1 = splitDataSet(myDat,0,1) print (myDat) print(retDataSet1) retDataSet0 = splitDataSet(myDat,0,0) print (myDat) print(retDataSet0) bestfeature = chooseBestFeatureToSplit(myDat) print('the bestFeatue is :') print(bestfeature) tree = createTree(myDat,labels) print(tree)
對應的結(jié)果是:
>>> import TREE >>> TREE.testTree1() The classify accuracy is: 0.97% [[1, 1, 'yes'], [1, 1, 'yes'], [1, 0, 'no'], [0, 1, 'no'], [0, 1, 'no']] [[1, 'yes'], [1, 'yes'], [0, 'no']] [[1, 1, 'yes'], [1, 1, 'yes'], [1, 0, 'no'], [0, 1, 'no'], [0, 1, 'no']] [[1, 'no'], [1, 'no']] the bestFeatue is : 0 the bestFeatue in creating is : 0 the bestFeatue in creating is : 0 {'no surfacing': {0: 'no', 1: {'flippers': {0: 'no', 1: 'yes'}}}}
最好再增加使用決策樹的分類函數(shù)
同時因為構(gòu)建決策樹是非常耗時間的,因為最好是將構(gòu)建好的樹通過 python 的 pickle 序列化對象,將對象保存在磁盤上,等到需要用的時候再讀出
def classify(inputTree,featLabels,testVec): firstStr = inputTree.keys()[0] secondDict = inputTree[firstStr] featIndex = featLabels.index(firstStr) key = testVec[featIndex] valueOfFeat = secondDict[key] if isinstance(valueOfFeat, dict): classLabel = classify(valueOfFeat, featLabels, testVec) else: classLabel = valueOfFeat return classLabel 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)
更多關(guān)于Python相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《Python數(shù)據(jù)結(jié)構(gòu)與算法教程》、《Python加密解密算法與技巧總結(jié)》、《Python編碼操作技巧總結(jié)》、《Python函數(shù)使用技巧總結(jié)》、《Python字符串操作技巧匯總》及《Python入門與進階經(jīng)典教程》
希望本文所述對大家Python程序設(shè)計有所幫助。
相關(guān)文章
關(guān)于CUDA out of memory的解決方案
這篇文章主要介紹了關(guān)于CUDA out of memory的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-02-02對pandas中iloc,loc取數(shù)據(jù)差別及按條件取值的方法詳解
今天小編就為大家分享一篇對pandas中iloc,loc取數(shù)據(jù)差別及按條件取值的方法詳解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-11-11使用Python實現(xiàn)在Excel工作表中添加、修改及刪除超鏈接
在創(chuàng)建Excel工作簿時,內(nèi)部文檔的互鏈、報告自動化生成或是創(chuàng)建外部資源快速訪問路徑是比較常見的需求,本文將介紹如何使用Python實現(xiàn)在Excel工作表中對超鏈接進行添加、修改及刪除的操作,需要的朋友可以參考下2024-10-10Python+Kepler.gl實現(xiàn)時間輪播地圖過程解析
這篇文章主要介紹了Python+Kepler.gl實現(xiàn)時間輪播地圖過程解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2020-07-07