=======================================================================
时间:2019-05-12
阅读:《机器学习实战》后作出改动
=======================================================================
PS:
Scikit-Learn使用的是CART算法,该算法仅生成二叉树:非叶节点永远只有两个子节点(即问题答案仅有是或否)。但是,其他算法,比如ID3生成的决策树,其节点可以拥有两个以上的子节点。
决策树是广泛用于分类和回归任务的模型(也能胜任多输出任务),功能强大,能够拟合复杂的数据集。本质上,它从一层层的if/else问题中进行学习,并得出结论。
学习决策树,就是学习一系列if/else问题,是我们能够以最快的速度得到正确答案。在机器学习中,这些问题叫做测试(不要与测试集混淆,测试集是用来测试模型泛化性能的数据)。
为了构造决策树,算法搜遍所有可能的测试,找出对目标变量来说信息量最大的那一个。
根结点表示整个数据集
通过测试条件的真假对数据集进行划分。
在区域中重复寻找最佳测试的过程,从而构建出更准确的模型。这一递归过程生成一棵二叉决策树,其中每个节点都包含一个测试。
对数据反复进行递归划分,知道划分后的每个区域(决策树的每个叶子结点)只包含单一目标值(单一类别或单一回归值)。如果树种某个叶结点所包含数据点的目标值都相同,那么这个叶结点就是纯的(pure)。
想要对新数据进行预测,首先要查看这个点位于特征空间划分的哪个区域,然后将该区域的多数目标值(如果是纯的叶结点,就是单一目标值)作为预测结果。从根节点开始对树进行遍历就可以找到这一区域,每一步是向左还是向右取决于是否满足相应的测试。
决策树也可以用于回归任务,使用的方法完全相同。预测的方法是,基于每个结点的测试对树进行遍历,最终找到新数据点所属的叶结点。这一数据点的输出即为此叶结点中所有训练点的平均目标值。
属性 | 含义 |
---|---|
samples | 统计该节点应用的训练实例数量 |
value | 该节点上每个类别的训练实例数量 |
gini(基尼系数) | 衡量节点的不纯度(impurity):如果应用的所有训练实例都属于同一个类别,那么节点就是“纯”的(gini=0) |
sklearn.tree.export_graphviz(
decision_tree,
out_file=None, #输出文件名
max_depth=None, #决策树的最大深度
feature_names=None, #特征名
class_names=None, #类名
label=’all’, #是否显示标签,默认显示所有
filled=False, #当设置为True时,绘制节点以指示用于分类的多数类、用于回归的值的极值或用于多输出的节点的纯度。
leaves_parallel=False, #当设置为True时,将所有叶子节点画在树的底部。
impurity=True, #当设置为True时,在每个结点中显示非纯结点
node_ids=False, #当设置为True时,在每个节点上显示ID号。
proportion=False, #当设置为True时,将“值”和/或“样本”的显示分别更改为比例和百分比。
rotate=False, #当设置为True时,从左到右对树进行定向,而不是自顶向下。
rounded=False, #当设置为True时,绘制带有圆角的节点框,并使用Helvetica字体而不是Times-Roman。
special_characters=False, #设置为False时,忽略特殊字符以获得PostScript兼容性
precision=3 #每个节点的非纯洁点值、阈值和属性值中浮点精度的位数
)
树的可视化有助于深入理解算法是如何进行预测的,也易于向非专家解释的机器学习算法的优秀示例。
调用scikit-learn中tree模块内的export_graphviz方法将决策树导出为.dot格式的文件。
from sklearn.tree import export_graphviz
export_graphviz(
tree_clf,
out_file=image_path("iris_tree.dot"),
feature_names=iris.feature_names[2:],
class_names=iris.target_names,
rounded=True,
filled=True
)
这样,在你的项目文件夹内应当就能够看到一个.dot格式的文件
使用graphivz来读取显示.dot文件
https://blog.csdn.net/az9996/article/details/86564357
可以使用graphviz包[1]中的dot命令行工具将这个.dot文件转换为其他格式,例如PDF或PNG。下面这行命令将.dot文件转换为.png图像文件:
$ dot -Tpng iris_tree.dot -o iris_tree.png
通常来说,构造决策树直到所有叶结点都是纯的叶结点,这会导致模型非常复杂,并且对训练数据高度过拟合。纯叶结点的存在说明这棵树在训练集上的精度是100%。训练集中的每个数据点都位于分类正确的叶结点中。此时的决策边界并不是人们想象中的决策边界的样子,这个决策边界过于关注远离同类别其它点的单个异常点。
防止过拟合有两种常见的策略:一种是及早停止树的生长,也叫预剪枝(pre-pruning);另一种是先构造树,但随后删除或折叠信息量很少的结点,也叫后剪枝(post-pruning)或剪枝(pruning)。预剪枝的限制条件可能包含限制树的最大深度、限制叶结点的最大数目,或者规定一个结点中数据点的最小数目来防止继续划分。
scikit-learn的决策树在DecisionTreeRegressor类和DecisionTreeClassifier类中实现。scikit-learn只实现了预剪枝,没有实现后剪枝。
如果我们不限制决策树的深度,它的深度和复杂度都可以变得特别大。因此,未剪枝的树容易过拟合,对新数据的泛化性能不佳。现在我们将预剪枝应用在决策树上,这可以在完美拟合训练数据之前阻止树的展开。一种选择是在达到一定深度后停止树的展开。同个设置max_depth的值,即可控制树的展开。限制树的深度可以减少过拟合。这回降低训练集的精度,但可以提高测试集的精度。
查看整个树可能非常费劲,除此之外,还可以用一些有用的属性来总结树的工作原理。其中,最长用的是特征重要性(feature importance),它为每个特征对树的决策的重要性进行排序。对于每个特征来说,它都是一个介于0和1之间的数字,其中0表示“根本没用到”,1表示“完美预测目标值”。特征重要性的求和始终为1。
如果某个特征的feature_importance_很小,并不能说明这个特征没有提供任何信息。这只能说明该特征没有被树选中,可能是因为另外一个特征也包含了同样的信息。
与线性模型的系数不同,特征重要性始终为正数,也不能说明该特征对应哪个类别。特征重要性告诉我们“worst radius”特征很重要,但并没有告诉我们半径大表示样本是良性还是恶性。事实上,在特征和类别之间可能没有这样简单的关系。
回归树的用法和分析与分类树非常相似。但在将基于树的模型用于回归时,我们想要指出它的一个特殊性质。DecisionTreeRegressor(以及其他所有基于树的回归模型)不能外推(extrapolate),也不能在训练数据范围之外进行预测。
一旦输入超出了模型训练数据的范围,模型就只能持续预测最后一个已知数据点。树不能在训练数据的范围之外生成“新的”响应。所有基于树的模型都有这个缺点。(实际上,利用基于树的模型可以做出非常好的预测(比如试图预测价格会上涨还是下跌)。这个例子的目的并不是要说明对时间序列来说树是一个不好的模型,而是为了说明树在预测方式上的特殊性质。)
控制决策树模型复杂度的参数是预剪枝参数,它在树完全展开之前停止树的构造。选择一种预剪枝策略(设置max_depth、max_leaf_nodes或min_samples_leaf)足以防止过拟合。
优点:
一是的到的模型很容易可视化,非专家也很容易理解(至少对于较小的树而言);
二是算法完全不受数据缩放的影响。由于每个特征被单独处理,而且数据的划分也不依赖于缩放,因此决策树算法不需要特征预处理,比如归一化或标准化。特别是特征的尺度完全不一样时或者二元特征和连续特征同时存在时,决策树效果很好。
缺点:
即使做了预剪枝,它也经常会过拟合,泛化性能很差。因此,在大多数应用中,往往使用决策树集成(DecisionTree ensemble)来代替单颗决策树。