写在前头

经典机器学习十大算法,怎么能少得了决策树呢? 没错! 决策树是非常经典的分类和回归算法,包括后面集成的梯度提升算法,XGBoost,GBDT等,都是基于决策树基础上构建出来的。因此,入门机器学习,深度学习,人工智能,一定要首先深刻理解决策树。下面这篇文章,通俗易懂地解释了决策树。

01 这真的好吗?

一个在训练数据集上可以取得100%的准确率的分类器,一定很好吗?未必好,因为它在测试集上的测试结果未必好,又因为分类器的好坏最重要的是要看在测试集上的表现效果。

那么问题来了,为什么它在测试集上的效果就不好呢? 试想这样一种极端情况,我们手上有100个水果,其中包括三类:香蕉,苹果,杏,它们常用的区分特征比如:形状,大小,外观等,假如我们启用了一个非常特殊的特征,恰好把这100个水果样本对应到了100个叶子节点,也就是说每个叶子都还有唯一的一个样本,这在训练集上的准确率一定是100%呀,但是在测试集上呢,第101个水果在这个极其特殊的特征上,都有可能不在原100个特征取值内,所以你根本找不到它的对应,所以它不属于这100个叶子中之一。

当然,这个极端的例子虽然未必能在实际训练测试中遇到,但是它却很好的解释了选择合适的特征,并且避免叶子节点过多,同时防止过多的叶子节点包含的样本数过少的现象,才是决策树在测试集上表现良好的重要考量。

同时,还有一个因素也得考量,昨天推送分析过,决策树本质上是 if-else的多层嵌套,每个递归构建的新的分裂点(节点)都会不断地降低不纯度(熵),最终在叶子节点上,不纯度降为0,但是,一个叶子节点的深度如果很大,说明经过的 if 就非常多,这样就需要苛刻的条件才能满足这个很深的叶子节点(即这个类别),言外之意,它缺少必要的泛化能力,测试集的数据有可能不会走到这里。

经典机器学习算法:决策树,通俗易懂地教程「入门推荐」

为了解决以上通过训练构建出的决策树的深度过大,叶子节点过多,叶子节点含有的样本数过少的问题(实际上就是一棵树多余的树枝),就需要想办法剪去这些树枝,从而得到一棵不高不胖的决策树。

02 怎么剪枝

上面谈到了决策树剪枝的必要性,通过剪枝提高,测试集上的数据在构建好的决策树上找到自己对应所属的叶子节点,即找到自己的对应分类。

应该怎么做剪枝呢? 一种思路是在众多特征中贪心地选择最佳的信息增益率的那个特征作为根节点,依次递归地进行这种操作,在进行到某步操作时,发现树的深度大于指定的深度了,此时这一枝递归返回;

或者发现此时已形成的叶子节点已经达到指定的最多叶子节点数,也递归返回;

或者发现某个分裂点(节点)的样本数已经小于了指定的节点含有的最少样本数时,也递归返回。

以上就是常用的在构建决策树时的同时,进行剪枝操作,因为是同时做,时间复杂度小,这种做法称为:预剪枝。

还有,等决策树建立好了,我再修修补补一下,怎么修补?看看那些叶子节点的父节点,好,如果我这个父节点不分裂,是不是泛化误差会更小些呢,如果是这样,我就没有必要分裂了吧。

那么这种情况下,该父节点是否分裂有没有量化的公式呢:

经典机器学习算法:决策树,通俗易懂地教程「入门推荐」

其中 Tleaf 表示叶子节点的数目;

C(Node)表示某个节点的基尼系数乘以样本数。

这样比较下分裂Or不分裂谁的C值小,就选择谁,这种方法就是后剪枝,显然这种算法是在决策树构建完后,再花时间去剪枝,时间上肯定没有一边建立树,一边剪枝的效率高。

03 可视化决策树

下面我们在sklearn中,可视化决策树,同时关键是要理解以上几种剪枝策略。

我们直接用sklearn提供的一个数据集首先生成一棵不带剪枝策略的树,代码如下:

#导入iris数据集

from sklearn.datasets import load_iris

from sklearn import tree

iris = load_iris()

#创建决策树分类器

clf = tree.DecisionTreeClassifier()

#训练

clf = clf.fit(iris.data, iris.target)

#graphviz 可视化树

import graphviz

dot_data = tree.export_graphviz(clf, out_file=None,

feature_names=iris.feature_names,

class_names=iris.target_names,

filled=True, rounded=True,

special_characters=True)

graph = graphviz.Source(dot_data)

生成的决策树如下所示,每个节点包括的数据结构如下:

分类的不等式基尼系数样本个数每个类别的样本数list这个节点的类别经典机器学习算法:决策树,通俗易懂地教程「入门推荐」

我们看到这棵树,树的深度,叶子节点数都很大,每个叶子节点含有的样本数有的只有1个样本,明显需要剪枝,下面看下剪枝参数如何设置。

04 剪枝决策树

clf = tree.DecisionTreeClassifier()这个构建决策树的构造函数,带有参数常用的包括如下:

criterion='gini', 选用基尼系数作为选择特征的分裂点max_depth=None, 树的最大深度min_samples_split=2, 分裂点的样本个数min_samples_leaf =1, 叶子节点的样本个数max_leaf_nodes=None,最大的叶子节点数

可以看到这个构造函数的参数,都包括了以上阐述的预剪枝的策略,sklearn强大。

如果参数的max_depth = 4,那么得到的决策树如下所示:

经典机器学习算法:决策树,通俗易懂地教程「入门推荐」

05 总结

以上我们分析了为什么需要对决策树剪枝,以及常见的剪枝策略都有哪些,以及在sklearn中如何可视化决策树,以及如何利用超参数剪枝决策树。

相关文章