1. 程式人生 > >決策樹演算法——熵與資訊增益(Python3實現)

決策樹演算法——熵與資訊增益(Python3實現)

1、熵、條件熵與資訊增益

(1)熵(entropy)

(2)條件熵(conditional entropy)

(3)資訊增益(information gain)

2、資訊增益演算法實現流程

2、資料集以及每個特徵資訊增益的計算

2.1貸款申請樣本資料表

                                                                    表5.1 貸款申請樣本資料表

1

青年

一般

2

青年

3

青年

4

青年

一般

5

青年

一般

6

中年

一般

7

中年

8

中年

9

中年

非常好

10

中年

非常好

11

老年

非常好

12

老年

13

老年

14

老年

非常好

15

老年

一般

2.2根據資訊增益準則選擇最優特徵

3、Python3實現熵與資訊增益選擇最優特徵

  在編寫程式碼之前,我們先對資料集進行屬性標註。

  • 年齡:0代表青年,1代表中年,2代表老年;
  • 有工作:0代表否,1代表是;
  • 有自己的房子:0代表否,1代表是;
  • 信貸情況:0代表一般,1代表好,2代表非常好;
  • 類別(是否給貸款):no代表否,yes代表是。

程式碼實現如下:

# -*- coding: UTF-8 -*-
from math import log


"""
函式說明:建立測試資料集
"""
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                           #返回資料集和分類屬性


"""
函式說明:計算給定資料集的經驗熵(夏農熵)
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                                #返回經驗熵(夏農熵)


"""
函式說明:按照給定特徵劃分資料集

Parameters:
    dataSet - 待劃分的資料集
    axis - 劃分資料集的特徵
    value - 需要返回的特徵的值
"""
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                                   #返回劃分後的資料集


"""
函式說明:選擇最優特徵
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                                             #返回資訊增益最大的特徵的索引值


if __name__ == '__main__':
    dataSet, features = createDataSet()
    entropy=calcShannonEnt(dataSet)
    bestfeature=chooseBestFeatureToSplit(dataSet)
    print("訓練集的熵為:%f"%(entropy))
    print("最優特徵索引值:" + str(bestfeature))

輸出結果為:

補充:

資訊增益比(增益率)

基尼指數

參考:統計學習方法——李航;機器學習實戰;機器學習——周志華。