《机器学习实战》总结:ID3决策树
来源:互联网 发布:科比布莱恩特生涯数据 编辑:程序博客网 时间:2024/05/29 15:36
熵(Entropy)
1、定义
熵是对随机变量不确定程度的度量。设
在《信息论基础 第2版》一书中,对熵的定义如下:
一个离散型随机变量
X 的熵Ent(X) 定义为其中熵的单位为比特。Ent(X)=−∑i=1npi∗log2(pi)
根据熵的定义,熵表示在一个数据集合中,需要用多少的比特位来表示数据所属分类的总数。比如,抛一个硬币有两种可能:正面朝上和反面朝上。则在一个记录了多次抛硬币的结果的数据集合中的所有数据属于两个类:正面朝上类和反面朝上类。这两个类只需要一个比特位就可以表示,则
2、用python计算给定数据集合的熵
在分类算法中,数据的形式一般以矩阵表示,如下表格为海洋生物数据:
其中 属于鱼类 是该数据集中的类标签。显然在这个数据集合中有:
用python计算给定数据集合的熵代码如下:
import numpy as npimport pandas as pdimport matplotlib as mplimport math% matplotlib inline
def CalEnt(labels): # calculate the frequencies of each class frequencies = {} for label in labels: frequencies[label] = frequencies.get(label, 0) + 1 frequencies = np.array(list(frequencies.values())) / len(labels) # calculate the entropy of the dataset corresponding to the class labels Ent = sum([-(fre * math.log(fre, 2)) for fre in frequencies]) return Entlabels = ['yes', 'yes', 'no', 'no', 'no']print('Entropy:')print(CalEnt(labels))
Entropy:0.970950594455
让我们尝试增加一个类别”maybe”的数据,看看熵是如何变化的:
labels2 = ['maybe', 'yes', 'yes', 'no', 'no', 'no']print('Entropy2:')print(CalEnt(labels2))
Entropy2:1.45914791703
信息增益(information gain)
1、定义
要了解信息增益,我们先用上面的海洋生物数据作为例子来说明为什么将数据集进行划分后可以减少熵:
假设将海洋生物的数据按照不浮出水面是否可以生存划分成两个数据子集:一个是“是”的子集,一个是“否”的子集,则划分后得到如下表格:
假设第一个子集为
labels_S1 = ['yes', 'yes', 'no']labels_S2 = ['no', 'no']print("S1's entropy: ", CalEnt(labels_S1))print("S1's entropy: ", CalEnt(labels_S2))
S1's entropy: 0.918295834054S1's entropy: 0.0
为了比较划分数据集后的熵与原来的熵,我们计算划分后的熵的期望值
根据上面的公式,我们可以计算出划分数据集后熵的期望值大约为
显然,划分数据集后熵明显减少了,而熵减少的量就是信息增益:
上述划分的特征向量
计算该类划分的熵期望值可以得到:
labels_S1 = ['yes', 'yes', 'no', 'no']labels_S2 = ['no']print('Expected entropy: ', len(labels_S1) / len(labels) * CalEnt(labels_S1) + len(labels_S2) / len(labels) * CalEnt(labels_S2))
Expected entropy: 0.8
此时信息增益为
2、用python选取给定数据集中信息增益最大的特征向量
对于上面的海洋生物数据集,假设用
其中,第0列表示不浮出水面是否可以生存列,第1列表示是否有脚蹼列。
数据集对应的python列表形式为:dataSet = [[1, 1], [1, 1], [1, 0], [0, 1], [0, 1]],
而数据集中各个特征向量(即各行)对应的标签数组为:labels = [‘yes’, ‘yes’, ‘no’, ‘no’, ‘no’],
对于给定的数据集dataSet(一般是二维数组),选取信息增益最大的特征向量的python代码如下:
# 选择划分后得到信息增益最大的特征向量,返回这个特征向量和对应的最大信息增益def chooseBestFeatureToSplit(dataSet, labels): numRows = len(dataSet) numFeatures = len(dataSet[0]) originalEnt = CalEnt(labels) maxInfoGain = 0.0 bestFeature = 0 for i in range(numFeatures): subDataSets, newLabels, values = splitDataSet(i, dataSet, labels) newEnt = 0.0 for subLabels in newLabels: newEnt += float(len(subLabels)) / float(len(labels)) * CalEnt(subLabels) infoGain = originalEnt - newEnt if infoGain > maxInfoGain: maxInfoGain = infoGain bestFeature = i return bestFeature, maxInfoGain# 根据选择到的特征向量坐标(axis的值)对数据集进行划分,返回划分后的所有数据子集,每个子集对应的标签列表,# 以及每个数据子集对应的特征向量的值def splitDataSet(axis, dataSet, labels): axis = int(axis) newLabels = [] numRows = len(dataSet) featureValues = [] subDataSets = [] subLabels = [] values = [] for i in range(numRows): featureValues.append(dataSet[i][axis]) featureValues = set(featureValues) for value in featureValues: subDataSet, subLabel = splitByValue(axis, value, dataSet, labels) subDataSets.append(subDataSet) subLabels.append(subLabel) values.append(value) return subDataSets, subLabels, values# 根据特征向量的某个值对数据集进行划分,把所有含有这个特征向量的值为value的记录挑选出来形成数据子集# 返回数据子集和对应的标签列表def splitByValue(axis, value, dataSet, labels): subDataSet = [] subLabel = [] for i in range(len(dataSet)): if dataSet[i][axis] == value: newFeature = dataSet[i] subDataSet.append(newFeature) subLabel.append(labels[i]) return subDataSet, subLabeldataSet = [[1, 1], [1, 1], [1, 0], [0, 1], [0, 1]]labels = ['yes', 'yes', 'no', 'no', 'no']bestFeature, maxInfoGain = chooseBestFeatureToSplit(dataSet, labels)subDataSets, subLabels, values = splitDataSet(bestFeature, dataSet, labels)print('subsets: ', subDataSets)print('subLabels: ', subLabels)print('best feature: ', bestFeature)print('max information gain: ', maxInfoGain)
subsets: [[[0, 1], [0, 1]], [[1, 1], [1, 1], [1, 0]]]subLabels: [['no', 'no'], ['yes', 'yes', 'no']]best feature: 0max information gain: 0.419973094022
如上图程序运行结果所示,信息增益最大值为
ID3 决策树
要了解决策树,首先让我们来看看python中可以怎样表示一棵树。在C语言中,得到一棵树只需要知道这棵树的根节点指针,而在python中,可以利用字典这个数据结构来表示一棵树,其中字典中的keys表示父结点,而对应的values表示子结点。
首先我们来创建最简单的ID3决策树,前面已经说过,创建决策树的过程就是不断把数据集划分成混合度更小直至熵接近0的子集的过程,当子集中的熵接近于0时,我们就可以认为该子集中的所有数据属于同一个类,此时分类就结束了,当前的数据集就成为决策树的叶子结点。我们可以认为,在决策树中,各个结点就是一个数据集,父结点是待划分的数据集,子结点是把父结点划分后形成的数据子集,决策树的构建过程就是把根结点数据集一直划分到叶子结点数据集的过程,这个过程是递归定义的。
# 创建决策树def buildDecisionTree(dataSet, labels, feature_dict, labels_dict): # 当数据集中所有的标签都相同时,说明所有数据属于同一类,直接返回对应的标签结果 if labels.count(labels[0]) == len(labels): return labels_dict[labels[0]] # 否则,每次选择信息增益最大的特征向量继续划分数据集,递归建立决策树 bestFeature, maxInfoGame = chooseBestFeatureToSplit(dataSet, labels) subDataSets, subLabels, values = splitDataSet(bestFeature, dataSet, labels) subTree = {} subTree[feature_dict[bestFeature]] = {} for i in range(len(values)): subTree[feature_dict[bestFeature]][values[i]] = buildDecisionTree(subDataSets[i], subLabels[i], feature_dict, labels_dict) return subTreedataSet = [[1, 1], [1, 1], [1, 0], [0, 1], [0, 1]]labels = ['yes', 'yes', 'no', 'no', 'no']feature_dict = { 0 : "No surfacing", 1 : "Flippers" }labels_dict = { 'yes' : "Fish", 'no' : "Not fish" }decisionTree = buildDecisionTree(dataSet, labels, feature_dict, labels_dict)decisionTree
{'No surfacing': {0: 'Not fish', 1: {'Flippers': {0: 'Not fish', 1: 'Fish'}}}}
由结果可知,我们成功地根据样本数据集训练出了一棵决策树,而我们的目的是利用这个决策树对未知的数据进行分类,因此最后还需要一个分类函数:
def classify(decisionTree, features, featuresName): firstClass = list(decisionTree.keys())[0] nextDict = decisionTree[firstClass] firstIndex = featuresName.index(firstClass) nextClass = nextDict[features[firstIndex]] if type(nextClass).__name__ == "dict": return classify(nextClass, features, featuresName) else: return nextClasslabel1 = classify(decisionTree, [1, 1], ["No surfacing", "Flippers"])label2 = classify(decisionTree, [1, 0], ["No surfacing", "Flippers"])print("The first animal is ", label1)print("The second animal is ", label2)
The first animal is FishThe second animal is Not fish
至此,我们完成了一棵ID3决策树的创建和使用。ID3决策树的缺点是可能造成过度匹配,因此我们在实际应用中需要适当裁剪决策树,去掉一些不必要的叶子节点。
以上是我个人学习了《机器学习实战》第3章关于ID3决策树的总结,并根据自己的理解独立写了一遍代码,感觉收获很大,对于ID3决策树的原理基本是理解了,不足之处请指正。
参考文献
1、《机器学习实战》 Peter Harrington 著,李悦 李鹏 曲亚东 王斌 译,人民邮电出版社
2、《信息论基础 第2版》Thomas M.Cover Joy A.Thomas 著,阮吉寿 张华 译,机械工业出版社
- 《机器学习实战》总结:ID3决策树
- 《机器学习实战》ID3-决策树
- 《机器学习实战》之ID3决策树算法
- 【机器学习实战】-02决策树ID3
- 机器学习实战之决策树ID3算法
- 【机器学习实战-python3】决策树ID3
- 机器学习实战-决策树ID3-python代码
- 机器学习实战——简单决策树ID3学习
- 机器学习实战 (2)决策树 (一) ID3算法
- 《机器学习实战》决策树(ID3算法)的分析与实现
- 机器学习实战之 决策树——ID3算法
- 机器学习实战—ch03 .决策树(ID3算法)
- 机器学习实战【2】(决策树ID3算法)
- 机器学习算法-决策树ID3
- 机器学习--决策树(ID3)算法
- <机器学习>ID3决策树javaDemo
- 机器学习之决策树--ID3
- 机器学习-决策树 ID3算法
- 通用类型的两路归并算法实现(二)——面向接口实现通用类型的两路归并
- 百度地图移动版API终于发布了(Android)
- 数组方法实现(一)————数组方法join()
- JPA之使用JPQL语句操作数据库
- 原 Spring + SpringMVC + Mybatis 整合,实现 CRUD (增删改查)
- 《机器学习实战》总结:ID3决策树
- uva10384 The Wall Pusher 推门游戏
- Mongo 聚合框架-Aggregate(二)
- XML的四种生成方式
- php表示一年,一个星期等时间,很好用,方便
- servlet -1
- 链表习题
- ubuntu 卸载 /安装google-chrome
- Oracle PL/SQL常用命令