php实现决策树模型,通俗地说决策树算法(二)实例解析

favicon.ico摘要:

益来选哪个属性来作为枝干嘛,现在我们用增益率来选!这里面,IV(a)这个,当属性可选的值越多(比如一年可取365个日期)的时候,它的值越大。而IV(a)值越大,增益率显然更小,这就出现新问题了。C4.5决策树跟ID3决策树反过来,它更偏袒属性可选值少的属性。这就很麻烦了,那么有没有一种更加公正客观的决策树算法呢?有的!!CART决策树上面说到,ID3决策树用信息增益作为属性选取,C4.5用增益率作

一. 概述

上一节,我们介绍了决策树的一些基本概念,包括树的基本知识以及信息熵的相关内容,那么这次,我们就通过一个例子,来具体展示决策树的工作原理,以及信息熵在其中承担的角色。

city>>1);if(newCapacity-minCapacity<0)newCapacity=minCapacity;if(newCapacity-MAX_ARRAY_SIZE

有一点得先说一下,决策树在优化过程中,有3个经典的算法,分别是ID3,C4.5,和CART。后面的算法都是基于前面算法的一些不足进行改进的,我们这次就先讲ID3算法,后面会再说说它的不足与改进。

那个作为根节点就行了,在这个例子中,很明显,信息增益最大的是季节这个属性。选完根节点怎么办?把每个节点当作一颗新的树,挑选剩下的属性,重复上面的步骤就可以啦。当全部都遍历完之后,一颗完整的树也就构建出

二. 一个例子

众所周知,早上要不要赖床是一个很深刻的问题。它取决于多个变量,下面就让我们看看小明的赖床习惯吧。

ww.cnblogs.com/zwwhnly/");platformList.set(1,"掘金:https://juejin.im/user/5c7ce730f265da2dca

季节

时间已过 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天小明的赖床情况。现在我们可以根据这些数据来构建一颗决策树。

tring>platformList=newLinkedList<>();3.Vector使用Vector也是List接口的实现类,内部也是通过数组来实现。Vector类的代码声明如

可以发现,数据中有三个属性会影响到最终的结果,分别是,季节,时间是否过8点,风力情况。

elementData==DEFAULTCAPACITY_EMPTY_ELEMENTDATA){returnMath.max(DEFAULT_CAPACITY,minCapacity);}return

4a803abc-8f49-452c-afad-07b65b33a733.jpg

要构建一颗决策树,首先我们要找到它的根,按照上一节所说,我们需要计算每一个属性的信息熵。

size());1.4删除元素使用ArrayList删除元素有以下两个重载:Eremove(intindex);booleanremove(Objecto);Eremove(intindex);是删除

在计算每一个属性的信息熵之前,我们需要先根据历史数据,计算没有任何属性影响下的赖床信息熵。从数据我们可以知道,14天中,有赖床为8天,不赖床为6天。则

m/zwwhnly/掘金:https://juejin.im/user/5c7ce730f265da2dca388167微信公众号:申城异乡人isEmpty:true2.LinkedList使用Lin

p(赖床) = 8 / 12.

p(不赖床) = 6 / 12.

信息熵为

会扩容到33-->49。看下ArrayList的源码,就明白为什么会这样扩容:privatestaticfinalintDEFAULT_CAPACITY=10;publicbooleanadd(

H(赖床) = -(p(赖床) * log(p(赖床)) + p(不赖床) * log(p(不赖床))) = 0.89

接下来就可以来计算每个属性的信息熵了,这里有三个属性,即季节,是否过早上8点,风力情况,我们需要计算三个属性的每个属性在不同情况下,赖床和不赖床的概率,以及熵值。

(赖床))+p(不赖床)*log(p(不赖床)))=0.89接下来就可以来计算每个属性的信息熵了,这里有三个属性,即季节,是否过早上8点,风力情况,我们需要计算三个属性的每个属性在不同情况下,赖床和不

说得有点绕,我们先以风力情况这一属性来计算它的信息熵是多少,风力情况有三种,我们分别计算三种情况下的熵值。

67b167cd-af63-4cb6-a1a9-bbba45a68aca.jpg

风力情况为 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

最终,风力情况这一属性的熵值为其对应各个值的熵值乘以这些值对应频率。

.println("isEmpty:"+platformList.isEmpty());}输出结果为:索引为3的元素为:个人博客platformList的元素个数为:6platfo

H(风力情况) = 5/12 * entropy(breeze) + 4/12 * entropy(no wind) + 3/12 * entropy(gale) = 0.801

还记得吗,一开始什么属性没有,赖床的熵是H(赖床)=0.89。现在加入风力情况这一属性后,赖床的熵下降到了0.801。这说明信息变得更加清晰,我们的分类效果越来越好。

df5b8a3b-e79a-42f0-be4e-95088c5e4e9a.jpg

以同样的计算方式,我们可以求出另外两个属性的信息熵:

ummernobreezeyeswinteryesbreezeyeswinternogaleyeswinternonowindyesspringyesnowindnosummeryesgalenosu

H(季节) = 0.56

H(是否过 8 点) = 0.748

通过它们的信息熵,我们可以计算出每个属性的信息增益。没错,这里又出现一个新名词,信息增益。不过它不难理解,信息增益就是拿上一步的信息熵(这里就是最原始赖床情况的信息熵)减去选定属性的信息熵,即

va.io.Serializable{......}1.1添加元素使用ArrayList添加元素有以下两个重载:booleanadd(Ee);voidadd(intindex,Eelement);bo

信息增益 g(季节) = H(赖床) - H(季节) = 0.33

;>();//添加元素platformList.add("博客园");platformList.add("掘金");platformList.add(&q

这样我们就能计算每个属性的信息增益,然后选取信息增益最大的那个作为根节点就行了,在这个例子中,很明显,信息增益最大的是季节这个属性。

itialCapacity){this(initialCapacity,0);}publicVector(intinitialCapacity,intcapacityIncrement){super(

选完根节点怎么办?把每个节点当作一颗新的树,挑选剩下的属性,重复上面的步骤就可以啦。

16db18c3-d7d3-4e89-8fee-90f0e02772d3.jpg

当全部都遍历完之后,一颗完整的树也就构建出来了,这个例子中,我们最终构造的树会是这个样子的:

19f10ec9-e959-4c59-8541-9f5d494057dc.jpg

三. 过拟合与剪枝

在构建决策树的时候,我们的期望是构建一颗最矮的决策树,为什么需要构建最矮呢?这是因为我们要避免过拟合的情况。

,"博客园:https://www.cnblogs.com/zwwhnly/");platformList.set(1,"掘金:https://juejin.im/use

什么是过拟合呢,下图是一个分类问题的小例子,左边是正常的分类结果,右边是过拟合的分类结果。

entData;publicArrayList(){this.elementData=DEFAULTCAPACITY_EMPTY_ELEMENTDATA;}privatestaticfinalObje

54c3c5e2-eebe-4f11-b42f-b92aa61250a2.jpg

在现实世界中,我们的数据通常不会很完美,数据集里面可能会有一些错误的数据,或是一些比较奇葩的数据。如上图中的蓝色方块,正常情况下我们是允许一定的误差,追求的是普适性,就是要适应大多数情况。但过拟合的时候,会过度追求正确性,导致普适性很差。

属性选取,C4.5用增益率作为属性选取。但它们都有各自的缺陷,所以最终提出了CART,目前sklearn中用到的决策树算法也是CART。CART决策树用的是另一个东西作为属性选取的标准,那就是基尼系数

剪枝,即减少树的高度就是为了解决过拟合,你想想看,过拟合的情况下,决策树是能够对给定样本中的每一个属性有一个精准的分类的,但太过精准就会导致上面图中的那种情况,丧失了普适性。

个可选值(春,夏,秋,冬)。那么计算春季的时候就会按二分的方式计算(春,(夏,秋,冬))。而后面其他步骤与ID3类似。通过这种计算,可以较好得规避ID3决策树的缺陷。所以如果用CART算法训练出来的决

而剪枝又分两种方法,预剪枝干,和后剪枝。这两种方法其实还是蛮好理解的,一种是自顶向下,一种是自底向上。我们分别来看看。

指定元素"个人博客"platformList.remove("个人博客");System.out.println("platformList的元素个数

预剪枝

预剪枝其实你可以想象成是一种自顶向下的方法。在构建过程中,我们会设定一个高度,当达构建的树达到那个高度的时候呢,我们就停止建立决策树,这就是预剪枝的基本原理。

tring>strArrayList=newArrayList<>();for(inti=0;i<20;i++){strArrayList.add(String.valueOf

后剪枝

后剪枝呢,其实就是一种自底向上的方法。它会先任由决策树构建完成,构建完成后呢,就会从底部开始,判断哪些枝干是应该剪掉的。

ity=oldCapacity+((capacityIncrement>0)?capacityIncrement:oldCapacity);if(newCapacity-minCapacity&

注意到预剪枝和后剪枝的最大区别没有,预剪枝是提前停止,而后剪枝是让决策树构建完成的,所以从性能上说,预剪枝是会更块一些,后剪枝呢则可以更加精确。

属性可选的值越多(比如一年可取365个日期)的时候,它的值越大。而IV(a)值越大,增益率显然更小,这就出现新问题了。C4.5决策树跟ID3决策树反过来,它更偏袒属性可选值少的属性。这就很麻烦了,那么

ID3决策树算法的不足与改进

ID3决策树不足

用ID3算法来构建决策树固然比较简单,但这个算法却有一个问题,ID3构建的决策树会偏袒取值较多的属性。为什么会有这种现象呢?还是举上面的例子,假如我们加入了一个属性,日期。一年有365天,如果我们真的以这个属性作为划分依据的话,那么每一天会不会赖床的结果就会很清晰,因为每一天的样本很少,会显得一目了然。这样一来信息增益会很大,但会出现上面说的过拟合情况,你觉得这种情况可以泛化到其他情况吗?显然是不行的!

add("微信公众号");//添加重复元素,会添加成功,因为List支持添加重复元素platformList.add("博客园");platformList.a

C4.5决策树

针对ID3决策树的这个问题,提出了另一种算法C4.5构建决策树。

C4.5决策树中引入了一个新的概念,之前不是用信息增益来选哪个属性来作为枝干嘛,现在我们用增益率来选!

于数组和双向链表,这里不做详解,后续会单独写篇文章总结。4.2.2线程安全性ArrayList和LinkedList是线程不安全的,Vector是线程安全的。Vector可以看做是ArrayList在

73e9ee53-657a-4f35-a97d-74f79ecc6943.jpg

92774939-9f1c-41f4-a0f2-d6912a90b472.jpg

这里面,IV(a)这个,当属性可选的值越多(比如一年可取365个日期)的时候,它的值越大。

而IV(a)值越大,增益率显然更小,这就出现新问题了。C4.5决策树跟ID3决策树反过来,它更偏袒属性可选值少的属性。这就很麻烦了,那么有没有一种更加公正客观的决策树算法呢?有的!!

tem.out.println();System.out.println("使用foreach遍历:");for(Stringplatform:platformList){Syst

CART 决策树

上面说到,ID3决策树用信息增益作为属性选取,C4.5用增益率作为属性选取。但它们都有各自的缺陷,所以最终提出了CART,目前sklearn中用到的决策树算法也是CART。CART决策树用的是另一个东西作为属性选取的标准,那就是基尼系数。

d334df48-6915-48bf-8d3b-93dc1d0f9584.jpg

1bd64109-9c61-4e32-b818-52c365c3d235.jpg

第一条公式中pk表示的是每个属性的可选值,将这些可选值计算后累加。这条公式和信息增益的结果其实是类似的,当属性分布越平均,也就是信息越模糊的时候,基尼系数值会更大,反之则更小。但这种计算方法,每次都只用二分分类的方式进行计算。比如说上面例子中的季节属性,有春夏秋冬四个可选值(春,夏,秋,冬)。那么计算春季的时候就会按二分的方式计算(春,(夏,秋,冬))。而后面其他步骤与ID3类似。通过这种计算,可以较好得规避ID3决策树的缺陷。

据。如上图中的蓝色方块,正常情况下我们是允许一定的误差,追求的是普适性,就是要适应大多数情况。但过拟合的时候,会过度追求正确性,导致普适性很差。剪枝,即减少树的高度就是为了解决过拟合,你想想看,过拟合

所以如果用CART算法训练出来的决策树,会和我们上面ID3训练出来的决策树有些不一样。在下一篇文章就会用sklearn来使用CART算法训练一颗决策树,并且会将结果通过画图的方式展现。

List的元素主要有以下3种方式:迭代器遍历for循环foreach循环使用方法如下所示:System.out.println("使用Iterator遍历:");Iterator&

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值