这篇文章只是为了方便理解,在实际建模、找工作的笔试、面试中用到,所有不会太复杂地讲原理和涉及到代码运用(python选手可自学sklearn大家庭)。所以只是很通俗地介绍决策树的相关知识。
1. 什么是决策树
![73cc9525bf765dd5422a34902bfae153.png](https://i-blog.csdnimg.cn/blog_migrate/578c548d80f51cf7b12193065830657f.jpeg)
如图,他是一棵能帮你做决策的树。树上的节点是training data里的特征(可以理解为通往答案分岔路口)。
如图,根据training data,我们发现,只要refund是yes的人,全都是cheat为no的,所以有理由相信只要是refund是yes的人,他就会是cheat为no的人。回到refund是no的情况,之后,我们开始关注Marst这个特征,我们发现在training data中只要是refund是no且married的人,cheat为no,所以我们有理由相信这类人的cheat就是no。同理其他特征。
所以当我们对test set的record进行分类的时候,就会沿着这一棵决策树进行判断,最后得到类别。
那么,我们就会有以下几个问题:
1) 怎么构建决策树?
2) 如果遇到一个特征不能完全成为分岔路口,也就是遇到例如refund 是yes的人既有cheat为no,也有yes,该如何处理?
3) 如果遇到特别特别多的特征,那么我是不是必须要建一颗硕大无比的树呢?
第二节告诉你答案。
2. 怎么构建决策树
1) 数据处理
a) 想清楚是二分叉还是多分叉
b) 对于连续值变量是采用离散化还是基于某个值大于/小于/等于分段
2) 如何选取特征作为当前的最佳节点/分岔路口
一共会有以下三种方法进行选择:
a) gini index
![fe9958573bba0703e4753998aebd79c1.png](https://i-blog.csdnimg.cn/blog_migrate/ca25890fb506664445be4505aae0dff7.png)
从gini的公式,我们发现了熟悉的条件概率,之后你会发现后面几个方法都绕不开条件概率,只是不同方式去利用条件概率给出的信息。
我们发现他就是看在特征t作为节点的时候,record的分类情况如何,他们分别在class c1 和class c2的个数是多少,进而求出各自的条件概率,最后得到特征t的gini index。
那么越小的gini index,越好的分类效果。
但是,有个问题出现了,我们即使得到特征t的gini index最小,那么我们如何判断他该不该继续分子节点呢?(因为有时候继续分反而更加混乱)。
这就引申到Ginisplit的概念。
公式如下:
![3db6cb2bf66537dbf669052f87727179.png](https://i-blog.csdnimg.cn/blog_migrate/3680b176af151f04a6a08822be5ff06d.png)
需要注意的是分母是当前node的record总数,而分子是子节点拥有的record总数。
![6a47a1011249ec922d0871eb56600dd8.png](https://i-blog.csdnimg.cn/blog_migrate/6639985a5662de5d45a029bd4b5746c0.png)
通过以上小例子,我们只是子节点的gini split比父节点的gini要更小,也就是说分类效果更好,所以我们应该继续分下去。
插播一条如何计算连续值gini index的小广告:
i. 以下这张图的方法,就是先把特征的值进行排序之后,进行分段,求出每一段的gini index
![6165860bc35673b70be22f7a22532282.png](https://i-blog.csdnimg.cn/blog_migrate/c5a148d7a6b336d7fb54798e618faa36.jpeg)
ii. 自己分段,例如遇到温度特征的时候,可以根据常识设置10度以下为寒冷,10-30度是舒适,30度以上是炎热这三个类别。
b) entropy
![6d28e9678d8320ca6fc8126c1f2921da.png](https://i-blog.csdnimg.cn/blog_migrate/4c3ebf6c024a37b0e932f2fa64e2f06c.png)
依旧和条件概率有关系,但加多了个log。也是因为有log的关系,所以要加个负号,使得他是一个正值。以下是计算entropy的例子。
![2a2189ec9629099c06bed6c61ce963b2.png](https://i-blog.csdnimg.cn/blog_migrate/1baafc989756a5ff1b2daf5e49206810.png)
我们就知道,当entropy越小的时候,分类效果越好。
自然地,和gini index一样,我们需要进一步判断该不该继续进行分子节点。由以下式子判断(和gini split很像)
![3e1057e1bb3556104ba4e9a4a32b42ca.png](https://i-blog.csdnimg.cn/blog_migrate/a255c1cc5cd5fbc7b08fae070758999e.png)
但是这个式子有个缺点就是,但该特征的取值越多(即子节点的个数越多),GAINsplit的取值会越大,会反映出分类效果越好,但这个好不一定是真的,可能只是因为该特征取值多而已,所以为了牵制住这个因素,我们引入下一公式:
![32b3eab0e5804e232d3725665fd9cfaf.png](https://i-blog.csdnimg.cn/blog_migrate/e2496e55f5ad5d612facdf9ad8d3e4fd.png)
加入splitinfo以牵制住特征取值太多的影响,以下是一个例子:
![2ed32b1ba99db2e2436302c4dc4875b0.png](https://i-blog.csdnimg.cn/blog_migrate/f844ecda1edc4ff305030455ba34c966.png)
所以该特征的取值越多,splitinfo会越大,那么GainRATIO会越小。在经过类似normalization的处理之后。得到各个特征的Gain,再进行比较,选出最大值以作为当前节点。
c) classification error
![965dc514dd4e8023bec33db32bd31ac0.png](https://i-blog.csdnimg.cn/blog_migrate/3048f91c67b37fbf8d238f9dd001cb5e.png)
依旧是条件概率,但比较省事的是,他只要最大值。那他的含义和她名字一样,就是当我们分类的时候,把条件概率最大的那一节点看作是正确的,而分到其他类则为错误的,我们要计算这个错误的值是多少。自然的,越小的错误,分类效果越好。
那么这三个分类标准选取哪个呢?
还是要具体情况具体分析,没有一个指标是绝对的好。只能说当前建模(我接触到的)大多使用gini index。不同指标,建出来的树可能一样可能不一样。以下是三种分类标准的取值范围:
![8a5e723b0e02779ab52c5b3f11d054ef.png](https://i-blog.csdnimg.cn/blog_migrate/82b9cbf086a687c8aa3ff01f7279e33f.png)
3. 怎么防止过拟合?
过拟合,也就是我们的模型过于为training set“量身定制”,导致用在test set上效果不好,“穿不上”这套紧身的衣服。放在决策树里,就是分支过多、过复杂。想象一下,如果我们疯狂无限分支,会不会出现一个目标值就对应一个子节点呢,也就是为了一个目标值的准确分类而大动干戈地建一个子节点给他。这样是不够robust的,所以我们需要防止过拟合。通常,我们用以下三条标准去停止分支:
1) 当所有record都属于同一类时,停止扩展节点
2) 当所有record具有相似的属性值时,停止扩展节点
3) 当节点包含少量其他的record时提前终止,虽然这会一定程度减小在训练集上的准确率,但我们更需要一个泛化能力好的模型。