機器學習 | 算法筆記- 決策樹(Decision Tree)

前言

本系列爲機器學習算法的總結和概括,目的爲了清晰闡述算法原理,同時附帶上手代碼實例,便於理解。

目錄

   決策樹
   線性迴歸
  組合算法(Ensemble Method)
   K-Means
  機器學習算法總結
 
本章爲決策樹算法,內容包括基本模型介紹,以及包括ID三、C4.5和CART樹不一樣樹模型的介紹。同時包括python3下的代碼實戰,代碼實現包括自我實現和基於sklearn的算法,實戰案例有...(參考《機器學習實戰》)。

1、算法簡介

1.1 基本模型介紹

決策樹是一類常見的機器學習方法,能夠幫助咱們解決分類與迴歸兩類問題。模型可解釋性強,模型符合人類思惟方式,是經典的樹形結構。分類決策數模型是一種描述對實例進行分類的樹形結構。決策樹由結點 (node) 和有向邊 (directed edge) 組成。結點包含了一個根結點 (root node)、若干個內部結點 (internal node) 和若干個葉結點 (leaf node)。內部結點表示一個特徵或屬性,葉結點表示一個類別。
簡單而言,決策樹是一個多層if-else函數,對對象屬性進行多層if-else判斷,獲取目標屬性的類別。因爲只使用if-else對特徵屬性進行判斷,因此通常特徵屬性爲離散值,即便爲連續值也會先進行區間離散化,如能夠採用二分法(bi-partition)。
思考:選哪些特徵屬性參與決策樹建模、哪些屬性排在決策樹的頂部,哪些排在底部,對屬性的值該進行什麼樣的判斷、樣本屬性的值缺失怎麼辦、若是輸出不是分類而是數值能用麼、對決策沒有用或沒有多大幫助的屬性怎麼辦、何時使用決策樹?

1.2 決策樹特色

· 決策樹優勢
  1)決策樹易於理解和實現,人們在在學習過程當中不須要使用者瞭解不少的背景知識,這同時是它的可以直接體現數據的特色,只要經過解釋後都有能力去理解決策樹所表達的意義。
  2)對於決策樹,數據的準備每每是簡單或者是沒必要要的,並且可以同時處理數據型和常規型屬性,在相對短的時間內可以對大型數據源作出可行且效果良好的結果。
  3)易於經過靜態測試來對模型進行評測,能夠測定模型可信度;若是給定一個觀察的模型,那麼根據所產生的決策樹很容易推出相應的邏輯表達式。
· 決策樹缺點
  1)對連續性的字段比較難預測。
  2)對有時間順序的數據,須要不少預處理的工做。
  3)當類別太多時,錯誤可能就會增長的比較快。
  4)通常的算法分類的時候,只是根據一個字段來分類。

2、算法分類和流程

2.1 算法分類

現有的關於決策樹學習的主要思想主要包含如下 3 個研究成果:
  由 Quinlan 在 1986 年提出的 ID3 算法
  由 Quinlan 在 1993 年提出的 C4.5 算法
  由 Breiman 等人在 1984 年提出的 CART 算法
算法比較

2.2 算法流程- 劃分選擇

決策樹學習一般包括 3 個步驟:特徵選擇、決策樹的生成、決策樹的修剪。最爲關鍵的就是如何選擇最優劃分屬性。通常而言,隨着劃分過程不斷進行,咱們但願決策樹的分支結點所包含的樣本儘量屬於同一類別,即結點的 「純度」 (purity) 愈來愈高。

2.2.1 信息增益(information gain)php

信息增益表示得知特徵Xj的信息而使所屬分類的不肯定性減小的程度。
特徵A對訓練數據集D的信息增益g(D,A),定義爲集合D的經驗熵H(D)與特徵A給定的狀況下D的經驗條件熵H(D|A)之差。
假設數據集D有K種分類,特徵A有n種取值可能。其中數據集D的經驗熵H(D)爲
其中P k爲集合D中的任同樣本數據分類k的機率,或者說屬於分類k的樣本所佔的比例。
經驗條件熵H(D|A)爲 
也可記做
其中P i爲特徵取值爲第i個可取值的機率。D i爲特徵A爲第i個可取值的樣本集合。
通常而言,信息增益越大,則意味着使用屬性A來進行劃分所得到的 "純度提高" 越大。所以,咱們能夠用信息增益來進行決策樹的劃分屬性選擇。著名的 ID3 決策樹學習算法就是以信息增益爲準則來選擇劃分屬性。

2.2.2 信息增益比(information gain ratio)html

特徵A對訓練數據集D的信息增益gR(D,A),定義爲其信息增益g(D,A)與訓練集D的經驗熵H(D)之比。
是爲了矯正在訓練數據集的經驗熵大時,信息增益值會偏大,反之,信息增益值會偏小的問題。即特徵選擇使用了一個啓發式策略:先從候選劃分屬性中找出信息增益高於平均水平的屬性,再從中選擇增益率最高的。 C4.5算法是使用該方式來劃分屬性。

2.2.3 基尼指數(Gini index)node

ID3仍是C4.5都是基於信息論的熵模型的,這裏面會涉及大量的對數運算,爲了簡化模型同時也徹底丟失熵模型的優勢,在CART算法中使用基尼係數來代替信息增益比,基尼係數表明了模型的不純度,基尼係數越小,則不純度越低,特徵越好。這和信息增益(比)是相反的。經過子集計算基尼不純度,即隨機放置的數據項出現於錯誤分類中的機率。以此來評判屬性對分類的重要程度。
其中p k爲任同樣本點屬於第k類的機率,也能夠說成樣本數據集中屬於k類的樣本的比例。
集合D的基尼指數爲Gini(D),在特徵A條件下的集合D的基尼指數爲
其中 |D i|爲特徵A取第i個值時對應的樣本個數。|D|爲總樣本個數
CART算法中對於分類樹採用的是上述的基尼指數最小化準則。對於迴歸樹,CART採用的是平方偏差最小化準則。

2.3 剪枝

剪枝 (pruning) 是決策樹學習算法對付 「過擬合」 的主要手段。在決策樹學習中,爲了儘量正確分類訓練樣本,結點劃分過程將不斷重複,有時會形成決策樹分支過多,這時就可能因針對訓練樣本學得 「太好」 了,以致於把訓練集自身的一些特色看成全部數據都具備的通常性質而致使過擬合。所以,可經過主動去掉一些分支來下降過擬合的風險。
 
決策樹剪枝的基本策略有 「預剪枝」 (prepruning) 和 「後剪枝」 (postpruning)。
  · 預剪枝 是指在決策樹生成過程當中,對每一個結點在劃分前先進行估計,若當前節點的劃分不能帶來決策樹泛化性能的提高,則中止劃分並將當前結點標記爲葉結點;
  · 後剪枝 則是先從訓練集生成一顆完整的決策樹,而後自底向上地對非葉結點進行考察,若將該結點的子樹替換爲葉結點能帶來決策樹泛化性能的提高,則將該子樹替換爲葉結點。

4、案例

本篇文章將在基本概念基礎上,以實際案例熟悉決策樹構建、可視化和分類預測等。
決策樹算法訓練流程主要包括:收集數據- 準備數據- 分析數據- 訓練算法- 測試算法

4.1 基於python3的代碼實現

基於ID3算法,實現預測貸款用戶是否具備償還貸款的能力
1)建立數據集
"""
函數說明:建立測試數據集

Parameters:
    無
Returns:
    dataSet - 數據集
    labels - 特徵標籤

"""
def createDataSet():
    dataSet = [[0, 0, 0, 0, 'no'],                        #數據集
            [0, 0, 0, 1, 'no'],
            [0, 1, 0, 1, 'yes'],
            [0, 1, 1, 0, 'yes'],
            [0, 0, 0, 0, 'no'],
            [1, 0, 0, 0, 'no'],
            [1, 0, 0, 1, 'no'],
            [1, 1, 1, 1, 'yes'],
            [1, 0, 1, 2, 'yes'],
            [1, 0, 1, 2, 'yes'],
            [2, 0, 1, 2, 'yes'],
            [2, 0, 1, 1, 'yes'],
            [2, 1, 0, 1, 'yes'],
            [2, 1, 0, 2, 'yes'],
            [2, 0, 0, 0, 'no']]
    labels = ['年齡', '有工做', '有本身的房子', '信貸狀況']        #特徵標籤
    return dataSet, labels                             #返回數據集和分類屬性
View Code
2)劃分數據集
"""
函數說明:按照給定特徵劃分數據集

Parameters:
    dataSet - 待劃分的數據集
    axis - 劃分數據集的特徵
    value - 須要返回的特徵的值
Returns:
    無

"""
def splitDataSet(dataSet, axis, value):        
    retDataSet = []                                        #建立返回的數據集列表
    for featVec in dataSet:                             #遍歷數據集
        if featVec[axis] == value:
            reducedFeatVec = featVec[:axis]                #去掉axis特徵
            reducedFeatVec.extend(featVec[axis+1:])     #將符合條件的添加到返回的數據集
            retDataSet.append(reducedFeatVec)
    return retDataSet                                      #返回劃分後的數據集
View Code

3)計算香儂熵python

"""
函數說明:計算給定數據集的經驗熵(香農熵)

Parameters:
    dataSet - 數據集
Returns:
    shannonEnt - 經驗熵(香農熵)

"""
def calcShannonEnt(dataSet):
    numEntires = len(dataSet)                        #返回數據集的行數
    labelCounts = {}                                #保存每一個標籤(Label)出現次數的字典
    for featVec in dataSet:                            #對每組特徵向量進行統計
        currentLabel = featVec[-1]                    #提取標籤(Label)信息
        if currentLabel not in labelCounts.keys():    #若是標籤(Label)沒有放入統計次數的字典,添加進去
            labelCounts[currentLabel] = 0
        labelCounts[currentLabel] += 1                #Label計數
    shannonEnt = 0.0                                #經驗熵(香農熵)
    for key in labelCounts:                            #計算香農熵
        prob = float(labelCounts[key]) / numEntires    #選擇該標籤(Label)的機率
        shannonEnt -= prob * log(prob, 2)            #利用公式計算
    return shannonEnt                                #返回經驗熵(香農熵)
View Code

4)選擇最優特徵git

"""
函數說明:選擇最優特徵

Parameters:
    dataSet - 數據集
Returns:
    bestFeature - 信息增益最大的(最優)特徵的索引值

"""
def chooseBestFeatureToSplit(dataSet):
    numFeatures = len(dataSet[0]) - 1                    #特徵數量
    baseEntropy = calcShannonEnt(dataSet)                 #計算數據集的香農熵
    bestInfoGain = 0.0                                  #信息增益
    bestFeature = -1                                    #最優特徵的索引值
    for i in range(numFeatures):                         #遍歷全部特徵
        #獲取dataSet的第i個全部特徵
        featList = [example[i] for example in dataSet]
        uniqueVals = set(featList)                         #建立set集合{},元素不可重複
        newEntropy = 0.0                                  #經驗條件熵
        for value in uniqueVals:                         #計算信息增益
            subDataSet = splitDataSet(dataSet, i, value)         #subDataSet劃分後的子集
            prob = len(subDataSet) / float(len(dataSet))           #計算子集的機率
            newEntropy += prob * calcShannonEnt(subDataSet)     #根據公式計算經驗條件熵
        infoGain = baseEntropy - newEntropy                     #信息增益
        # print("第%d個特徵的增益爲%.3f" % (i, infoGain))            #打印每一個特徵的信息增益
        if (infoGain > bestInfoGain):                             #計算信息增益
            bestInfoGain = infoGain                             #更新信息增益,找到最大的信息增益
            bestFeature = i                                     #記錄信息增益最大的特徵的索引值
    return bestFeature                         
View Code
5)統計類標籤
"""
函數說明:統計classList中出現此處最多的元素(類標籤)

Parameters:
    classList - 類標籤列表
Returns:
    sortedClassCount[0][0] - 出現此處最多的元素(類標籤)

"""
def majorityCnt(classList):
    classCount = {}
    for vote in classList:                                        #統計classList中每一個元素出現的次數
        if vote not in classCount.keys():classCount[vote] = 0    
        classCount[vote] += 1
    sortedClassCount = sorted(classCount.items(), key = operator.itemgetter(1), reverse = True)        #根據字典的值降序排序
    return sortedClassCount[0][0]                                #返回classList中出現次數最多的元素

"""
View Code

6)建立決策樹github

"""
函數說明:建立決策樹

Parameters:
    dataSet - 訓練數據集
    labels - 分類屬性標籤
    featLabels - 存儲選擇的最優特徵標籤
Returns:
    myTree - 決策樹

"""
def createTree(dataSet, labels, featLabels):
    classList = [example[-1] for example in dataSet]            #取分類標籤(是否放貸:yes or no)
    if classList.count(classList[0]) == len(classList):            #若是類別徹底相同則中止繼續劃分
        return classList[0]
    if len(dataSet[0]) == 1:                                    #遍歷完全部特徵時返回出現次數最多的類標籤
        return majorityCnt(classList)
    bestFeat = chooseBestFeatureToSplit(dataSet)                #選擇最優特徵
    bestFeatLabel = labels[bestFeat]                            #最優特徵的標籤
    featLabels.append(bestFeatLabel)
    myTree = {bestFeatLabel:{}}                                    #根據最優特徵的標籤生成樹
    del(labels[bestFeat])                                        #刪除已經使用特徵標籤
    featValues = [example[bestFeat] for example in dataSet]        #獲得訓練集中全部最優特徵的屬性值
    uniqueVals = set(featValues)                                #去掉重複的屬性值
    for value in uniqueVals:                                    #遍歷特徵,建立決策樹。                        
        myTree[bestFeatLabel][value] = createTree(splitDataSet(dataSet, bestFeat, value), labels, featLabels)
    return myTree
View Code

遞歸建立決策樹時,遞歸有兩個終止條件:第一個中止條件是全部的類標籤徹底相同,則直接返回該類標籤;第二個中止條件是使用完了全部特徵,仍然不能將數據劃分僅包含惟一類別的分組,即決策樹構建失敗,特徵不夠用。此時說明數據緯度不夠,因爲第二個中止條件沒法簡單地返回惟一的類標籤,這裏挑選出現數量最多的類別做爲返回值。算法

7)樹的可視化
"""
函數說明:獲取決策樹葉子結點的數目

Parameters:
    myTree - 決策樹
Returns:
    numLeafs - 決策樹的葉子結點的數目

"""
def getNumLeafs(myTree):
    numLeafs = 0                                                #初始化葉子
    firstStr = next(iter(myTree))                                #python3中myTree.keys()返回的是dict_keys,不在是list,因此不能使用myTree.keys()[0]的方法獲取結點屬性,可使用list(myTree.keys())[0]
    secondDict = myTree[firstStr]                                #獲取下一組字典
    for key in secondDict.keys():
        if type(secondDict[key]).__name__=='dict':                #測試該結點是否爲字典,若是不是字典,表明此結點爲葉子結點
            numLeafs += getNumLeafs(secondDict[key])
        else:   numLeafs +=1
    return numLeafs

"""
函數說明:獲取決策樹的層數

Parameters:
    myTree - 決策樹
Returns:
    maxDepth - 決策樹的層數

"""
def getTreeDepth(myTree):
    maxDepth = 0                                                #初始化決策樹深度
    firstStr = next(iter(myTree))                                #python3中myTree.keys()返回的是dict_keys,不在是list,因此不能使用myTree.keys()[0]的方法獲取結點屬性,可使用list(myTree.keys())[0]
    secondDict = myTree[firstStr]                                #獲取下一個字典
    for key in secondDict.keys():
        if type(secondDict[key]).__name__=='dict':                #測試該結點是否爲字典,若是不是字典,表明此結點爲葉子結點
            thisDepth = 1 + getTreeDepth(secondDict[key])
        else:   thisDepth = 1
        if thisDepth > maxDepth: maxDepth = thisDepth            #更新層數
    return maxDepth

"""
函數說明:繪製結點

Parameters:
    nodeTxt - 結點名
    centerPt - 文本位置
    parentPt - 標註的箭頭位置
    nodeType - 結點格式
Returns:
    無

"""
def plotNode(nodeTxt, centerPt, parentPt, nodeType):
    arrow_args = dict(arrowstyle="<-")                                            #定義箭頭格式
    font = FontProperties(fname=r"c:\windows\fonts\simsun.ttc", size=14)        #設置中文字體
    createPlot.ax1.annotate(nodeTxt, xy=parentPt,  xycoords='axes fraction',    #繪製結點
        xytext=centerPt, textcoords='axes fraction',
        va="center", ha="center", bbox=nodeType, arrowprops=arrow_args, FontProperties=font)

"""
函數說明:標註有向邊屬性值

Parameters:
    cntrPt、parentPt - 用於計算標註位置
    txtString - 標註的內容
Returns:
    無

""" 
def plotMidText(cntrPt, parentPt, txtString):
    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)

"""
函數說明:繪製決策樹

Parameters:
    myTree - 決策樹(字典)
    parentPt - 標註的內容
    nodeTxt - 結點名
Returns:
    無

""" 
def plotTree(myTree, parentPt, nodeTxt):
    decisionNode = dict(boxstyle="sawtooth", fc="0.8")                                        #設置結點格式
    leafNode = dict(boxstyle="round4", fc="0.8")                                            #設置葉結點格式
    numLeafs = getNumLeafs(myTree)                                                          #獲取決策樹葉結點數目,決定了樹的寬度
    depth = getTreeDepth(myTree)                                                            #獲取決策樹層數
    firstStr = next(iter(myTree))                                                            #下個字典                                                 
    cntrPt = (plotTree.xOff + (1.0 + float(numLeafs))/2.0/plotTree.totalW, plotTree.yOff)    #中心位置
    plotMidText(cntrPt, parentPt, nodeTxt)                                                    #標註有向邊屬性值
    plotNode(firstStr, cntrPt, parentPt, decisionNode)                                        #繪製結點
    secondDict = myTree[firstStr]                                                            #下一個字典,也就是繼續繪製子結點
    plotTree.yOff = plotTree.yOff - 1.0/plotTree.totalD                                        #y偏移
    for key in secondDict.keys():                                
        if type(secondDict[key]).__name__=='dict':                                            #測試該結點是否爲字典,若是不是字典,表明此結點爲葉子結點
            plotTree(secondDict[key],cntrPt,str(key))                                        #不是葉結點,遞歸調用繼續繪製
        else:                                                                                #若是是葉結點,繪製葉結點,並標註有向邊屬性值                                             
            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

"""
函數說明:建立繪製面板

Parameters:
    inTree - 決策樹(字典)
Returns:
    無

""" 
def createPlot(inTree):
    fig = plt.figure(1, facecolor='white')                                                    #建立fig
    fig.clf()                                                                                #清空fig
    axprops = dict(xticks=[], yticks=[])
    createPlot.ax1 = plt.subplot(111, frameon=False, **axprops)                                #去掉x、y軸
    plotTree.totalW = float(getNumLeafs(inTree))                                            #獲取決策樹葉結點數目
    plotTree.totalD = float(getTreeDepth(inTree))                                            #獲取決策樹層數
    plotTree.xOff = -0.5/plotTree.totalW; plotTree.yOff = 1.0;                                #x偏移
    plotTree(inTree, (0.5,1.0), '')                                                            #繪製決策樹
    plt.show()                                                                                #顯示繪製結果
View Code

8)執行決策樹windows

依靠訓練數據構造好決策樹以後能夠用於實際數據分類。app

"""
函數說明:使用決策樹分類

Parameters:
    inputTree - 已經生成的決策樹
    featLabels - 存儲選擇的最優特徵標籤
    testVec - 測試數據列表,順序對應最優特徵標籤
Returns:
    classLabel - 分類結果

""" 
def classify(inputTree, featLabels, testVec):
    firstStr = next(iter(inputTree))                                                        #獲取決策樹結點
    secondDict = inputTree[firstStr]                                                        #下一個字典
    featIndex = featLabels.index(firstStr)                                                
    for key in secondDict.keys():
        if testVec[featIndex] == key:
            if type(secondDict[key]).__name__ == 'dict':
                classLabel = classify(secondDict[key], featLabels, testVec)
            else: classLabel = secondDict[key]
    return classLabel
View Code

9)決策樹存儲dom

能夠調用python模塊中的pickle序列化對象,這樣可以在每次執行時調用已經構造好的決策樹

"""
函數說明:存儲決策樹

Parameters:
    inputTree - 已經生成的決策樹
    filename - 決策樹的存儲文件名
Returns:
    無

""" 
def storeTree(inputTree, filename):
    with open(filename, 'wb') as fw:
        pickle.dump(inputTree, fw)
View Code

4.2 基於sklearn的代碼實現

一樣,python的sklearn庫也提供了決策樹的模型-DecisionTreeClassifier,能夠直接調用,使用方便。具體介紹參見 官方文檔
class sklearn.tree.DecisionTreeClassifier(criterion=’gini’, splitter=’best’, max_depth=None, min_samples_split=2, min_samples_leaf=1, min_weight_fraction_leaf=0.0, max_features=None, random_state=None, max_leaf_nodes=None, min_impurity_decrease=0.0, min_impurity_split=None, class_weight=None, presort=False)

參數介紹:

  · criterion: 特徵選擇標準,默認值爲‘gini’,即CART算法。(entropy, gini)
  · splitter: 特徵劃分標準,默認值爲‘best’。(best, random) best在特徵的全部劃分點中找出最優的劃分點,random隨機的在部分劃分點中找局部最優的劃分點。默認的‘best’適合樣本量不大的時候,而若是樣本數據量很是大,此時決策樹構建推薦‘random’。
  · max_depth: 決策樹最大深度。默認值是‘None’。(int,  None)經常使用的能夠取值10-100之間,經常使用來解決過擬合。
  · min_samples_split: 內部節點再劃分所需最小樣本數。默認值爲2。(int, float)
  · min_samples_leaf: 葉子節點最少樣本數。
  · min_weight_fraction_leaf: 葉子節點最小的樣本權重和。默認爲0。(float)
  · max_features: 在劃分數據集時考慮的最多的特徵值數量。
  · random_state: 默認是None(int, randomSate instance, None)
  · max_leaf_nodes: 最大葉子節點數。默認爲None。(int, None)經過設置最大葉子節點數,能夠防止過擬合。
  · min_impurity_decrease: 節點劃分最小不純度。默認值爲‘0’。(float,)
  · min_impurity_split: 信息增益的閥值。
  · class_weight: 類別權重。默認爲None,(dict, list of dicts, balanced)
  · presort: bool,默認是False,表示在進行擬合以前,是否預分數據來加快樹的構建。
 
實例:項目採用用決策樹預測隱形眼鏡類型,數據集下載地址:
模型構建以後可使用Graphviz可視化樹,pydotplus和Grphviz。肯定好決策樹後能夠進行預測。項目代碼以下:
# -*- coding: UTF-8 -*-
from sklearn.preprocessing import LabelEncoder, OneHotEncoder
from sklearn.externals.six import StringIO
from sklearn import tree
import pandas as pd
import numpy as np
import pydotplus

if __name__ == '__main__':
    with open('lenses.txt', 'r') as fr:                                        #加載文件
        lenses = [inst.strip().split('\t') for inst in fr.readlines()]        #處理文件
    lenses_target = []                                                        #提取每組數據的類別,保存在列表裏
    for each in lenses:
        lenses_target.append(each[-1])
    print(lenses_target)

    lensesLabels = ['age', 'prescript', 'astigmatic', 'tearRate']            #特徵標籤       
    lenses_list = []                                                        #保存lenses數據的臨時列表
    lenses_dict = {}                                                        #保存lenses數據的字典,用於生成pandas
    for each_label in lensesLabels:                                            #提取信息,生成字典
        for each in lenses:
            lenses_list.append(each[lensesLabels.index(each_label)])
        lenses_dict[each_label] = lenses_list
        lenses_list = []
    # print(lenses_dict)                                                        #打印字典信息
    lenses_pd = pd.DataFrame(lenses_dict)                                    #生成pandas.DataFrame
    # print(lenses_pd)                                                        #打印pandas.DataFrame
    le = LabelEncoder()                                                        #建立LabelEncoder()對象,用於序列化           
    for col in lenses_pd.columns:                                            #序列化
        lenses_pd[col] = le.fit_transform(lenses_pd[col])
    # print(lenses_pd)                                                        #打印編碼信息

    clf = tree.DecisionTreeClassifier(max_depth = 4)                        #建立DecisionTreeClassifier()類
    clf = clf.fit(lenses_pd.values.tolist(), lenses_target)                    #使用數據,構建決策樹
    dot_data = StringIO()
    tree.export_graphviz(clf, out_file = dot_data,                            #繪製決策樹
                        feature_names = lenses_pd.keys(),
                        class_names = clf.classes_,
                        filled=True, rounded=True,
                        special_characters=True)
    graph = pydotplus.graph_from_dot_data(dot_data.getvalue())
    graph.write_pdf("tree.pdf")                                                #保存繪製好的決策樹,以PDF的形式存儲。
View Code

 

參考:
相關文章
相關標籤/搜索