第二十九章 Decision Tree算法(上)

這一篇文章中,討論一種被廣泛使用的分類算法——決策樹(decision tree)。決策樹的優(yōu)勢(shì)在于構(gòu)造過程不需要任何領(lǐng)域知識(shí)或參數(shù)設(shè)置,因此在實(shí)際應(yīng)用中,對(duì)于探測(cè)式的知識(shí)發(fā)現(xiàn),決策樹更加適用。

決策樹案例

通俗來說,決策樹分類的思想類似于找對(duì)象。現(xiàn)想象一個(gè)女孩的母親要給這個(gè)女孩介紹男朋友,于是有了下面的對(duì)話:

女兒:多大年紀(jì)了?

母親:26。

女兒:長(zhǎng)的帥不帥?

母親:挺帥的。

女兒:收入高不?

母親:不算很高,中等情況。

女兒:是公務(wù)員不?

母親:是,在稅務(wù)局上班呢。

女兒:那好,我去見見。

這個(gè)女孩的決策過程就是典型的分類樹決策。相當(dāng)于通過年齡、長(zhǎng)相、收入和是否公務(wù)員對(duì)將男人分為兩個(gè)類別:見和不見。假設(shè)這個(gè)女孩對(duì)男人的要求是:30歲以下、長(zhǎng)相中等以上并且是高收入者或中等以上收入的公務(wù)員,那么這個(gè)可以用下圖表示女孩的決策邏輯。

上圖完整表達(dá)了這個(gè)女孩決定是否見一個(gè)約會(huì)對(duì)象的策略,其中綠色節(jié)點(diǎn)表示判斷條件,橙色節(jié)點(diǎn)表示決策結(jié)果,箭頭表示在一個(gè)判斷條件在不同情況下的決策路徑,圖中紅色箭頭表示了上面例子中女孩的決策過程。

這幅圖基本可以算是一顆決策樹,說它“基本可以算”是因?yàn)閳D中的判定條件沒有量化,如收入高中低等等,還不能算是嚴(yán)格意義上的決策樹,如果將所有條件量化,則就變成真正的決策樹了。

有了上面直觀的認(rèn)識(shí),我們可以正式定義決策樹了:

決策樹(decision tree)是一個(gè)樹結(jié)構(gòu)(可以是二叉樹或非二叉樹)。其每個(gè)非葉節(jié)點(diǎn)表示一個(gè)特征屬性上的測(cè)試,每個(gè)分支代表這個(gè)特征屬性在某個(gè)值域上的輸出,而每個(gè)葉節(jié)點(diǎn)存放一個(gè)類別。使用決策樹進(jìn)行決策的過程就是從根節(jié)點(diǎn)開始,測(cè)試待分類項(xiàng)中相應(yīng)的特征屬性,并按照其值選擇輸出分支,直到到達(dá)葉子節(jié)點(diǎn),將葉子節(jié)點(diǎn)存放的類別作為決策結(jié)果。

可以看到,決策樹的決策過程非常直觀,容易被人理解。目前決策樹已經(jīng)成功運(yùn)用于醫(yī)學(xué)、制造產(chǎn)業(yè)、天文學(xué)、分支生物學(xué)以及商業(yè)等諸多領(lǐng)域。知道了決策樹的定義以及其應(yīng)用方法,下面介紹決策樹的構(gòu)造算法。

決策樹的構(gòu)造

不同于貝葉斯算法,決策樹的構(gòu)造過程不依賴領(lǐng)域知識(shí),它使用屬性選擇度量來選擇將元組最好地劃分成不同的類的屬性。所謂決策樹的構(gòu)造就是進(jìn)行屬性選擇度量確定各個(gè)特征屬性之間的拓?fù)浣Y(jié)構(gòu)。

構(gòu)造決策樹的關(guān)鍵步驟是分裂屬性。所謂分裂屬性就是在某個(gè)節(jié)點(diǎn)處按照某一特征屬性的不同劃分構(gòu)造不同的分支,其目標(biāo)是讓各個(gè)分裂子集盡可能地“純”。盡可能“純”就是盡量讓一個(gè)分裂子集中待分類項(xiàng)屬于同一類別。分裂屬性分為三種不同的情況:

1、屬性是離散值且不要求生成二叉決策樹。此時(shí)用屬性的每一個(gè)劃分作為一個(gè)分支。

2、屬性是離散值且要求生成二叉決策樹。此時(shí)使用屬性劃分的一個(gè)子集進(jìn)行測(cè)試,按照“屬于此子集”和“不屬于此子集”分成兩個(gè)分支。

3、屬性是連續(xù)值。此時(shí)確定一個(gè)值作為分裂點(diǎn)split_point,按照>split_point和<=split_point生成兩個(gè)分支。

構(gòu)造決策樹的關(guān)鍵性內(nèi)容是進(jìn)行屬性選擇度量,屬性選擇度量是一種選擇分裂準(zhǔn)則,是將給定的類標(biāo)記的訓(xùn)練集合的數(shù)據(jù)劃分D“最好”地分成個(gè)體類的啟發(fā)式方法,它決定了拓?fù)浣Y(jié)構(gòu)及分裂點(diǎn)split_point的選擇。

屬性選擇度量算法有很多,一般使用自頂向下遞歸分治法,并采用不回溯的貪心策略。這里介紹ID3和c4.5兩種常用算法。

ID3算法

從信息論知識(shí)中我們直到,期望信息越小,信息增益越大,從而純度越高。所以ID3算法的核心思想就是以信息增益度量屬性選擇,選擇分裂后信息增益最大的屬性進(jìn)行分裂。下面先定義幾個(gè)要用到的概念。

設(shè)D為用類別對(duì)訓(xùn)練元組進(jìn)行的劃分,則D的熵表示為:

其中pi表示第i個(gè)類別在整個(gè)訓(xùn)練元組中出現(xiàn)的概率,可以用屬于此類別元素的數(shù)量除以訓(xùn)練元組元素總數(shù)量作為估計(jì)。熵的實(shí)際意義表示是D中元組的類標(biāo)號(hào)所需要的平均信息量。

現(xiàn)在我們假設(shè)將訓(xùn)練元組D按屬性A進(jìn)行劃分,則A對(duì)D劃分的期望信息為:

而信息增益即為兩者的差值:

ID3算法就是在每次需要分裂時(shí),計(jì)算每個(gè)屬性的增益率,然后選擇增益率最大的屬性進(jìn)行分裂。下面我們繼續(xù)用SNS社區(qū)中不真實(shí)賬號(hào)檢測(cè)的例子說明如何使用ID3算法構(gòu)造決策樹。為了簡(jiǎn)單起見,我們假設(shè)訓(xùn)練集合包含10個(gè)元素:

其中s、m和l分別表示小、中和大。

設(shè)L、F、H和R表示日志密度、好友密度、是否使用真實(shí)頭像和賬號(hào)是否真實(shí),下面計(jì)算各屬性的信息增益。

因此日志密度的信息增益是0.276。

用同樣方法得到H和F的信息增益分別為0.033和0.553。

因?yàn)镕具有最大的信息增益,所以第一次分裂選擇F為分裂屬性,分裂后的結(jié)果如下圖表示:

在上圖的基礎(chǔ)上,再遞歸使用這個(gè)方法計(jì)算子節(jié)點(diǎn)的分裂屬性,最終就可以得到整個(gè)決策樹。

上面為了簡(jiǎn)便,將特征屬性離散化了,其實(shí)日志密度和好友密度都是連續(xù)的屬性。對(duì)于特征屬性為連續(xù)值,可以如此使用ID3算法:先將D中元素按照特征屬性排序,則每?jī)蓚€(gè)相鄰元素的中間點(diǎn)可以看做潛在分裂點(diǎn),從第一個(gè)潛在分裂點(diǎn)開始,分裂D并計(jì)算兩個(gè)集合的期望信息,具有最小期望信息的點(diǎn)稱為這個(gè)屬性的最佳分裂點(diǎn),其信息期望作為此屬性的信息期望。

C4.5算法

ID3算法存在一個(gè)問題,就是偏向于多值屬性,例如,如果存在唯一標(biāo)識(shí)屬性ID,則ID3會(huì)選擇它作為分裂屬性,這樣雖然使得劃分充分純凈,但這種劃分對(duì)分類幾乎毫無用處。ID3的后繼算法C4.5使用增益率的信息增益擴(kuò)充,試圖克服這個(gè)偏倚。

C4.5算法首先定義了“分裂信息”,其定義可以表示成:

其中各符號(hào)意義與ID3算法相同,然后,增益率被定義為:

C4.5選擇具有最大增益率的屬性作為分裂屬性,其具體應(yīng)用與ID3類似,不再贅述。

如果屬性用完了怎么辦

在決策樹構(gòu)造過程中可能會(huì)出現(xiàn)這種情況:所有屬性都作為分裂屬性用光了,但有的子集還不是純凈集,即集合內(nèi)的元素不屬于同一類別。在這種情況下,由于沒有更多信息可以使用了,一般對(duì)這些子集進(jìn)行“多數(shù)表決”,即使用此子集中出現(xiàn)次數(shù)最多的類別作為此節(jié)點(diǎn)類別,然后將此節(jié)點(diǎn)作為葉子節(jié)點(diǎn)。

關(guān)于剪枝

在實(shí)際構(gòu)造決策樹時(shí),通常要進(jìn)行剪枝,這時(shí)為了處理由于數(shù)據(jù)中的噪聲和離群點(diǎn)導(dǎo)致的過分?jǐn)M合問題。剪枝有兩種:

先剪枝——在構(gòu)造過程中,當(dāng)某個(gè)節(jié)點(diǎn)滿足剪枝條件,則直接停止此分支的構(gòu)造。

后剪枝——先構(gòu)造完成完整的決策樹,再通過某些條件遍歷樹進(jìn)行剪枝。

流程圖形式的決策樹

上圖流程圖就是一個(gè)假想的郵件分類系統(tǒng)決策樹,正方形代表判斷模塊,橢圓形代表終止模塊,表示已經(jīng)得出結(jié)論,可以終止運(yùn)行。判斷模塊引出的左右箭頭稱為分支,它可以到達(dá)另一個(gè)判斷模塊或者終止模塊。決策樹的主要優(yōu)勢(shì)在于數(shù)據(jù)形式非常容易理解。

優(yōu)點(diǎn)

計(jì)算復(fù)雜度不高,對(duì)中間值的缺失不敏感,可以處理不相干特征數(shù)據(jù),輸出結(jié)果易于理解。

缺點(diǎn)

可能會(huì)產(chǎn)生過度匹配問題。

適用數(shù)據(jù)類型

數(shù)值型跟標(biāo)稱型

ID3算法python2實(shí)現(xiàn)

from math import log

import operator

#def createDataSet():自己創(chuàng)建的數(shù)據(jù),可作實(shí)驗(yàn)用

#dataSet = [[1, 1, 'yes'],

# [1, 1, 'yes'],

# [1, 0, 'no'],

# [0, 1, 'no'],

# [0, 1, 'no']]

# labels = ['no surfacing','flippers']

#print dataSet

#change to discrete values

#return dataSet, labels

def loadDataSet(fileName): #general function to parse tab -delimited floats

dataMat = [] #assume last column is target value

fr = open(fileName)

for line in fr.readlines():

curLine = line.strip().split(',')

fltLine = list(curLine) #map all elements to float()

dataMat.append(fltLine)

return dataMat

#def createDataSet():

#dataSet = [[1, 1, 'yes'],

#[1, 1, 'yes'],

#[1, 0, 'no'],

#[0, 1, 'no'],

#[0, 1, 'no']]

#labels = ['no surfacing','flippers']

#print dataSet

#change to discrete values

#return dataSet, labels

def calcShannonEnt(dataSet):#計(jì)算給定數(shù)據(jù)集的香農(nóng)熵

numEntries = len(dataSet)#計(jì)算數(shù)據(jù)集中實(shí)例的總數(shù)

#print numEntries

labelCounts = {}#創(chuàng)建一個(gè)數(shù)據(jù)字典

for featVec in dataSet: #the the number of unique elements and their occurance

currentLabel = featVec[-1]#鍵值是最后一列數(shù)值

#print currentLabel

if currentLabel not in labelCounts.keys(): labelCounts[currentLabel] = 0#如果鍵值不存在,則擴(kuò)展字典并將當(dāng)前鍵值加入字典

labelCounts[currentLabel] += 1#當(dāng)前鍵值加入字典

#print labelCounts

shannonEnt = 0.0

for key in labelCounts:

prob = float(labelCounts[key])/numEntries# 使用所有類標(biāo)簽的發(fā)生概率計(jì)算類別出現(xiàn)的概率

#print prob

shannonEnt -= prob * log(prob,2) #log base 2 用這個(gè)概率計(jì)算香農(nóng)熵

#print shannonEnt

return shannonEnt

def splitDataSet(dataSet, axis, value):#劃分?jǐn)?shù)據(jù)集,dataSet為待劃分的數(shù)據(jù)集,axis為劃分?jǐn)?shù)據(jù)集的特征,value為特征的返回值

retDataSet = []#創(chuàng)建新的list對(duì)象

for featVec in dataSet:

#print featVec

if featVec[axis] == value:#將符合特征的數(shù)據(jù)抽取出來

reducedFeatVec = featVec[:axis] #chop out axis used for splitting

#print reducedFeatVec

reducedFeatVec.extend(featVec[axis+1:])#extend()函數(shù)只接受一個(gè)列表作為參數(shù),并將該參數(shù)的每個(gè)元素都添加到原有的列表中

#print reducedFeatVec

retDataSet.append(reducedFeatVec)#append()向列表的尾部添加一個(gè)元素,任意,可以是tuple

return retDataSet

def chooseBestFeatureToSplit(dataSet):#遍歷整個(gè)數(shù)據(jù)集,循環(huán)計(jì)算香農(nóng)熵和splitDataSet()函數(shù),找到最好的劃分方式

numFeatures = len(dataSet[0]) - 1 #the last column is used for the labels判斷當(dāng)前數(shù)據(jù)集包含多少特征屬性

baseEntropy = calcShannonEnt(dataSet)#計(jì)算整個(gè)數(shù)據(jù)集的原始香農(nóng)熵,保存最初的無序度量值,用于與劃分完之后的數(shù)據(jù)集計(jì)算的熵值進(jìn)行比較

bestInfoGain = 0.0; bestFeature = -1

for i in range(numFeatures): #iterate over all the features 遍歷數(shù)據(jù)集中的所有特征

featList = [example[i] for example in dataSet]#create a list of all the examples of this feature使用列表推導(dǎo)創(chuàng)建新的列表

uniqueVals = set(featList) #get a set of unique values將數(shù)據(jù)集中所有可能存在的值寫入featlist中,并從列表中創(chuàng)建集合

newEntropy = 0.0

for value in uniqueVals:#遍歷當(dāng)前特征值中的所有唯一屬性值,

subDataSet = splitDataSet(dataSet, i, value)#對(duì)每個(gè)特征劃分一次數(shù)據(jù)集

prob = len(subDataSet)/float(len(dataSet))

newEntropy += prob * calcShannonEnt(subDataSet) #計(jì)算數(shù)據(jù)集的新熵值,并對(duì)所有唯一特征值得到的熵求和

infoGain = baseEntropy - newEntropy #calculate the info gain; ie reduction in entropy#信息增益

if (infoGain > bestInfoGain): #compare this to the best gain so far#比較所有特征中的信息增益

bestInfoGain = infoGain #if better than current best, set to best

bestFeature = i#返回最好特征劃分的索引值

return bestFeature #returns an integer

def majorityCnt(classList):

classCount={}#創(chuàng)建鍵值為classList中唯一值的數(shù)據(jù)字典,字典對(duì)象存儲(chǔ)了classList中每個(gè)類標(biāo)簽現(xiàn)的頻率

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)#利用operator操作鍵值排序字典

return sortedClassCount[0][0]#返回出現(xiàn)次數(shù)最多的分類名稱

def createTree(dataSet,labels):#創(chuàng)建樹的函數(shù)代碼

classList = [example[-1] for example in dataSet]#創(chuàng)建了名為classList的列表變量,包含所有類標(biāo)簽

if classList.count(classList[0]) == len(classList): #

return classList[0]#stop splitting when all of the classes are equal

if len(dataSet[0]) == 1: #stop splitting when there are no more features in dataSet

return majorityCnt(classList)

bestFeat = chooseBestFeatureToSplit(dataSet)

bestFeatLabel = labels[bestFeat]

myTree = {bestFeatLabel:{}}#存儲(chǔ)了樹的所有信息

del(labels[bestFeat])#當(dāng)前數(shù)據(jù)集選取的最好特征存儲(chǔ)在變量bestFeat中,

featValues = [example[bestFeat] for example in dataSet]#得到列表包含的所有屬性值

uniqueVals = set(featValues)

for value in uniqueVals:#遍歷當(dāng)前選擇特征包含的所有屬性值

subLabels = labels[:] #copy all of labels, so trees don't mess up existing labels為了保證每次調(diào)用函數(shù)createtree()時(shí)不改變?cè)剂斜淼膬?nèi)容,使用新變量subLabels代替原始列表

myTree[bestFeatLabel][value] = createTree(splitDataSet(dataSet, bestFeat, value),subLabels)#遞歸調(diào)用函數(shù)cteatetree()得到的返回值插入到字典變量mytree中

return myTree

def classify(inputTree,featLabels,testVec):#遞歸函數(shù),

firstStr = inputTree.keys()[0]

secondDict = inputTree[firstStr]

featIndex = featLabels.index(firstStr)#使用index查找當(dāng)前列表中第一個(gè)匹配firstStr變量的元素

key = testVec[featIndex]

valueOfFeat = secondDict[key]

if isinstance(valueOfFeat, dict): #如果到達(dá)葉子節(jié)點(diǎn)

classLabel = classify(valueOfFeat, featLabels, testVec)#返回當(dāng)前節(jié)點(diǎn)的分類標(biāo)簽

else: classLabel = valueOfFeat

return classLabel

def storeTree(inputTree,filename):#決策樹分類器的存儲(chǔ)

import pickle#pickle序列化對(duì)象可以在磁盤上保存對(duì)象,并在需要時(shí)讀出來

fw = open(filename,'w')

pickle.dump(inputTree,fw)

fw.close()

def grabTree(filename):

import pickle

fr = open(filename)

return pickle.load(fr)

import matplotlib.pyplot as plt

decisionNode = dict(boxstyle="sawtooth", fc="0.8")

leafNode = dict(boxstyle="round4", fc="0.8")

arrow_args = dict(arrowstyle="<-")

def getNumLeafs(myTree):#遍歷整顆樹,累計(jì)葉子節(jié)點(diǎn)的個(gè)數(shù),并返回?cái)?shù)值

numLeafs = 0

firstStr = myTree.keys()[0]#第一個(gè)關(guān)鍵字是以第一次劃分?jǐn)?shù)據(jù)集的類別標(biāo)簽

secondDict = myTree[firstStr]#表示子節(jié)點(diǎn)的數(shù)值

for key in secondDict.keys():#遍歷整顆樹的所有子節(jié)點(diǎn)

if type(secondDict[key]).__name__=='dict':#test to see if the nodes are dictonaires, if not they are leaf nodes type()函數(shù)判斷子節(jié)點(diǎn)是否為字典類型,如果子節(jié)點(diǎn)是字典類型

numLeafs += getNumLeafs(secondDict[key])#則該節(jié)點(diǎn)是一個(gè)判斷節(jié)點(diǎn),遞歸調(diào)用getNumLeafs()函數(shù)

else: numLeafs +=1

return numLeafs

def getTreeDepth(myTree):#遍歷過程中遇到判斷節(jié)點(diǎn)的個(gè)數(shù)

maxDepth = 0

firstStr = myTree.keys()[0]

secondDict = myTree[firstStr]

for key in secondDict.keys():

if type(secondDict[key]).__name__=='dict':#test to see if the nodes are dictonaires, if not they are leaf nodes

thisDepth = 1 + getTreeDepth(secondDict[key])

else: thisDepth = 1

if thisDepth > maxDepth: maxDepth = thisDepth

return maxDepth

def plotNode(nodeTxt, centerPt, parentPt, nodeType):#執(zhí)行實(shí)際的繪圖功能

createPlot.ax1.annotate(nodeTxt, xy=parentPt, xycoords='axes fraction',

xytext=centerPt, textcoords='axes fraction',

va="center", ha="center", bbox=nodeType, arrowprops=arrow_args )#全局繪圖區(qū)

def plotMidText(cntrPt, parentPt, txtString):#計(jì)算子節(jié)點(diǎn)與父節(jié)點(diǎn)的中間位置,在父節(jié)點(diǎn)間填充文本信息

xMid = (parentPt[0]-cntrPt[0])/2.0 + cntrPt[0]

yMid = (parentPt[1]-cntrPt[1])/2.0 + cntrPt[1]

createPlot.ax1.text(xMid, yMid, txtString, va="center", ha="center", rotation=30)

def plotTree(myTree, parentPt, nodeTxt):#if the first key tells you what feat was split on計(jì)算寬與高

numLeafs = getNumLeafs(myTree) #this determines the x width of this tree計(jì)算樹的寬

depth = getTreeDepth(myTree)#計(jì)算樹的高

firstStr = myTree.keys()[0] #the text label for this node should be this

cntrPt = (plotTree.xOff + (1.0 + float(numLeafs))/2.0/plotTree.totalW, plotTree.yOff)

plotMidText(cntrPt, parentPt, nodeTxt)#標(biāo)記子節(jié)點(diǎn)屬性值

plotNode(firstStr, cntrPt, parentPt, decisionNode)

secondDict = myTree[firstStr]

plotTree.yOff = plotTree.yOff - 1.0/plotTree.totalD

for key in secondDict.keys():

if type(secondDict[key]).__name__=='dict':#test to see if the nodes are dictonaires, if not they are leaf nodes

plotTree(secondDict[key],cntrPt,str(key)) #recursion

else: #it's a leaf node print the leaf node

plotTree.xOff = plotTree.xOff + 1.0/plotTree.totalW

plotNode(secondDict[key], (plotTree.xOff, plotTree.yOff), cntrPt, leafNode)

plotMidText((plotTree.xOff, plotTree.yOff), cntrPt, str(key))

plotTree.yOff = plotTree.yOff + 1.0/plotTree.totalD

#if you do get a dictonary you know it's a tree, and the first element will be another dict

def createPlot(inTree):#第一個(gè)版本的函數(shù)

fig = plt.figure(1, facecolor='white')

fig.clf()

axprops = dict(xticks=[], yticks=[])

createPlot.ax1 = plt.subplot(111, frameon=False, **axprops) #no ticks

createPlot.ax1 = plt.subplot(111, frameon=False) #ticks for demo puropses

plotTree.totalW = float(getNumLeafs(inTree))#全局變量plotTree.totalW存儲(chǔ)樹的寬度

plotTree.totalD = float(getTreeDepth(inTree))#全局變量plotTree.totalD存儲(chǔ)樹的深度

plotTree.xOff = -0.5/plotTree.totalW; plotTree.yOff = 1.0;#使用plotTree.totalW,plotTree.totalD計(jì)算樹節(jié)點(diǎn)的擺放位置,這樣可以將樹繪制在水平方向和垂直方向的中心位置

plotTree(inTree, (0.5,1.0), '')

plt.show()

#def createPlot():

#fig = plt.figure(1, facecolor='white')

#fig.clf()

#createPlot.ax1 = plt.subplot(111, frameon=False) #ticks for demo puropses

#plotNode('a decision node', (0.5, 0.1), (0.1, 0.5), decisionNode)

#plotNode('a leaf node', (0.8, 0.1), (0.3, 0.8), leafNode)

#plt.show()

def retrieveTree(i):#輸出預(yù)先存儲(chǔ)的樹信息,避免每次測(cè)試都要從數(shù)據(jù)集中創(chuàng)建樹的麻煩,該函數(shù)主要用于測(cè)試,返回預(yù)定義的樹結(jié)構(gòu)

listOfTrees =[{'no surfacing': {0: 'no', 1: {'flippers': {0: 'no', 1: 'yes'}}}},

{'no surfacing': {0: 'no', 1: {'flippers': {0: {'head': {0: 'no', 1: 'yes'}}, 1: 'no'}}}}

]

return listOfTrees[i]

if __name__ == "__main__":

myMat=loadDataSet('C:\Users\HZF\Desktop\credit.txt')

labels=['A1','A2','A3','A4','A5','A6','A7','A8','A9','A10','A11','A12','A13','A14','A15']

myTree=createTree(myMat,labels)

print myTree

#numLeafs=getNumLeafs(myTree)

maxDepth=getTreeDepth(myTree)

print maxDepth

createPlot(myTree)

#classLabel=classify(myTree,labels,[1,1])

#labels=['age','prescript','astigmatic','tearRate']

#storeTree(myTree,'C:/Users/HZF/Desktop/machinelearninginaction/Ch03/classifierStorage.txt')

#pickle.load(fr)=grabTree('C:/Users/HZF/Desktop/machinelearninginaction/Ch03/classifierStorage.txt')

#print pickle.load(fr)

#print numLeafs

#print maxDepth

#print classLabel

#myMat,labels=createDataSet()

#myMat[0][-1]='maybe'

#print myMat

#shannonEnt=calcShannonEnt(myMat)

#print shannonEnt

#retDataSet=splitDataSet(myMat, 0, 0)

#print retDataSet

#bestFeature=chooseBestFeatureToSplit(myMat)

#print bestFeature

#myTree=createTree(myMat,labels)

#classify(inputTree,featLabels,testVec)

#print myTree

上篇就寫這么多了,中下篇會(huì)盡快更新哦!

參考文獻(xiàn)

1、《機(jī)器學(xué)習(xí)實(shí)戰(zhàn)》(書)

2、算法雜貨鋪——分類算法之決策樹(博客)

3、其他網(wǎng)站資料(略)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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