学习MachineLearing第三日 决策树
关于信息熵和信息增益的计算,没有构建决策树的部分。
# 决策树
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 # 返回数据集和分类属性
# 计算给定数据集的经验熵
def calcEnt(dataSet):
# 返回数据集的行数
numEntires=len(dataSet)
# 保存每个标签出现次数的字典
labelCounts={}
# 遍历每一个特征向量
for eigenVec in dataSet:
# 提取当前特征向量的标签
currentlabel=eigenVec[-1]
# 如果标签没有存在字典中,添加进去
if (currentlabel not in labelCounts.keys()):
labelCounts[currentlabel] = 0
# 标签计数
labelCounts[currentlabel] += 1
# 定义香农熵
Ent=0.0
# 遍历标签
for key in labelCounts:
# 计算标签的概率
prob = float(labelCounts[key]) / numEntires
# 计算此标签的信息熵,并累加
# Ent = -Σ(1~k)pklog2(pk)
Ent -= prob * log(prob, 2)
return Ent
# 计算各个特征的信息增益,信息增益可由信息熵减去条件熵推出
def splitDataSet(dataSet, axis, value):
"""
:param dataSet: 待划分数据集
:param axis: 划分数据集的特征值
:param value:需要返回特征的值
:return: 无
"""
retDataSet = []
for eigenVec in dataSet:
if(eigenVec[axis] == value):
reducedFeatVec = eigenVec[:axis]
reducedFeatVec.extend(eigenVec[axis+1:])
retDataSet.append(reducedFeatVec)
return retDataSet
def chooseBeatFeatureToSplit(dataSet):
"""
:param dataSet:数据集
:return: 返回最大特征的索引值
"""
numFeatures = len(dataSet[0]) - 1
# 计算数据集的信息熵
baseEntropy = calcEnt(dataSet)
# 定义信息增益
beatGain = 0.0
# 最优特征的索引值
beatFeatureIndex = -1
# 遍历所有特征
for i in range(numFeatures):
# 获取dataSet的第i个特征
featList = [example[i] for example in dataSet]
# 创建set集合,元素不可重复
uniqueVals = set(featList)
# 定义条件经验熵
newEntropy = 0.0
# 遍历标签
for value in uniqueVals:
# 依照特征,划分子集
subDataSet = splitDataSet(dataSet, i, value)
print(subDataSet)
# 求出子集的概率
prob = len(subDataSet) / float(len(dataSet))
# 计算条件熵
newEntropy += prob * calcEnt(subDataSet)
# 计算此特征下的信息增益
infoGain = baseEntropy - newEntropy
print("第%d个特征的增益为%.3f" % (i, infoGain))
if(infoGain > beatGain):
beatGain = infoGain
beatFeatureIndex = i
return beatFeatureIndex
if __name__ == '__main__':
dataSet, feature = createDataSet()
print("数据集:",dataSet)
print("信息熵:",calcEnt(dataSet))
print("最优特征索引值:" + str(chooseBeatFeatureToSplit(dataSet)))