三生万物:决策树

一、概述

不知怎么回事,提到决策树我就想起”道生一,一生二,二生三,三生万物“这句话,大概是因为决策树从一个根节点慢慢“长”成一棵树,也要经历“一生二,二生三”的过程。决策树本质上就是一种二叉树,根据特定的标准不停的分成左右两个子树,直到符合某种条件停止。树算法解释性强、简单直观以及接近人的决策方式使它成为流行的机器学习算法之一。当决策树与装袋法(Bag)、提升法(Boosting)结合之后,可以成为更强大的算法。

决策树按响应值的类型大致分为分类树和回归树,实现决策树的方法也很多,比如CART、ID3、C4.5等等,本文将对CART这种算法进行介绍。

二、算法

一棵树要长成要解决两方面的问题,一是如何分,二是何时停。这两点对于分类和回归略有区别,先说如何分,对于定量变量一般是将小于某个值的数据划分为左子树,大于等于某个值的划分为右子树;对于定性变量一般是将等于某个值的划分为左子树,不等于某个值的划分为右子树。那么什么才是一个好的划分呢?分类树大致分为两种,一种是按纯度(Purity),纯度是通过基尼系数(Gini Index)进行定义的,基尼系数越小,纯度越大,那么划分效果越好。基尼系数的计算方法如下式所示:

 

G=k=1Kp^k(1p^k)

p^k代表第k类所占比例,当p^k接近0或1时,基尼系数会很小。

另一种标准是互熵(Cross-entropy),互熵的定义如下:

 

D=k=1Kp^klogp^k

由定义可以看到,和基尼系数类似,当p^k接近0或1时,互熵也很小,划分的效果也越好。

回归树则根据残差平方和RSS:

 

RSS=1Ni=1N(yiy¯)2

y¯代表平均响应值,可以看到这实际上就是方差,我们都知道方差是衡量数据变异性的量,因此RSS越小表示回归模型效果越好。

注意上面的纯度、互熵以及残差平方和均是树的一个分枝上的值,总的值要对左右分枝进行加权平均,例如基尼系数的最终值应该这样计算,

 

Gtotal=NleftNGleft+NrightNGright

N表示总的样本数,NleftNright分别代表左分枝和右分枝的样本数,互熵和残差平方和的计算方式类似。

说了如何分,那什么时候停呢?一般的惯例是子树中的预测变量或响应值都一样了就可以停止分裂了。有时候这个条件可能有些苛刻,这时候可以设置一个Node Size值,表示叶子节点包含的最小的样本数。分裂过程中如果一个子树的样本数小于等于这个值就停止分裂,分类数取数目最多的那个类,回归树取响应的均值。

说了这么多,下面举个例子,来演示下决策树算法,比如这里有一份城市和农村儿童身高数据,注意这里的数据都是我杜撰的,只是为了演示决策树的算法。如果已知一个儿童身高和性别,如何判断所处的区域?

身高 性别 地区
100 城市
90 城市
90 农村
80 农村

下面尝试根据基尼系数来构造一个分类树,
第一次分裂:

身高

身高

身高

性别=男:2/4 x (1/2 x 1/2 + 1/2 x 1/2) + 2/4 x (1/2 x 1/2 + 1/2 x 1/2) = 1/2

性别=女:2/4 x (1/2 x 1/2 + 1/2 x 1/2) + 2/4 x (1/2 x 1/2 + 1/2 x 1/2) = 1/2

可以看到前面两个都是1/3,选择哪一个都行,这里我选择第一个最小值:“身高 左子树

身高 性别 地区
90 城市
90 农村
80 农村

右子树

身高 性别 地区
100 城市

第二次分裂:

由于右面的子树只有一条数据,因此只需计算左边子树的基尼系数,

身高

身高

性别=女:2/3 x (1/2 x 1/2 + 1/2 x 1/2) + 1/3 x (1 x 0) = 1/3

性别=男:1/3 x (1 x 0) + 2/3 x (1/2 x 1/2 + 1/2 x 1/2) = 1/3

同上选择第一个最低值“身高 左子树

身高 性别 地区
80 农村

右子树

身高 性别 地区
90 城市
90 农村

第三次分裂:

同理,左边子树只有一条数据,只需计算右子树

身高

性别=女:1/2 x (1 x 0) + 1/2 x (1 x 0) = 0

性别=男:1/2 x (1 x 0) + 1/2 x (1 x 0) = 0

选择“性别=女”这个条件,至此所有的子树的响应值都是唯一的,停止分裂。

最终这个分类树的样子大概如下,

这里写图片描述

三、树的剪枝

其实树的剪枝就是正则化,剪枝一般分为两种:一种称为预剪枝,通过设置Node Size的大小来达到控制树的分枝个数的目的,这种方式简单易用,但有短视的风险;另一种称为后剪枝,原理是让树充分“生长”,然后尝试合并树的分枝,通过对比合并前后错误率是否降低来决定是否真得合并,这种方式效果较前一种好,但是实现稍微复杂一些。

四、说了就练

俗话说,光说不练假把式,下面我用R语言实现一个决策树,并尝试分析两个实际的数据集。

1、鸢尾花(iris)数据集,这个数据集包括五个变量:花萼长度(Sepal.Length),花萼宽度(Sepal.Width),花瓣长度(Petal.Length),花瓣宽度(Petal.Width),种类(Species),下面尝试使用花萼长度(Sepal.Length)和花萼宽度(Sepal.Width)这两个变量来预测鸢尾花的种类(Species)。

为了简便,我采用的是预剪枝的方式。那么选择多大的Node Size合适呢?关于这个问题通常的方法就是交叉验证(Cross-validation)。下图是采用10折交叉验证(k-fold cross-validation)得到的错误率,

这里写图片描述

可以看到,当Node Size为40的时候测试集的错误率Eout最低,从另一个方面也可以看到如果不进行剪枝,Eout约为0.4,比剪枝后的错误率高了将近0.2。从下面的第一张图也可以直观的看到当Node Size从小到大增加时,分类边界(Decision Boundary)从过拟合(Overfit)到欠拟合(Underfit)的变化趋势。第二张图是根据交叉验证得到的最佳分类边界,它和Node Size为30的分类边界非常相似。

这里写图片描述

这里写图片描述

最终的错误率约为0.2,从上面第二张图可以看到versicolor和virginica这两类的鸢尾花有些数据在二维空间完全重合在了一起,仅仅依靠花萼长度(Sepal.Length),花萼宽度(Sepal.Width)这两个变量是无法把它们分开的,这个时候单纯的增加样本数无法进一步提高模型的质量,这个时候最好去寻找新的变量,事实上,当加上花瓣长度(Petal.Length),花瓣宽度(Petal.Width)这两个变量时,预测的错误率可以降低到0.06左右。

树的样子如下,

这里写图片描述

[L]和[R]分别代表左右分枝。

2、上面是个分类问题,那么再看一个回归问题。北京二手房这个数据集有13个特征,下面使用决策树根据房子的区域(area)、是否学区(school)、是否有地铁(subway)、总价(num)这四个变量来预测房价(price)。

同样,祭出我们的法宝交叉验证得到一个合适的Node Size,如下所示,

这里写图片描述

对于回归,我采用了决策系数R2作为衡量模型效果的标准,由于R2是越大越好,且0

这里写图片描述

得到的决策系数R2约为0.7,也就是区域、是否学区、是否有地铁、总价这四个变量解释了70%房价变异。由这个相对误差图可以看出大部分的数据都落在了0附近,实际上有20275条数据落在[-0.2,0.2],28379条数据落在[-0.5,0.5]。那么,那些误差比较大的都是些什么数据呢?

感觉这些数据好像异常数据,北京还有低于1万的房价?!

五、总结

当一个小小的种子慢慢成长为一颗参天大树,独霸森林一方,常常让人感受生命的强大,而决策树算法同样让人惊叹,易于实现又足够灵活,既能用于分类又能用于回归,也在机器学习领域赢得了一席之地。本文简单介绍了决策树的算法和剪枝,在此基础上用R实现了一个决策树,并在两个数据集上进行了测验,证实了决策树的能力。

打赏支持我写出更多好文章,谢谢!

打赏作者

打赏支持我写出更多好文章,谢谢!

任选一种支付方式

1 2 收藏 2 评论

关于作者:翱翔的翱

Java is a good boy! 个人主页 · 我的文章 · 6 ·    

相关文章

可能感兴趣的话题



直接登录
最新评论
跳到底部
返回顶部