前情提要:
通俗地说决策树算法(一)基础概念介绍html
上一节,咱们介绍了决策树的一些基本概念,包括树的基本知识以及信息熵的相关内容,那么此次,咱们就经过一个例子,来具体展现决策树的工做原理,以及信息熵在其中承担的角色。java
有一点得先说一下,决策树在优化过程当中,有3个经典的算法,分别是ID3,C4.5,和CART。后面的算法都是基于前面算法的一些不足进行改进的,咱们此次就先讲ID3算法,后面会再说说它的不足与改进。算法
众所周知,早上要不要赖床是一个很深入的问题。它取决于多个变量,下面就让咱们看看小明的赖床习惯吧。spring
季节 | 时间已过 8 点 | 风力状况 | 要不要赖床 |
---|---|---|---|
spring | no | breeze | yes |
winter | no | no wind | yes |
autumn | yes | breeze | yes |
winter | no | no wind | yes |
summer | no | breeze | yes |
winter | yes | breeze | yes |
winter | no | gale | yes |
winter | no | no wind | yes |
spring | yes | no wind | no |
summer | yes | gale | no |
summer | no | gale | no |
autumn | yes | breeze | no |
OK,咱们随机抽了一年中14天小明的赖床状况。如今咱们能够根据这些数据来构建一颗决策树。编程
能够发现,数据中有三个属性会影响到最终的结果,分别是,季节,时间是否过8点,风力状况。并发
要构建一颗决策树,首先咱们要找到它的根,按照上一节所说,咱们须要计算每个属性的信息熵。函数式编程
在计算每个属性的信息熵以前,咱们须要先根据历史数据,计算没有任何属性影响下的赖床信息熵。从数据咱们能够知道,14天中,有赖床为8天,不赖床为6天。则函数
p(赖床) = 8 / 12. p(不赖床) = 6 / 12.
信息熵为oop
H(赖床) = -(p(赖床) * log(p(赖床)) + p(不赖床) * log(p(不赖床))) = 0.89
接下来就能够来计算每一个属性的信息熵了,这里有三个属性,即季节,是否过早上8点,风力状况,咱们须要计算三个属性的每一个属性在不一样状况下,赖床和不赖床的几率,以及熵值。性能
说得有点绕,咱们先以风力状况这一属性来计算它的信息熵是多少,风力状况有三种,咱们分别计算三种状况下的熵值。
风力状况为 breeze 时,有 4 / 5 的几率会赖床,而 1 / 5 的几率不会赖床,它的熵为 entropy(breeze) = -(p(breeze,赖床) * log(p(breeze,赖床)) + p(breeze,不赖床) * log(p(breeze,不赖床))) 0.722。 风力状况为 no wind 时,和上面同样的计算,熵值为 entropy(no wind) = 0.811 风力状况为 gale 时,熵值为 entropy(gale) = 0.918
最终,风力状况这一属性的熵值为其对应各个值的熵值乘以这些值对应频率。
H(风力状况) = 5/12 * entropy(breeze) + 4/12 * entropy(no wind) + 3/12 * entropy(gale) = 0.801
还记得吗,一开始什么属性没有,赖床的熵是H(赖床)=0.89。如今加入风力状况这一属性后,赖床的熵降低到了0.801。这说明信息变得更加清晰,咱们的分类效果愈来愈好。
以一样的计算方式,咱们能够求出另外两个属性的信息熵:
H(季节) = 0.56 H(是否过 8 点) = 0.748
经过它们的信息熵,咱们能够计算出每一个属性的信息增益。没错,这里又出现一个新名词,信息增益。不过它不难理解,信息增益就是拿上一步的信息熵(这里就是最原始赖床状况的信息熵)减去选定属性的信息熵,即
信息增益 g(季节) = H(赖床) - H(季节) = 0.33
这样咱们就能计算每一个属性的信息增益,而后选取信息增益最大的那个做为根节点就好了,在这个例子中,很明显,信息增益最大的是季节这个属性。
选完根节点怎么办?把每一个节点看成一颗新的树,挑选剩下的属性,重复上面的步骤就能够啦。
当所有都遍历完以后,一颗完整的树也就构建出来了,这个例子中,咱们最终构造的树会是这个样子的:
在构建决策树的时候,咱们的指望是构建一颗最矮的决策树,为何须要构建最矮呢?这是由于咱们要避免过拟合的状况。
什么是过拟合呢,下图是一个分类问题的小例子,左边是正常的分类结果,右边是过拟合的分类结果。
在现实世界中,咱们的数据一般不会很完美,数据集里面可能会有一些错误的数据,或是一些比较奇葩的数据。如上图中的蓝色方块,正常状况下咱们是容许必定的偏差,追求的是普适性,就是要适应大多数状况。但过拟合的时候,会过分追求正确性,致使普适性不好。
剪枝,即减小树的高度就是为了解决过拟合,你想一想看,过拟合的状况下,决策树是可以对给定样本中的每个属性有一个精准的分类的,但太过精准就会致使上面图中的那种状况,丧失了普适性。
而剪枝又分两种方法,预剪枝干,和后剪枝。这两种方法其实仍是蛮好理解的,一种是自顶向下,一种是自底向上。咱们分别来看看。
预剪枝其实你能够想象成是一种自顶向下的方法。在构建过程当中,咱们会设定一个高度,当达构建的树达到那个高度的时候呢,咱们就中止创建决策树,这就是预剪枝的基本原理。
后剪枝呢,其实就是一种自底向上的方法。它会先任由决策树构建完成,构建完成后呢,就会从底部开始,判断哪些枝干是应该剪掉的。
注意到预剪枝和后剪枝的最大区别没有,预剪枝是提早中止,然后剪枝是让决策树构建完成的,因此从性能上说,预剪枝是会更块一些,后剪枝呢则能够更加精确。
用ID3算法来构建决策树当然比较简单,但这个算法却有一个问题,ID3构建的决策树会偏袒取值较多的属性。为何会有这种现象呢?仍是举上面的例子,假如咱们加入了一个属性,日期。一年有365天,若是咱们真的以这个属性做为划分依据的话,那么每一天会不会赖床的结果就会很清晰,由于每一天的样本不多,会显得一目了然。这样一来信息增益会很大,但会出现上面说的过拟合状况,你以为这种状况能够泛化到其余状况吗?显然是不行的!
针对ID3决策树的这个问题,提出了另外一种算法C4.5构建决策树。
C4.5决策树中引入了一个新的概念,以前不是用信息增益来选哪一个属性来做为枝干吗,如今咱们用增益率来选!
这里面,IV(a)这个,当属性可选的值越多(好比一年可取365个日期)的时候,它的值越大。
而IV(a)值越大,增益率显然更小,这就出现新问题了。C4.5决策树跟ID3决策树反过来,它更偏袒属性可选值少的属性。这就很麻烦了,那么有没有一种更加公正客观的决策树算法呢?有的!!
上面说到,ID3决策树用信息增益做为属性选取,C4.5用增益率做为属性选取。但它们都有各自的缺陷,因此最终提出了CART,目前sklearn中用到的决策树算法也是CART。CART决策树用的是另外一个东西做为属性选取的标准,那就是基尼系数。
第一条公式中pk表示的是每一个属性的可选值,将这些可选值计算后累加。这条公式和信息增益的结果实际上是相似的,当属性分布越平均,也就是信息越模糊的时候,基尼系数值会更大,反之则更小。但这种计算方法,每次都只用二分分类的方式进行计算。好比说上面例子中的季节属性,有春夏秋冬四个可选值(春,夏,秋,冬)。那么计算春季的时候就会按二分的方式计算(春,(夏,秋,冬))。然后面其余步骤与ID3相似。经过这种计算,能够较好得规避ID3决策树的缺陷。
因此若是用CART算法训练出来的决策树,会和咱们上面ID3训练出来的决策树有些不同。在下一篇文章就会用sklearn来使用CART算法训练一颗决策树,而且会将结果经过画图的方式展示。
推荐阅读:
Scala 函数式编程指南(一) 函数式思想介绍
Actor并发编程模型浅析
大数据存储的进化史 --从 RAID 到 Hadoop Hdfs
C,java,Python,这些名字背后的江湖!