欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

决策树Decision Tree

程序员文章站 2022-05-02 16:35:14
...

本文的内容参考了机器学习实战:基于Scikit-Learn和Tensorflow一书。

决策树可以实现分类和回归任务,甚至是多输出任务。能够拟合复杂的数据集。

决策树训练和可视化

在鸢尾花数据集上训练一个DecisionTreeClassifier:

from sklearn.datasets import load_iris
from sklearn.tree import DecisionTreeClassifier

iris = load_iris()
X = iris.data[:, 2:]  # petal length and width
y = iris.target

tree_clf = DecisionTreeClassifier(max_depth=2)
tree_clf.fit(X, y)

# 可视化

from sklearn.tree import export_graphviz

export_graphviz(
    tree_clf,
    out_file='iris_tree.dot',
    feature_names=iris.feature_names[2:],
    rounded=True,
    filled=True
)

import graphviz

with open('iris_tree.dot') as f:
    dot_graph = f.read()
dot = graphviz.Source(dot_graph)
dot.view()     # 以pdf形式查看

决策树Decision Tree决策树的特质之一是需要做的数据准备工作非常少。完全不需要进行缩放或集中。
节点的gini属性衡 量其不纯度(impurity):如果应用的所有训练实例都属于同一个类 别,那么节点就是“纯”的(gini=0)
深度2左侧节点,基 尼系数等于1–(0/54)^2^–(49/54)^2^–(5/54)^2^≈0.168

  1. 基尼不纯度:
    Gi=1k=1npi,k2{{\rm{G}}_i} = 1 - \sum\limits_{k = 1}^n {{p_{i,k}}^2}
    pi,k是第i个节点上,类别为k的训练实例占比。

  2. 信息熵
    将超参数 criterion设置为"entropy"来选择信息熵作为不纯度的测量方式。
    Hi=k=1,pi,k0npi,klog(pi,k){H_i} = - \sum\limits_{k = 1,{p_{i,k}} \ne 0}^n {{p_{i,k}}\log (} {p_{i,k}})
    基尼不纯度的 计算速度略微快一些,基尼不纯度倾向于从树枝中分裂出最常见的类别,而信息熵则倾 向于生产更平衡的树。

  3. CART算法:Classification And Regression Tree
    算法描述:其中T代表当前样本集,当前候选属性集T_attributelist表示。 (1)创建根节点N (2)为N分配类别 (3)if T都属于同一类别or T中只剩下 一个样本则返回N为叶节点,否则为其分配属性 (4)for each T_attributelist中属性执行该属性上的一个划分,计算此划分的GINI系数 (5)N的测试属性test_attribute=T_attributelist中最小GINI系数的属性 (6)划分T得到T1 T2子集 (7)对于T1重复(1)-(6) (8)对于T2重复(1)-(6)
    CART分类成本函数:
    J(k,tk)=mleftmGleft+mrightmGrightJ{\rm({k}},{t_k}) = {{{m_{left}}} \over m}{G_{left}} + {{{m_{right}}} \over m}{G_{{\rm{right}}}}
    Gleft/right衡量左右子集的不纯度,mleft/right是左右子集的实例数量。
    CART算法考虑到每个节点都有成为叶子节点的可能,对每个节点都分配类别。分配类别的方法可以用当前节点中出现最多的类别,也可以参考当前节点的分类错误或者其他更复杂的方法。CART算法仍然使用后剪枝。在树的生成过程中,多展开一层就会有多一些的信息被发现,CART算法运行到不能再长出分支为止,从而得到一棵最大的决策树。然后对这棵大树进行剪枝。
    Scikit-Learn使用的是CART算法,该算法仅生成二叉树:非 叶节点永远只有两个子节点(即问题答案仅有是或否)。但是,其他 算法,比如ID3生成的决策树,其节点可以拥有两个以上的子节点。
    CART是一种贪婪算法:从顶层开始搜索最优分 裂,然后每层重复这个过程。几层分裂之后,它并不会检视这个分裂 的不纯度是否为可能的最低值。贪婪算法通常会产生一个相当不错的 解,但是不能保证是最优解

  4. 决策边界
    决策树Decision Tree决策树是非常直观的,它们的决策也很容易解释,这 类模型通常被称为白盒模型。与之相反的,随机 森林或是神经网络被认为是一种黑盒模型

估算类别概率

max_depth=2时,

print(tree_clf.predict_proba([[5,1.5]]))
print(tree_clf.predict([[5,1.5]]))
#[[0.         0.90740741 0.09259259]]
#[1]

计算复杂度

预测时,遍历决策树需要经历大约O(log2(m))个节点,每个节点需要检测一个特征值。总体预测复杂度为:O(log2(m))。
训练时,算法需要在所有样本上比较所有特征,复杂度为O(n×mlog2(m))。对于小型训练集(几千个实例以内),ScikitLearn可以通过对数据预处理(设置presort=True)来加快训练,但是 对于较大训练集而言,可能会减慢训练的速度。

正则化超参数

为避免过度拟合,需要在训练过程中降低决策树的*度。正则化超参数的选择取决于你 所使用的模型,但是通常来说,至少可以限制决策树的最大深度。
DecisionTreeClassifier类还有一些其他的参数,同样可以限制决 策树的形状:min_samples_split(分裂前节点必须有的最小样本 数),min_samples_leaf(叶节点必须有的最小样本数量), min_weight_fraction_leaf(跟min_samples_leaf一样,但表现为加权实 例总数的占比),max_leaf_nodes(最大叶节点数量),以及 max_features(分裂每个节点评估的最大特征数量)。增大超参数 min_*或是减小max_*将使模型正则化。
还可以先不加约束地训练模型,然后再对不必要的节点进行 剪枝(删除)。如果一个节点的子节点全部为叶节点,则该节点可被 认为不必要,除非它所表示的纯度提升有重要的统计意义。标准统计 测试,比如χ2测试,是用来估算“提升纯粹是出于偶然”(被称为虚假 设)的概率。如果这个概率(称之为p值)高于一个给定阈值(通常 是5%,由超参数控制),那么这个节点可被认为不必要,其子节点 可被删除。直到所有不必要的节点都被删除,剪枝过程结束。
如以下对卫星数据集的决策树,左图模型过拟合,右图泛化效果更好。
决策树Decision Tree###回归

from sklearn.tree import DecisionTreeClassifier,DecisionTreeRegressor
tree_reg=DecisionTreeRegressor(max_depth=2)
tree_reg.fit(X,y)

决策树Decision Tree与分类相比,每个 节点上不再是预测一个类别而是预测一个值。每个区域的预测值永远等于该区域内 实例的目标平均值(标签值平均)。
CART回归成本函数:
J(k,tk)=mleftmMSEleft+mrightmMSErightJ({\rm{k}},{t_k}) = {{{m_{left}}} \over m}MS{E_{left}} + {{{m_{right}}} \over m}MS{E_{{\rm{right}}}}
其中
MSEnode=inode(yΛnodey(i))2,yΛ=1mnodeinodey(i)MS{E_{{\rm{node}}}} = \sum\limits_{i \in node} {({{\mathop y\limits^\Lambda }_{node}}} - {y^{(i)}}{)^2},\mathop y\limits^\Lambda = {1 \over {{m_{node}}}}\sum\limits_{i \in node} {{y^{(i)}}}
决策树Decision Tree在处理回归任务时也需要考虑正则化的问题:
决策树Decision Tree### 不稳定性
决策树正交的决策边界 (所有的分裂都与轴线垂直),这导致它们对训练集的旋转非常敏 感。
决策树Decision Tree决策树的主要问题是它们对训练数据中的小变化非 常敏感。如果你从鸢尾花数据集中移除花瓣最宽的Versicolor 鸢尾花(花瓣长4.8厘米,宽1.8厘米),然后重新训练一个决策树,可能会得到下图所示结果。
决策树Decision Tree