机器学习:原理及实现

决策树原理及实现(Decision Tree)

2019-05-26  本文已影响0人  d518a9b6ae51

项目地址:https://github.com/Daya-Jin/ML_for_learner
原博客:https://daya-jin.github.io/tag/#tree

模型概述

决策树算法最早用于分类任务,算法根据数据的特征与类别生成一棵树,并以这棵树对未知数据进行分类。

首先要了解熵(Entropy)的概念。在热力学中,熵被用于表示系统的混乱程度;而在信息论中,熵用于表示信息量的大小。

在一个有K个类别的样本D中,假设类别Y的概率分布为:

P(Y=k)=p_{k}

那么这个具有K个类别的样本的信息熵为:

H(D)=-\sum_{k=1}^{K}p_{k}\log{p_{k}}

当整个数据集只有一个类别时,熵最低,为

H_{min}(D)=-1\cdot{log1}=0

当数据集各类别为均匀分布时,熵最大,为

H_{max}(D)=-K\cdot\frac{1}{K}\cdot\log\frac{1}{K}=-\log{K}

假设某一离散属性AV个不同的的取值,那么当以特征A来划分时可以将数据集D分为V个子集:

D=\sum_{v}^{V}D_{v}

那么划分之后的V个子数据集的加权熵为:

H(D|A)=\sum_{v}^{V}\frac{|D_{v}|}{|D|}H(D_{v})

ID3

Iternative Dichotomizer,是最早的决策树算法,其根据信息增益(Information Gain)来寻找最佳决策特征,当按特征A来划分数据集时的信息增益定义为:

G(D,A)=H(D)-H(D|A)

首先,树的根节点中包含整个数据集,ID3算法会遍历所有特征分别做test来计算划分后的信息增益,然后选择信息增益最大的那个test,按该特征的类别数将数据集划分到下一层的各个子节点中;对各个子节点中的数据递归进行这个过程,直到信息增益足够小或者无特征可用。

可以看出,ID3算法有如下特点:

在只考虑信息增益的情况下,ID3算法有一个致命缺陷,就是会倾向于选择类别数多的特征来做划分。假设有一列特征(如样本ID)类别数与样本数相等,如果以该特征来进行划分数据集,则数据集被划分成了单样本节点,每个节点的熵均为0,总熵也为0,这样一来得到了最大的信息增益,但是这种划分显然是不合理的。

实现指导:分类回归

完整代码:分类回归

C4.5

为了修正ID3算法的缺陷,C4.5算法应运而生。

首先,C4.5在ID3的基础上改进了生成树算法,不再使用信息增益,而是使用增益比(gain ratio)来决定使用哪个特征来划分数据集。

增益比定义为:

GR(D,A)=\frac{G(D,A)}{IV(A)}

其中IV(A)被称为固有值(intrinsic value),它等价于某一特征在数据集中的熵。

假设在一个数据集D中有某个特征A,其有K个不同的取值,那么特征A在数据集中的概率分布为:

P(A=v)=\frac{|D_{v}|}{|D|}=p_{v}

那么数据集中该特征的固有值(熵)为:

IV(A)=-\sum_{v=1}^{V}p_{v}\log{p_{v}}

这样一来就减少了信息增益在做决策时的比重。

此外,C4.5算法还加入了对连续值的处理。对于一个连续特征A,假设其在样本中有n个不同的取值,其有序集合为\{a_{1},a_{2},…,a_{n}\},那么对应的就有n-1处划分点,取相邻两值的中点做划分点,那么划分点集合可表示为:s_{i}=\{\frac{a_{i}+a_{i+1}}{2}\|i=1,2,...,n-1\}。当选取某一划分点进行划分时,数据集D被分成两部分:D^{-}中所有样本的A特征都要小于等于s_{i}D^{+}中所有样本的A特征都要大于s_{i}。然后再以之前的公式计算划分之后的信息增益与增益比。

然后是C4.5对缺失值的处理,决策树算法在处理缺失值熵需要解决三个问题:熵的计算,数据集的划分,带缺失值的预测。

第一条,在做test时,当前特征为缺失值的样本不参与熵的计算;

第二条,在做test时,给当前特征缺失的样本赋一个初始值为1的权重,做划分时,这些特征缺失的样本会被复制多份分配到所有子节点中,并按照叶子节点中非缺失样本的比例更新权重。设某个子结点中的非缺失样本占父节点非缺失样本比例为r ,则更新该结点中每个缺失值样本的权重为w:=w\cdot{r}

第三条,在预测带缺失值的样本时,样本在决策树中的行走路线同上,最后该样本会同时出现在多个叶子节点中,按在各叶子节点中的权重和来给出预测类别。

最后,C4.5使用自底向上的剪枝策略来避免过拟合。

Classification And Regression Tree

CART是一棵二叉树,每次test都将问题空间分成两个区域,可处理连续变量与类别型变量,所以one-hot encoding对CART是无效的。

分类

CART分类树的生成类似上面两种算法,不过做test时选取特征的依据是基尼指数(Gini Index)。对于有K个类别的数据集D,某一样本属于类别k的概率等于该类别的分布概率:

P(Y=k)=p_{k}

那么该数据集D的基尼指数定义如下:

Gini(D)=1-\sum_{k=1}^{K}p_{k}^{2}

从公式易得,基尼指数表示的是从数据集中随机取两个不同类别样本的概率,其值越小则数据集纯度越高。

由于CART的特殊性,其在做test时与ID3、C4.5略有不同,CART是二叉树,并且在对类别型变量做划分时做得是非划分。如对一个数据集D以特征A的一个取值a来划分,那么数据集会被划分成D_{A=a}D_{A\ne{a}},那么数据集D依照特征A=a划分之后的加权基尼指数为:

G(D|A=a)=\frac{|D^{A=a}|}{|D|}Gini(D^{A=a})+\frac{|D^{A{\ne}a}|}{|D|}Gini(D^{A{\ne}a})

CART在划分时会遍历所有的特征与其所有可能的取值,再全局考量选取一个最佳特征与最佳划分点。若数据集有M个特征,每个特征有V种不同取值,上述过程可以用下式来表述:

(A_{opt},a_{opt})=arg\ min(G(D|A_{i}=a_{j})) \qquad i\ from\ 1 \to M,j\ from\ 1\to V

实现指导

完整代码

回归

首先需要说明的是回归树的输出是叶子结点中所有样本目标值的均值。那么对于回归任务,怎么去生成树?可以采用一种直观的方式来对数据集进行划分,假设某一时刻数据集(数据子集)D被决策树以特征X_{j}按取值s划分成了两部分(或两个叶子节点):

R_{1}(X_{j},s)=\{X|X_{j}<s\} \\ R_{2}(X_{j},s)=\{X|X_{j}\ge s\} \\

则此次划分的优劣可用MSE来判断:

Loss(X_{j},s)=\sum_{R_{1}}(y_{i}-\bar{y}_{R_{1}})^{2}+\sum_{R_{2}}(y_{i}-\bar{y}_{R_{2}})^{2}

其中,\hat{y}_{R_{1}}R_{1}区域所有样本目标值的均值,\hat{y}_{R_{2}}R_{2}区域所有样本目标值的均值。

在生成回归树时,使用贪心策略,遍历所有特征下所有可能的取值,找到一个最优划分点,然后以此类推。决策树在做预测时,首先将测试样本丢进决策树进行判定,判定该测试样本属于哪一个叶子节点,然后把该叶子结点内所有训练样本的目标均值作为测试样本的预测值。

除了使用MSE作为分裂依据(splitting criteria)之外,还有一个变量可以用作回归树的分裂:方差(variance)。当使用方差作为分裂依据时,生成树的目的很明显,希望子节点内的值越稳定越好。

CART同样使用剪枝来避免过拟合。

注意:能做回归任务并不是CART树的专利,ID3与C4.5都可以用于回归!

实现指导

完整代码

树的正则化

决策树算法的缺点就在于极易过拟合,所以控制决策树的模型复杂度以防止过拟合是很有必要的。首先可以设定几个参数抑制树的生长:最大树深(max_depth),最大叶子结点数(max_leaf_nodes),叶子结点最小样本数(min_samples_leaf),分裂最小增益(min_impurity_decrease)。除此之外,也可以对树的生长不做限制,然后再对树进行剪枝(pruning)。

Pessimistic Estimate Pruning

C4.5使用悲观估计剪枝法(待补充)。

Cost-Complexity Pruning

CART使用cost-complexity剪枝方法。类似线性模型中的正则化,可以加入一项结构风险项来指导剪枝过程,定义一个Cost-Complexity函数:

C_{\alpha}(T)=Err(T)+{\alpha}L(T)

其中T表示一棵树,Err(T)表示树T的分类(回归)误差,\alpha为正则化系数,L(T)为能表示树结构复杂度的函数。下面以分类任务做示例。

令树T的结构复杂度函数等于树的叶节点数:

L(T)=|T|

再令树T的误差函数为:

Err(T)=\sum_{i=1}^{|T|}err(t_{i})p(t_{i})

其中t_{i}为树T中的第i个叶节点,err(t_{i})为该叶节点的分类误差率,p(t_{i})为该叶节点的样本比例,上式实质上是一个加权误差率。对一个确定的\alpha值,一定会有一颗最小化C_{\alpha}的树T_{\alpha}。为了找到这颗最优剪枝树T_{\alpha},使用最弱链接剪枝(weakest link pruning)策略,自底向上地对非叶节点进行剪枝并查看效果,然后选取一个表现最好的T_{\alpha}

假设某一时刻以节点t进行剪枝,那么剪枝后与剪枝前的CC函数差为:

\begin{aligned} \Delta C_{\alpha}(t)&=C_{\alpha}(T-T_{t})-C_{\alpha}(T) \\ &=Err(T-T_{t})-Err(T)+\alpha(|T-T_{t}|-|T|) \\ &=(-Err(T_{t})+err(t))+\alpha(-|T_{t}|+1) \\ &=err(t)-Err(T_{t})+\alpha(1-|T_{t}|) \\ \end{aligned}

其中,T_{t}为树T中以节点t为根节点的子树。令\Delta C_{\alpha}(t)=0g(t)=\alpha'=\frac{err(t)-Err(T_{t})}{|T_{t}-1|},整个CCP算法流程如下所述:

  1. 生成一颗完整树T^{0},对所有的非叶节点都进行剪枝尝试,找到一个最小化g(t_{1})的剪枝节点t_{1},令\alpha^{1}=g(t_{1})T^{1}=T^{0}-T_{t_{1}}

  2. T^{1}所有的非节点都进行剪枝尝试,找到一个最小化g(t_{2})的剪枝节点t_{2},令\alpha^{2}=g(t_{2})T^{2}=T^{1}-T_{t_{2}}

  3. 依次进行下去,直到只剩下一个根节点为止,那么可以得到一个子树序列[T^{0},T^{1},...,root]和一系列参数[\alpha^{1},\alpha^{2},...],然后在所有子树上使用交叉验证来选取一个最佳参数\hat{\alpha}与最佳剪枝树T_{\hat{\alpha}}

总结

决策树算法的优缺点分别在于

优点:

缺点:

各决策树算法的对比:

| | ID3 | C4.5 | CART |
| :--------: |: ----: | :--: | :--: |
| splitting criterion | Information Gain | gain ratio | Gini Index |
| tree structure | multiway tree | multiway tree | binary tree |
| continuous attribute support | - | √ | √ |
| handling missing value | - | √ | √ |
| pruning | - | √ | √ |
| regression support | - | - | √ |

集成学习

讲决策树就不得不提集成学习。因为树模型中没有引入统计模型,导致树模型对的variance很大,虽然在训练集上表现很好,但是在测试集上的表现却差强人意,所以集成学习很适合应用到决策树算法上。

上一篇下一篇

猜你喜欢

热点阅读