简单介绍

决策树是一个非常常见并且优秀的机器学习中监督学习的算法,它易于理解、可解释性强,是一种简单且广泛使用的分类器。通过数据来训练该预测模型,从而高效对未打标签的数据进行分类。因此简单来说那,决策树就是可以看做一个if-then规则的集合。我们从决策树的根结点到每一个都叶结点构建一条规则,根据数据不同的输入选择下一个结点,直到达到了最终的叶结点。


ID3算法核心

知晓了决策树实现的功能之后,假如我们构建决策树,那么应该如何选择属性特征值呢。如上图所示,怎么判断出纹理这个特征就是树的根节点,为何不是触感,而色泽又凭什么要排在根蒂结点之后。这个问题也就是决策树学习的关键。其实就是选择最优划分属性,希望划分后,分支结点的“正确性”越来越高。如何计算该特征的正确性即为区分不同决策树的关键,下面就要引入一个信息的度量概念,信息增益,而ID3决策树在构建树的过程中,就是以信息增益来判断的。

香浓理论中的信息熵是度量样本集合不确定度(纯度)的最常用的指标。而在ID3算法中,我们采取信息增益这个量来作为纯度的度量。我们选取使得信息增益最大的特征进行分裂!信息熵是代表随机变量的复杂度(不确定度),条件熵代表在某一个条件下,随机变量的复杂度(不确定度)。而我们的信息增益恰好是:信息熵-条件熵。

数据的( Ck表示集合 D 中属于第 k 类样本的样本子集 )信息熵公式为:


针对某个特征 A,对于数据集 D 的条件熵为:


信息增益 = 信息熵 - 条件熵:


信息增益就表示为如果我们知道了属性A的信息,则可以使得样本集合不确定度减少的程度。那么我们选择决策树分裂的条件即为当前特征中信息增益最大的特征。

ID3决策树的构建过程

  • 初始化特征集合和数据集合;
  • 计算数据集合信息熵和所有特征的条件熵,选择信息增益最大的特征作为当前决策节点;
  • 更新数据集合和特征集合(删除上一步使用的特征,并按照特征值来划分不同分支的数据集合);
  • 重复 2,3 两步,若子集值包含单一特征,则为分支叶子节点。

ID3决策树的构建过程如上所示, 现在我们以周志华老师的《机器学习》一书中的例子来看一个具体的过程。数据集合如下:


正例(好瓜)占 8/17,反例占 9/17 ,根结点的信息熵为 :


计算当前属性集合{色泽,根蒂,敲声,纹理,脐部,触感}中每个属性的信息增益。
色泽有3个可能的取值:{青绿,乌黑,浅白}
D1(色泽=青绿) = {1, 4, 6, 10, 13, 17},正例 3/6,反例 3/6
D2(色泽=乌黑) = {2, 3, 7, 8, 9, 15},正例 4/6,反例 2/6
D3(色泽=浅白) = {5, 11, 12, 14, 16},正例 1/5,反例 4/5
三个分支结点的信息熵值为:


那么我们可以知道属性色泽的信息增益为:


同理其他的特征值的信息增益为:


于是我们找到了信息增益最大的属性纹理,它的Gain(D,纹理) = 0.381最大。
于是我们选择的划分属性为“纹理”。
如下:


于是,我们可以得到了三个子结点,对于这三个子节点,我们可以递归的使用刚刚找信息增益最大的方法进行选择特征属性,
比如:D1(纹理=清晰) = {1, 2, 3, 4, 5, 6, 8, 10, 15},第一个分支结点可用属性集合{色泽、根蒂、敲声、脐部、触感},基于 D1各属性的信息增益,分别求的如下:


于是我们可以选择特征属性为根蒂,脐部,触感三个特征属性中任选一个(因为他们三个相等并最大),其它俩个子结点同理,然后得到新一层的结点,再递归的由信息增益进行构建树即可。
我们最终的决策树如下:


至此,决策树构建完毕,ID3决策树的构建过程到此位置。

决策树代码实现

import numpy as np
import pandas as pd
import treePlotterclass TreeNode(object):def __init__(self, ids=None, children=[], entropy=0, depth=0):self.ids = ids  # 此节点中的数据索引self.entropy = entropy  # 熵,稍后填充self.depth = depth  # 到根节点的距离self.split_attribute = None  # 选择哪个属性,它是非叶子的self.children = children  # 其子节点列表self.order = None  # 孩子中 split_attribute 的值顺序self.label = None  # 如果是叶子节点的标签def set_properties(self, split_attribute, order):self.split_attribute = split_attributeself.order = orderdef set_label(self, label):self.label = labeldef entropy(freq):# remove prob 0freq_0 = freq[np.array(freq).nonzero()[0]]prob_0 = freq_0 / float(freq_0.sum())return -np.sum(prob_0 * np.log(prob_0))class DecisionTreeID3(object):def __init__(self, max_depth=10, min_samples_split=2, min_gain=1e-4):self.root = Noneself.max_depth = max_depthself.min_samples_split = min_samples_splitself.Ntrain = 0self.min_gain = min_gaindef fit(self, data, target):self.Ntrain = data.count()[0]self.data = dataself.attributes = list(data)self.target = targetself.labels = target.unique()ids = range(self.Ntrain)self.root = TreeNode(ids=ids, entropy=self._entropy(ids), depth=0)queue = [self.root]while queue:node = queue.pop()if node.depth < self.max_depth or node.entropy < self.min_gain:node.children = self._split(node)if not node.children:  # leaf nodeself._set_label(node)queue += node.childrenelse:self._set_label(node)def _entropy(self, ids):# 计算具有索引 id 的节点的熵# print('ncaa', len(ids))if len(ids) == 0:return 0ids = [i + 1 for i in ids]  # 熊猫系列索引从1开始# print('ids', ids)freq = np.array(self.target[ids].value_counts())# print('ncaa', self.target[ids].value_counts())return entropy(freq)def _set_label(self, node):# find label for a node if it is a leaf# simply chose by major votingtarget_ids = [i + 1 for i in node.ids]  # target is a series variablenode.set_label(self.target[target_ids].mode()[0])  # most frequent labeldef _split(self, node):ids = node.idsbest_gain = 0best_splits = []best_attribute = Noneorder = Nonesub_data = self.data.iloc[ids, :]for i, att in enumerate(self.attributes):values = self.data.iloc[ids, i].unique().tolist()if len(values) == 1:continue  # entropy = 0splits = []for val in values:sub_ids = sub_data.index[sub_data[att] == val].tolist()splits.append([sub_id - 1 for sub_id in sub_ids])# don't split if a node has too small number of pointsif min(map(len, splits)) < self.min_samples_split:continue# information gainHxS = 0for split in splits:HxS += len(split) * self._entropy(split) / len(ids)gain = node.entropy - HxSprint(att, '   ⑧⑧⑧⑧⑧⑧⑧⑧   ' , gain,sep='   ')if gain < self.min_gain:continue  # stop if small gainif gain > best_gain:best_gain = gainbest_splits = splitsbest_attribute = attorder = valuesif best_attribute != None:print('信息增益最大的属性为', best_attribute)node.set_properties(best_attribute, order)child_nodes = [TreeNode(ids=split,entropy=self._entropy(split), depth=node.depth + 1) for split in best_splits]return child_nodesdef predict(self, new_data):"""param new_data: 一个新的数据框,每一行都是一个数据点return: 每行的预测标签"""npoints = new_data.count()[0]labels = [None] * npointsfor n in range(npoints):x = new_data.iloc[n, :]  # one point# 如果没有遇到叶子,则从根开始并递归旅行node = self.rootwhile node.children:node = node.children[node.order.index(x[node.split_attribute])]labels[n] = node.labelreturn labelsdef show_tree(tnode: TreeNode):global decs_treeflag = Trueif not tnode.children:returnif tnode.split_attribute != None:decs_tree += "'{}':{{".format(tnode.split_attribute)print(tnode.split_attribute, ':{', sep='', end='')ans = tnode.orderfor i in range(len(ans)):temp = tnode.children[ans.index(ans[i])]decs_tree += "'{}':".format(ans[i])print(ans[i], ':', sep=' ', end='')if temp.label != None:decs_tree += "'" + temp.label + "'"print(temp.label,end='')else:flag = not flagdecs_tree += '{'print('{',end='')show_tree(temp)if not flag:decs_tree += '}'print('}',end='')flag = Trueif i != len(ans) - 1:decs_tree += ','print(',',end='')decs_tree += '}'print('}',end='')# if tnode.label != None:if __name__ == "__main__":global decs_treedecs_tree = ''df = pd.read_csv('weather.csv', index_col=0, parse_dates=True)print(df)X = df.iloc[:, :-1]y = df.iloc[:, -1]tree = DecisionTreeID3(max_depth=3, min_samples_split=2)tree.fit(X, y)print(tree.predict(X))node = tree.rootshow_tree(node)print()decs_tree = '{' + decs_tree + '}'print(eval(decs_tree))treePlotter.ID3_Tree(eval(decs_tree))

可视化呈现决策树

至此机器已经可以理解我们所写的决策树,但是人仍不便于理解,为了从数据集合中将决策树抽象成人能理解的树图,我们输出训练的决策树的结构,且将其进行可视化。(相关代码存放于Github中,虽然我也是借鉴别人的,>灬<,HJNODM)

参考书籍 周志华老师的西瓜书
参考博客 ID3算法思想
参考博客 决策树过程理解

[原文连接已失效]

ID3决策树的Python实现与理解相关推荐

  1. 监督学习 | ID3 决策树原理及Python实现

    文章目录 1. 信息熵 Information Entropy 1.1 信息熵公式推导 2. 信息增益 Information Gain 2.1 信息增益最大化 2.1.1 利用离散特征进行分类 2. ...

  2. id3决策树 鸢尾花 python_C4.5决策树Python代码实现

    C4.5决策树Python代码实现 我们知道C4.5决策树与ID3决策树最主要的区别就是C4.5使用信息增益率来划分最优属性.因为使用信息增益来划分属性的话会存在以下这些缺点:对可取属性多的特征有偏好 ...

  3. id3决策树 鸢尾花 python_机器学习之分类回归树(python实现CART)

    机器学习之分类回归树(python实现CART) 之前有文章介绍过决策树(ID3).简单回顾一下:ID3每次选取最佳特征来分割数据,这个最佳特征的判断原则是通过信息增益来实现的.按照某种特征切分数据后 ...

  4. 决策树ID3代码(Python)

    决策树ID3代码(Python) 上一节介绍了决策树的递归算法框架(create),这一节将用Python语言实现一个小程序.代码和数据来源于<机器学习实战>Peter Harringto ...

  5. ID3决策树 Python实现 + sklearn库决策树模型的应用

    本文介绍机器学习中决策树算法的python实现过程 共介绍两类方法: (1)亲手实习Python ID3决策树经典算法 (2)利用sklearn库实现决策树算法 关于决策树的原理,指路:机器学习 第四 ...

  6. 机器学习入门学习笔记:(3.2)ID3决策树程序实现

    前言 之前的博客中介绍了决策树算法的原理并进行了数学推导(机器学习入门学习笔记:(3.1)决策树算法).决策树的原理相对简单,决策树算法有:ID3,C4.5,CART等算法.接下来将对ID3决策树算法 ...

  7. python决策树实例_机器学习中的决策树及python实例

    一棵树在现实生活中有许多枝叶,事实上树的概念在机器学习也有广泛应用,涵盖了分类和回归.在决策分析中,决策树可用于直观地决策和作出决策.决策树,顾名思义,一个树状的决策模型.尽管数据挖掘与机器学习中常常 ...

  8. id3决策树 鸢尾花 python_决策树算法——集成学的基础!

    文 | 菊子皮 (转载请注明出处)同名B站:AIAS编程有道 「摘要:」  决策树在机器学习算法中是一个相对简单的算法,如果不能进行适当的剪枝就容易造成模型的过拟合.决策树算法也是当前很多集成学习算法 ...

  9. 基于信息增益的ID3决策树介绍。

    这篇文章介绍一下一种常见的机器学习算法:决策树.这篇文章的主要是根据<机器学习>中的知识点汇总的,其中使用了<机器学习实战>的代码.关于决策树中基本信息以及公式更加推荐看一看& ...

最新文章

  1. 计算机应用基础教材编写建议,【计算机应用论文】计算机应用基础校本教材编写研究(共3136字)...
  2. python 语音websocket_Python 牺牲性能以提升程序员的工作效率
  3. mysql查询哪天,Mysql日期查询的详细介绍
  4. 三维坐标 偏转_什么是激光三维扫描?
  5. Gitlab怎样添加组、创建用户、创建项目与推送代码
  6. android内部通信handler
  7. 【Swift】在Swift中获取当前的wifi SSID
  8. Android 关于后台杀死App之后改变服务器状态的一些尝试
  9. TURBOMAIL反垃圾邮件清洁工,还你一个清爽的邮箱
  10. PAT 1068. 万绿丛中一点红(20)-乙级
  11. POJ 1149 PIGS(最大流)dinic模板注释
  12. Linux 软件安装与卸载
  13. Pr学习笔记——添加字幕流
  14. linux 系统gbk字符集,linux 修改字符集gbk
  15. 树莓派 or 香橙派 部署c# .net 并设置开机启动
  16. pwnable.kr wp passcode
  17. 三十.什么是vm和vc?
  18. easy-mock使用
  19. Codeforces #308 C. Vanya and Scales
  20. 《基本穿搭:适用一生的穿衣法则》总结

热门文章

  1. STM32F10x UART多字节接收,程序卡死
  2. 基于ThinkPhp6搭建的博客管理系统
  3. 你不知道的小技巧 — 把对象交给spring管理的3种方法及经典应用
  4. 【2022/1/14】thinkphp源码无差别阅读(十九)
  5. MIT的算法导论课程资料
  6. 统计南京游玩地方(更新中)
  7. raid技术快速入门
  8. c语言计算标准体重的程序,C语言标准体重测试程序,请大家帮我看下,我的代码哪错了?...
  9. 成熟产品经理必备特质
  10. STM32F103+VL53L0X寄存器操作