決策樹演算法——熵與資訊增益(Python3實現)
阿新 • • 發佈:2019-02-20
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))
輸出結果為:
補充:
資訊增益比(增益率)
基尼指數
參考:統計學習方法——李航;機器學習實戰;機器學習——周志華。