決策樹

基本概念和公式

  • 信息
  • 信息熵
    度量樣本集合純度最常用的一種指標:
    在這裏插入圖片描述
    Ent(D)值越小,則D純度越高
  • 信息增益
    在這裏插入圖片描述
    (信息增益標準對可取數目較多的屬性有所偏好)
  • 信息增益率
    在這裏插入圖片描述
    (信息增益率標準對可取數目較少的屬性有所偏好)
    (C4.5採取的策略是,先從候選屬性中找出信息增益高於平均值的屬性,再從中選擇增益率最高的)
  • 基尼指數
    基尼值:
    反映從數據集D中隨機抽取兩個樣本,其類別標誌不一致的概率
    在這裏插入圖片描述
    Gini(D)越小,數據集D的純度越高
    屬性a的基尼指數:
    在這裏插入圖片描述
  • 剪枝處理
    剪枝處理是對付過擬合的一種方法。
    預剪枝:
    在決策樹生成過程中,對每個節點在劃分前後進行估計,若當前節點劃分不能帶來決策樹泛化性能的提升(即:訓練集精度提升),則停止劃分當前結點,並將當前節點作爲葉子節點。
    後剪枝:
    從訓練集中生成一棵完整的決策樹,然後對節點(子節點都是葉節點)進行剪枝,若剪枝後決策樹的泛化能力比未剪枝前好,則將此節點剪掉,作爲葉節點,葉節點的標記爲所有包含的樣本中個數最多的標記。
    兩種剪枝方法的比較:
    後剪枝保留了更多的分支,欠擬合風險小,但訓練時間開銷更大。
  • 連續值處理
    候選劃分點集合:
    T_a={(ai+a(i+1))/2|1≤i≤n-1}
    根據信息增益公式:
    在這裏插入圖片描述
    計算每個劃分集合的點劃分出來的信息增益值,然後選擇信息增益值最大的點作爲最佳劃分點。
  • 缺失值的處理
    樣本集在屬性a上沒有缺失的集合記爲,權重Wx。
    在這裏插入圖片描述
    在這裏插入圖片描述
    若樣本在屬性a上的值缺失,則同時將樣本華人與所有子節點,權值設爲R*W

決策樹的代碼實現

  • 香農公式的代碼實現
from math import log


def calcshannonEnt(dataset):
    numData =len(dataset)
    featVect = {}
    calcshannon = 0.0
    for data in dataset:
        label =data[-1]
        if  label not in featVect.keys():
            featVect[label] = 0
        featVect[label] +=1
    for i in featVect.keys():
        sublabels =featVect[i]
        p = float(sublabels)/numData
        calcshannon -= p*log(p, 2)
    return calcshannon


  • 數據集的代碼實現
def createDataSet():
    data = [
        [1, 1, 'yes'],
        [1, 1, 'yes'],
        [1, 0, 'no'],
        [0, 1, 'no'],
        [0, 1, 'no']
    ]
    labels = ['no surfacing', 'flippers']
    return data, labels

  • 劃分數據集
# coding=utf-8
#劃分數據集
def splitDataSet(dataset, axis, value):
    newDataSet = []
    for data in dataset:
        feature = data[axis]
        if feature == value:
            addFeat = data[:axis]
            addFeat.extend(data[axis+1:])
            newDataSet.append(addFeat)
    return newDataSet

  • 找最好的特徵對數據集進行劃分
# coding=utf-8
#信息增益最大即爲最好特徵
from calcshannonEnt import *
from splitDataSet import *


def chooseBestFeaturetoSplit(dataset):
    numFeature = len(dataset[0])-1
    baseCalcshannon = calcshannonEnt(dataset)
    bestInfoGain = 0.0
    bestFeature = -1
    for i in range(numFeature):
        numFeatureValue = [example[i] for example in dataset]
        uniqueValue = set(numFeatureValue)
        currentCalcshannon = 0.0
        for value in uniqueValue:
            subData = splitDataSet(dataset, i, value)
            p = float(len(subData))/len(dataset)
            currentCalcshannon += p*calcshannonEnt(subData)
        infoGain = baseCalcshannon - currentCalcshannon
        if infoGain>bestInfoGain:
            bestInfoGain = infoGain
            bestFeature = i
    return bestFeature



  • 構造決策樹
# coding=utf-8
"""決策樹創建設計遞歸過程"""
from chooseBestFeaturetoSplit import *
from majority import *


def createTree(dataset,labels):
    #遞歸出口:樣本所有分類標籤一致,所有特徵值考察完畢
    labelsValue = [example[-1] for example in dataset]
    if labelsValue.count(labelsValue[0]) == len(labelsValue):
        return labelsValue[0]
    if len(dataset
           [0]) == 1:
        return majority(dataset)
    bestFeature = chooseBestFeaturetoSplit(dataset)
    featureLabels = labels[bestFeature]
    myTree = {featureLabels: {}}
    del(labels[bestFeature])
    valueVect = [example[bestFeature] for example in dataset]
    uniqueVect = set(valueVect)
    for value in uniqueVect:
        subLabel = labels[:]
        myTree[featureLabels][value] = createTree(splitDataSet(dataset, bestFeature, value), subLabel)
    return myTree

確定同一類別中葉節點的標籤

import  operator


def majority(dataset):
    label = [example[-1] for example in dataset]
    uniqueLabel = set(label)
    labelList = {}
    for data in dataset:
        subLabel =data[-1]
        if subLabel not in labelList:
            labelList[subLabel] = 0
        labelList[subLabel] +=1
    labelCount = sorted(labelList.iteritems(), key=operator.itemgetter(1), reverse=True)
    return labelCount[0][0]
  • 確定測試數據標籤
from createTree import *


def classify(myTree,labels,testVect):
    firstStr = myTree.keys()
    secondStr = myTree.keys()[0]
    labelsIndex = labels.index(firstStr)
    for i in secondStr:
        subValue = i.keys()
        if testVect == subValue:
            if subValue.__name__ == 'dict':
                classify(subValue,labels,testVect)
            else:
                return subValue

將決策樹程序存儲起來

import pickle


def storeTree(tree, filename):
    fw = open(filename, 'w')
    pickle.dump(tree, fw)
    fw.close()


def grapTree(filename):
    fr = open(filename)
    return pickle.load(fr)

決策樹優缺點

優點:計算複雜度不高,輸出結果易於理解,對中間值的缺失不敏感,可以處理不相關特徵數據
缺點:可能會產生過度匹配

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章