决策树的一个重要任务是:为了数据中蕴含的知识信息。
决策树可以使用不熟悉的数据集合,并从中提取除一系列规则,在这些机器根据数据集创建规则时,就是机器学习的过程。
3.1 决策树的构造
- 优点:计算复杂度不高,输出结果易于理解,对中间值的缺失不敏感,可以处理不相关特征数据。
缺点:可能会产生过度匹配问题。
适用数据类型:数值型和标称型。 - 在构造决策树时,我们需要解决的第一个问题是:当前数据集上哪个特征在划分数据分类时起决定性作用。
为了找到决定性特征,划分出最好的结果,我们必须评估每个特征。
完成测试之后,原始数据集就被划分为几个数据子集。
这些数据子集会分布在第一个决策点的所有分支上。
如果某分支上的数据属于同一类型,无需进一步对数据集进行分割。
如果数据子集内的数据不属于同一类型,则需要重复划分数据子集。
直到所有具有相同数据类型的数据均在一个数据子集内。 - 创建分支的伪代码函数createBranch():
- 决策树的一般流程:
(1) 收集数据:可以使用任何方法。
(2) 准备数据:树构造算法只适用于标称型数据,因此数值型数据必须离散化。
(3) 分析数据:可以使用任何方法,构造树完成之后,我们应该检查图形是否符合预期。
(4) 训练算法:构造树的数据结构。
(5) 测试算法:使用经验树计算错误率。
(6) 使用算法:此步骤可以适用于任何监督学习算法,而使用决策树可以更好地理解数据
的内在含义。
3.1.1 信息增益
- 划分数据集的大原则:将无序的数据变得更加有序。
- 信息增益:划分数据集之前之后信息发生的变化。获得信息增益最高的特征就是最好的选择。
- 香农熵(熵):集合信息的度量方式。
- 熵:定义为信息的期望值。
- 信息:符号xi的信息定义:
其中p(xi)是选择该分类的概率。 - 信息熵:
其中n是分类的数目。 - 基尼不纯度:度量集合无序程度的方法。简单的说就是从一个数据集中随机选取子项,度量其被错误分类到其他组里的概率。
程序清单3-1 计算给定数据集的香农熵
1 | from math import log |
执行:
1 | >import trees |
3.1.2 划分数据集
- 使用ID3算法划分数据集。
三组参数:待划分的数据集、划分数据集的特征、需要返回的特征的值。
程序清单3-2 按照给定特征划分数据集
1 | def Split_Data(dataset, axis, value): |
执行:
1 | >import trees |
Python语言不用考虑内存分配问题。Python语言在函数中传递的是列表的引用,在函 数内部对列表对象的修改,将会影响该列表对象的整个生存周期。为了消除这个不良影响,我们需要在函数的开始声明一个新列表对象。
程序清单3-3 选择最好的数据集划分方式
1 | def Split_by_entropy(dataset): |
执行:
1 | >import trees |
3.1.3 递归构建决策树
- 工作原理:得到原始数据集,然后基于最好的属性值划分数据集(由于特征值可能多余两个,因此可能存在大于两个分支的数据集划分)。第一次划分之后,数据被向下传递到树分支的下一个节点,在这个节点上,再次划分数据。递归进行。
递归结束的条件:程序遍历完所有划分数据集的属性,或者每个分支下的所有实例都具有相同的分类。如果所有实例具有相同的分类,则得到一个叶子节点或者终止块。
如果数据集已经处理了所有属性,但是类标签依然不是唯一的,此时我们需要决定如何定义该叶子节点,在这种情况下,我们通常会采用==多数表决==的方法决定该叶子节点的分类。
多数表决法:
1 | def Majority_vote(classList): |
程序清单3-4 创建树的函数代码
1 | def Create_Tree(dataset, labels): |
执行:
1 | >import trees |
3.2 在 Python 中使用 Matplotlib 注解绘制树形图
Matplotlib提供了一个注解工具==annotations==,非常有用,它可以在数据图形上添加文本注释。
程序清单3-5 使用文本注解绘制树节点
我们要知道:
1)有多少个叶节点,以便确定x轴的长度;
2)树有多少层,以便确定y轴的高度。
1 | #定义文本框和箭头格式 |
程序清单3-6 获取叶节点的数目和树的层数
1 | def Num_of_leaf(myTree): |
程序清单3-7 plotTree函数
1 | def plotmidtext(cntrpt, parentpt, txtstring): |
执行:
1 | >import trees |
为啥没有根节点呢??
3.3 测试和存储分类器
使用决策树构建分类器,以及实际应用中如何存储分类器。