决策树简介(《机器学习实战》笔记)


决策树是一种机器学习算法,它可以实现分类和回归任务,甚至是多输出任务。它也是随机森林的重要组成部分,而随机森林则是现今最为强大的机器学习算法之一,因此了解决策树的原理是非常重要的。
说明为了说明方便,本篇博客插入了许多图片,部分图片由《机器学习实战》的作者通过jupyter notebook绘制,上传于GitHub供大家学习。

决策树分类

决策树训练和可视化

为了更加直观的了解决策树的工作原理,我们可以对决策树的训练结果进行可视化。首先我们可以使用决策树来制作一个鸢尾花分类器:

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

iris = load_iris()
X = iris.data[:,2:] #读取花瓣的长和宽
y = iris.target

tree_clf = DecisionTreeClassifier(max_depth=2)  #深度为2
tree_clf.fit(X,y)

训练好了决策树之后,我们可以使用export_graphviz()方法输出一个图形定义文件来查看训练好的决策树的结构:

from sklearn.tree import export_graphviz

export_graphviz(
    tree_clf,  #训练好的决策树
    out_file="iris_tree.dot",  #输出的文件路径
    feature_names=iris.feature_names[2:],  #提取特征的名字
    class_names=iris.target_names,  #提取标签的名字
    rounded=True,  #让决策树的框图圆润
    filled=True
)

对于输出的dot文件我们需要下载graphviz来打开,并将其输出为png等常见的文件格式。下载地址(下载msi)。下载安装完成之后,在目录中的bin文件夹中打开gvedit.exe,使用其打开dot文件,即可查看图片,点击setting按钮对其进行输出。
可视化结果如下:
决策树可视化

分类过程

预测过程根据上面的图可以清楚的看出来,当有一个示例输入时,先判断花瓣长度是否小于等于2.45cm,若是则进入左边的结点(深度1),属于setosa鸢尾花,若不是则进入右边的结点继续进行判断:花瓣的宽度是否小于等于1.75cm,若是则属于versicolor否则属于virginica。
每个结点中的samples表示它使用的训练实例的数量,value则表示该节点中训练集中每个类别中的数目,而gini则代表基尼不纯度,用来表示不纯度,如果应用的所有训练实例都属于一个类别,则gini=0,结点是“纯”的。基尼不纯度的计算公式为:
G i = 1 − ∑ k = 1 n p i , k 2 G_i=1-\sum^n_{k=1}p_{i,k}^2 Gi=1k=1npi,k2

其中 p i , k p_{i,k} pi,k是第i个节点上,类别为k的训练实例占比。
还有一种计算不纯度的方式,成为信息熵,其计算公式为:
H i = − ∑ k = 1   p i , k ≠ 0 n p i , k l o g ( p i , k ) H_i=-\sum_{k=1\ p_{i,k}\neq0}^np_{i,k}log(p_{i,k}) Hi=k=1 pi,k=0npi,klog(pi,k)
其中 p i , k p_{i,k} pi,k如之前的定义。可以将超参数criterion设置为"entropy"来选择信息熵作为不纯度的测量方式,两者无非常明显的区别。基尼不纯度的计算速度略快,所以作为默认选择。根据书中提到的:基尼不纯度倾向于从树枝中分裂出最常见的类别,而信息熵则倾向于生产更平衡的树。
对于sklearn,其训练决策树时使用的是CART算法,该算法仅生成二叉树。
下面这张图就是决策树的决策边界。加粗直线表示根节点(深度0)的决策边界:x=2.45cm这条线。由于左侧区域是纯的,所以不可再分,对于右侧,则在y=1.75cm处再次分裂(虚线),此时达到了最大深度2,因此不再分裂。如果最大深度设置为3,则会再次产生一条分界线(点线)。
决策边界

估计类别的概率

估算类别的方法很简单,还是回到最开始的决策树,比如说现在有一个实例,根据决策树的训练结果,走到了右下角(紫色),那么他就有 1 1 + 45 = 2.17 % \frac{1}{1+45}=2.17\% 1+451=2.17%的概率属于versicolor,有 45 1 + 45 = 97.83 % \frac{45}{1+45}=97.83\% 1+4545=97.83%的概率属于virginica。
决策树

CART训练算法

CART算法首先根据单个特征k和阈值来分裂,特征k和阈值的选取由CART分类的成本函数决定,CART分类的成本函数为:
J ( k , t k ) = m l e f t m G l e f t + m r i g h t m G r i g h t 其 中 { G l e f t / r i g h t 衡 量 左 / 右 子 集 的 不 纯 度 m l e f t / r i g h t 是 左 / 右 子 集 的 实 例 数 量 J(k,t_k)=\frac{m_{left}}{m}G_{left}+\frac{m_{right}}{m}G_right\newline其中\begin{cases}G_{left/right}衡量左/右子集的不纯度\\m_{left/right}是左/右子集的实例数量\end{cases} J(k,tk)=mmleftGleft+mmrightGright{Gleft/right/mleft/right/
将训练集一分为二之后,继续使用相同的方式对每个子集中的实例进行分类,直到达到最大深度或者不纯度为0或者再也不能找到能够降低不纯度的分裂(当然也可以使用一些超参数进行正则化)。

正则化超参数

决策树非常容易过拟合,因为在不进行正则化的条件下,很可能会生成许多参数导致过拟合。为避免过拟合,需要设置一些超参数进行正则化,常见的超参数如下:

  • max_depth:默认值为None,即无限深度,所以如果不设定的话则必然会出现过拟合的现象。
  • max_featrue:分裂结点时进行评估的特征的最大数量
  • max_leaf_nodes:最大叶结点数量
  • min_samples_leafs:叶子结点必须拥有的最小样本数量
  • min_weight_fraction_leaf:叶子结点中每一类实例最低的加权实例总数占比

我们可以增大min_*或者减小max_*超参数的值来对模型进行正则化。
下面是书中给出的没有进行约束和进行约束后决策树的分类情况(数据集由make_moom生成):
正则化前后

回归

决策树也可以执行回归任务,就像之前说的,为了了解其工作原理我们可以使用可视化技术。首先我们需要对模型进行训练,训练集是带有噪声的二次数据集,我们设置最大深度为2:

import numpy as np
from sklearn.tree import DecisionTreeRegressor

# 创建数据集
np.random.seed(42)
m = 200
X = np.random.rand(m, 1)
y = 4 * (X - 0.5) ** 2
y = y + np.random.randn(m, 1) / 10

# 训练
tree_reg = DecisionTreeRegressor(max_depth=2, random_state=42)
tree_reg.fit(X, y)

# 可视化
export_graphviz(
        tree_reg1,
        out_file="regression_tree.dot",
        feature_names=["x1"],
        rounded=True,
        filled=True
    )

可视化结果如下:
回归决策树
其原理与决策树分类非常类似,通过计算成本函数将数据分段(分块),计算每一段中数据的平均值作为预测结果。上图中value为预测结果,mse则为方差。其成本函数为:
J ( k , t k ) = m l e f t m M S E l e f t + m r i g h t m M S E r i g h t J(k,t_k)=\frac{m_{left}}{m}MSE_{left}+\frac{m_{right}}{m}MSE_{right} J(k,tk)=mmleftMSEleft+mmrightMSEright

其 中 { M S E n o d e = ∑ i ∈ n o d e ( y ^ n o d e − y ( i ) ) 2 y ^ n o d e = 1 m n o d e ∑ i ∈ n o d e y ( i ) 其中\begin{cases}MSE_{node}=\sum_{i\in node}(\hat y_{node}-y^{(i)})^2\\ \hat y_{node}=\frac{1}{m_{node}}\sum_{i \in node}y^{(i)} \end{cases} {MSEnode=inode(y^nodey(i))2y^node=mnode1inodey(i)
根据上面的成本函数,即可完成分块,之后取每一个块中数据的平均值作为预测结果。下面是不同深度的决策树的回归表现:
不同深度的决策树的回归结果
当然我们可以使用min_samples_leaf来进行正则化,下面左边这张图是没用任何约束的条件下训练模型得到的结果,可以看出其发生了过拟合,而右图则是将min_samples_leaf设置为10后的结果,看起来预测结果更加的靠谱:
正则化

不稳定性

决策树对训练集的微小变化非常敏感。决策树的所有边界都是垂直或者水平的,这就是决策树的局限性,比如下面这张图显示的是一个线性可分的数据集,在旋转之前决策树可以轻松的分裂来对其进行分裂,但是当数据集旋转了45°之后,边界就产生了不必要的卷曲,这可能会使得其在实际工作中表现较差。
对旋转数据敏感
再比如说,如果移除之前鸢尾花数据集中花瓣最长的Versicolor鸢尾花,则决策边界将会发生巨大的变化:
变化的决策边界

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值