决策树算法在机器学习中算是很经典的一个算法系列了。它既可以作为分类算法,也可以作为回归算法,同时也特别适合集成学习比如随机森林。
决策树是对特征空间(数据集)的一个划分,在每个划分单元上有一个特定的输出值。假设决策树将特征空间划分成M个单元 R1,R2,...,RM ,每个单元 Rm 上都有一个特定的输出值 cm ,对于分类树来说 cm 是类别,对于回归树是该单元上所有样本对应目标的均值。于是决策树的模型可以表示为
而决策树的树形结构展现的是对特征空间的划分规则。划分规则可以有很多,也可能不存在,如何选择最好的划分规则是构建决策树的关键。
如何度量一个决策树的好坏呢?根据(1)中的 f(x) 与真实目标值的损失函数,分类树是0-1损失函数,而回归树是平方损失函数,由此得到决策树模型的损失函数。最小化损失函数便可选择最优的决策树。但是优化的过程是一个NP难问题,所以现实中决策树算法通常采用启发式算法,近似求解这一问题。
特征空间的划分过程对应于决策树的构造过程,而特征空间的划分依据的是特征和特征的取值,所以特征的选择成为构建决策树的关键。根据特征选择的方式可以将决策树算法分为ID3,C4.5和CART。
学习信息增益,首先要明白什么是熵和条件熵
熵:表示随机变量不确定性的度量。设X是一个取值有限的随机变量,其概率分布为
则随机变量X的熵定义为
条件熵:条件熵 H(Y|X) 表示在已知随机变量X的条件下,随机变量Y的不确定性,定义为X给定条件下Y的条件概率分布的熵对X的数学期望
其中 H(Y|X=xi) 是Y的条件概率分布的熵
互信息:表示得知X之后,Y的信息的不确定性减少的程度
信息增益:在决策树中的信息增益等价于训练数据D中类别与特征A的互信息
其中 H(D) 表示对训练数据集D分类的不确定性,是对类别分布的熵。 H(D|A) 是在特征A确定的条件下,数据集分类的不确定。信息增益即在给定特征A之后,数据集分类不确定性的减少。
如何根据信息增益选择最优的特征?对训练数据集D,计算每个特征的信息增益,选择信息增益最大的特征为最优的特征。
设训练数据集为D,|D|是样本的个数。设有K个类别 {c1,c2,...,cK} ,每个类别的个数为 |ck| 。设特征A有n个不同的取值 {a1,a2,...,an} ,根据特征可以将数据集划分成n个子集 D1,D2,...,Dn ,每个部分的样本个数为 |Di| 。设子集 Di 中属于类别 ck 的集合为 Dik , |Dik| 为该子集的个数,于是信息增益的算法如下:
计算数据集D的熵 H(D)
计算特征A对数据集D的条件熵 H(D|A)
计算信息增益 g(D,A)=H(D)−H(D|A)
以信息增益作为划分训练数据集的度量,容易偏向选择取值较多的特征,使用信息增益比可以解决这一问题。
其中 g(D,A) 是数据集关于特征A的信息增益, HA(D)=−∑ni=1|Di|Dlog|Di|D ,根据特征A将数据集划分,然后计算熵,对应于特征A的熵。
以随机变量X为例,基尼系数的定义为
如果是二分类问题,属于第一类的概率为 p ,则对应的基尼系数为
Gini(p)=p(1−p)+(1−p)p=2p(1−p)
基尼系数常用于CART分类树的构建,而CART树是二叉树,根据特征A将数据集分为两部分 D1,D2 ,所以在特征A的条件下,集合D的基尼系数为
基尼系数代表了模型的不纯度,基尼系数越小,模型的不纯度越低,表示特征越好,这和信息增益(比)是相反的。
同时基尼系数的计算中没有对数的计算,比信息增益比要快速和精确,而且基尼系数的曲线和熵近似,可以作为熵的一种替代。
决策树的生成对应于特征空间划分的过程。首先将数据集(特征空间)作为根节点,在所有特征中选择一个最好特征最为划分特征,根据特征的取值将数据集划分为多个子集,作为子节点,然后递归地对子节点进行划分,直到满足停止条件。
根据上节三种特征选择的度量方式,可以将决策树生成算法分为ID3,C4.5和CART。
ID3算法构造一棵分类树。首先给出ID3算法的流程:
输入:数据集D
输出:决策树T
决策树构建完毕之后,每一个叶节点对应的是一个划分空间,假设有M个划分空间 R1,R2,...RM ,叶节点 Rm 的类标记 cm 是该子空间的输出。给定一个新样本 x ,用 f(x)=∑Mi=1cmI(x∈Rm) ,即根据决策树找到其对应的叶节点,该叶节点的类别标记即为 x 的预测类别。
ID3算法虽然提出了新思路,但是还是有很多值得改进的地方。
C4.5利用信息增益比改善ID3中的第二个问题,同时可以将连续特征离散化来解决第一个问题。至于第三个和第四个问题,之后具体讲解。
C4.5和利用信息增益比选择特征,其余和ID3完全一样。不做解释。
但是C4.5仍然有一些缺点,1、信息增益比的计算中有对数的计算,在计算过程中会损失准确定;2、C4.5是一颗多叉树,很多时候,在计算机中二叉树模型会比多叉树运算效率高。如果采用二叉树,可以提高效率。3、C4.5仍然只能用于分类。
CART采用基尼系数来选择特征,避免了对数的计算。同时每次划分数据集是只将其划分为两部分,所以CART是一棵二叉树,而且CART回归树可以处理回归问题。
CART是一颗二叉树,首先选择最佳划分的特征,然后选择最佳划分的值,每次划分出一棵二叉树。回忆下ID3或者C4.5,如果某个特征A被选取建立决策树节点,如果它有a1,a2,a3三种类别,我们会在决策树上一下建立一个三叉的节点。这样导致决策树是多叉树。但是CART分类树使用的方法不同,他采用的是不停的二分,还是这个例子,CART分类树会考虑把A分成{a1}和{a2,a3}, {a2}和{a1,a3}, {a3}和{a1,a2}三种情况,找到基尼系数最小的组合,比如{a2}和{a1,a3},然后建立二叉树节点,一个节点是a2对应的子集,另一个节点是{a1,a3}对应的子集。同时,由于这次没有把特征A的取值完全分开,后面我们还有机会在子节点继续选择到特征A来划分a1和a3。这和ID3或者C4.5不同,在ID3或者C4.5的一棵子树中,离散特征只会参与一次节点的建立。
CART分类树的算法如下:
停止条件是1、节点中样本个数小于阈值;2、样本子集的基尼系数小于阈值;3、没有更多的特征用于划分
回归树不再次用信息增益(比)或基尼系数来选择特征和划分点,而是使用平方误差最小的准则求解最优的特征和划分值。遍历数据集中的每一个特征和该特征的每个取值,对于第j个特征的取值s,将数据集划分为两个子集,划分规则是
计算对应子集的输出值
其中 ave 表示求平均值。
最后求解平方误差
选择可以使上式最小的j,s划分数据集。
CART回归树的算法流程如下:
根据上文选择最优的特征j和切分点s
用选定的 (j,s) 将数据集划分成两个区域作为两个子节点,并确定相应的输出值
划分区域为
输出值为
对子节点(子集)重复1,2,直到满足停止条件
停止条件是1、节点中样本个数小于阈值;2、样本集的平方误差小于阈值;3、没有更多的特征用于划分
构建好决策树之后,给定待预测的样本 x ,用 f(x)=∑Mi=1cmI(x∈Rm) ,即根据决策树找到其对应的叶节点,该叶节点的输出值记即为 x 的预测值。
CART回归树和分类树有两点主要的区别:1、选择特征和切分点的度量方式不同,分类树采用基尼系数,而回归树采用平方误差;2、叶节点的输出求解方式不同,分类树叶节点的输出是该节点对应子集中采用大多数样本的类别,而回归树叶节点的输出是该节点对应子集中所有样本目标的均值。
ID3,C4.5和CART的区别
算法 | 支持模型 | 树结构 | 特征选择 | 连续值处理 | 缺失值处理 | 剪枝 |
---|---|---|---|---|---|---|
ID3 | 分类 | 多叉树 | 信息增益 | 不支持 | 不支持 | 不支持 |
C4.5 | 分类 | 多叉树 | 信息增益比 | 支持 | 支持 | 支持 |
CART | 分类,回归 | 二叉树 | 基尼系数,均方差 | 支持 | 支持 | 支持 |
看起来CART算法高大上,那么CART算法还有没有什么缺点呢?有!主要的缺点我认为如下:
魏红宁. 决策树剪枝方法的比较[J]. 西南交通大学学报, 2005, 40(1):44-48.
决策树算法递归地产生决策树,直到不能继续下去为止,这样得到的决策树往往对训练数据分类很准确,但是对未知的测试数据却没有那么准确,即偏差小,方差大,容易出现过拟合现象。过拟合的原因在于学习时过多考虑如何提高对训练数据的正确分类,从而得到复杂的决策树。所以要对决策树进行简化,简化的过程称为剪枝(pruning)。剪枝的方法分为两种:预剪枝和后剪枝。
预剪枝:在决策树构造过程中,根据某些条件,提早停止树的构造。比如节点中样本个数小于阈值,决策树的高度达到指定高度等,sklearn.tree中使用的就是预剪枝,阈值需要自己设置。缺点是可能会产生欠拟合。
后剪枝:在生成决策树之后进行剪枝,得到简化的决策树。后剪枝又可以分为两类:1、自底向上;2、自顶向下。思想就是从原始决策树中,按照规则将非叶节点剪枝成为叶节点,比较剪枝前后决策树的误差决定是否要剪枝,直到得到误差最小的决策树。后剪枝和预剪枝相比,需要消耗额外的时间,但是效果更好。
REP(reduced error pruning):REP是当前最简单的后剪枝方法,需要一个额外的数据集D辅助剪枝过程。基本思路是,对于决策树T中的每个非叶子节点S,将其子树都剪去,成为一个叶节点,此时的决策树为 TS ,计算D在T和 TS 上的误差,如果 TS 的误差小于T的误差,则对该非叶节点剪枝,否则不剪枝。虽然REP很简单,但是需要一个额外的数据集,当数据量小的时候,一般不采用这种方法。REP是自底向上的后剪枝方法。
PEP(pessmistic error pruning):PEP方法是为了克服REP方法需要额外剪枝数据缺点而提出的,不需要额外的剪枝数据。PEP按照以下公式对每个非叶节点自上而下计算,如果满足,则将该非叶节点剪枝成为叶节点,直到遍历完所有非叶节点。
其中
e′(t)=e(t)+0.5
e′(Tt)=∑ie(i)+2/Nt
Se(e′(Tt))=[e′(Tt)n(t)−e′(Tt)n(t))]12
e(t) 是非叶节点t处的误差, Tt 是以t为根节点的子树, i 是子树 Tt 的叶子结点的编号, Nt 是子树 Tt 叶子结点的个数, n(t) 是非叶节点t处训练样本的个数。
对于每个非叶节点,如果满足(1)式,在在该处剪枝。下面给出一个例子:
上图中的非叶节点有5个,从 t1 到 t5 。首先对 t1 计算:
e′(t1)=25+0.5=25.5 ,以 t1 为根的子树有6个叶节点,所以 e′(Tt1)=1+2+1+1+6/2=8 , Se(e′(Tt1)=[8∗80−880]12=2.68 ,因为 25.5>8+2.68 ,所以不用剪枝。依次计算 t2 到 t5 ,只有 t4 需要剪枝,所以讲 t2 的两个子树剪掉,是 t4 称为一个叶节点。
PEP是一种自顶向下的剪枝方法,是目前比较精确的一种剪枝方法。但是PEP和预剪枝有同样的缺陷,由于是自顶向下的剪枝,如果某个非叶节点需要剪枝,则连通其所有子节点一同剪去,而这些剪去的叶节点并没有判断。
在PEP中,每个非叶节点最多只用判断一次,所以剪枝速度很快。
CCP(cost-complexity pruning):CCP主要包含两个步骤,1、从原始的决策树 T0 中按照规则生成一个子树序列 T0,T1,...,Tn ,其中 Tn 是只包含根节点的树;2、从子树序列中根据误差估计选择一棵最好的树最为剪枝后的决策树。(在《统计学习方法》P72页有详细介绍)
1、如何从原始决策树生成一个子树序列:子树 Ti+1 是从子树 Ti 生成的。对子树 Ti 的每个非叶节点计算下式
其中 Tt 是以非叶节点 t 为根节点的子树, R(Tt) 是测试数据在该子树上的误差(如果是回归树,计算均方误差), R(t) 是剪枝后该节点上的误差, |L(Tt)| 是子树的叶子节点数。选择 α 最小的非叶节点进行剪枝得到 Ti+1 ,并记录对应的 αi+1=α 直到只剩一个根节点为止,即 Tn 。
2、如何从子树序列中选择最优的决策树:在得到子树序列后,用测试数据在每个决策树上计算 Rα(Ti)=R(Ti)+α|L(Ti)|,i=0,1,2,...,n ,找到使 Tα(Ti) 最小的i,对应的决策树即为剪枝后的决策树。
具体步骤如下:
输入:原始决策树 T0
输出:剪枝后最优决策树 Tα
设 k=0,T=T0,α=+∞
自下而上地对每个非叶节点计算
并找到使 g(ti) 最小的非叶节点 tm ,对该节点进行剪枝,并对该叶节点以多数表决法决定其输出类别,得到树T,并有 α=g(tm)
设 k=k+1,αk=g(tm),Tk=T
如果 T 不是只有根节点构成的树,则回到第2步
采用交叉验证法计算 Rα(Ti)=R(Ti)+α|L(Ti)|,i=0,1,2,...,n ,得到 miniRα(Ti) ,得到最优子树 Ti
以上图为例,图中所示的是 T0 ,首先对非叶节点 T−2T5 计算 g(ti) , R(t5)=4/80,R(Tt5)=0,L(TT5)=2,g(t5)=4/80=0.02 ,依次计算 g(t4)=0.0125,g(t3)=0.0375,g(t2)=0.0293 ,其中最小的是 g(t4) ,所以对 t4 剪枝得到 T1 ,并且 α1 =0.0125。
CCP是一个自底向上的剪枝方法,所需的时间与非叶节点的个数成二次关系,所以和PEP相比比较慢,而且CCP方法存在一个缺点,就是最优决策树只能从 T0,T1,...,Tn 中选择,如果最优决策树不再这个序列中,的不能得到。
总之,决策树的剪枝是在遍历每个非叶节点的过程中,通过剪枝和测试的动态过程中完成的。
巩固, 张虹. 决策树算法中属性缺失值的研究[J]. 计算机应用与软件, 2008, 25(9):242-244.
《机器学习》 周志华
http://blog.csdn.net/zrjdds/article/details/50223091
Python中处理缺失值
决策树为什么对缺失值不敏感
总结于scikit-learn的英文文档。
首先我们看看决策树算法的优点:
我们再看看决策树算法的缺点:
scikit-learn决策树算法类库内部实现是使用了调优过的CART树算法,既可以做分类,又可以做回归。分类决策树的类对应的是DecisionTreeClassifier,而回归决策树的类对应的是DecisionTreeRegressor。两者的参数定义几乎完全相同,但是意义不全相同。下面就对DecisionTreeClassifier和DecisionTreeRegressor的重要参数做一个总结,重点比较两者参数使用的不同点和调参的注意点。
参数 | DecisionTreeClassifier | DecisionTreeRegressor |
---|---|---|
特征选择标准criterion | 可以使用”gini”或者”entropy”,前者代表基尼系数,后者代表信息增益。一般说使用默认的基尼系数”gini”就可以了,即CART算法。除非你更喜欢类似ID3, C4.5的最优特征选择方法。 | 可以使用”mse”或者”mae”,前者是均方差,后者是和均值之差的绝对值之和。推荐使用默认的”mse”。一般来说”mse”比”mae”更加精确。除非你想比较二个参数的效果的不同之处。 |
特征划分点选择标准splitter | 可以使用”best”或者”random”。前者在特征的所有划分点中找出最优的划分点。后者是随机的在部分划分点中找局部最优的划分点。默认的”best”适合样本量不大的时候,而如果样本数据量非常大,此时决策树构建推荐”random” | 同左 |
划分时考虑的最大特征数max_features | 可以使用很多种类型的值,默认是”None”,意味着划分时考虑所有的特征数;如果是”log2”意味着划分时最多考虑log2Nlog2N个特征;如果是”sqrt”或者”auto”意味着划分时最多考虑N−−√N个特征。如果是整数,代表考虑的特征绝对数。如果是浮点数,代表考虑特征百分比,即考虑(百分比xN)取整后的特征数。其中N为样本总特征数。一般来说,如果样本特征数不多,比如小于50,我们用默认的”None”就可以了,如果特征数非常多,我们可以灵活使用刚才描述的其他取值来控制划分时考虑的最大特征数,以控制决策树的生成时间。 | 同左 |
决策树最大深max_depth | 决策树的最大深度,默认可以不输入,如果不输入的话,决策树在建立子树的时候不会限制子树的深度。一般来说,数据少或者特征少的时候可以不管这个值。如果模型样本量多,特征也多的情况下,推荐限制这个最大深度,具体的取值取决于数据的分布。常用的可以取值10-100之间。 | 同左 |
内部节点再划分所需最小样本数min_samples_split | 这个值限制了子树继续划分的条件,如果某节点的样本数少于min_samples_split,则不会继续再尝试选择最优特征来进行划分。 默认是2.如果样本量不大,不需要管这个值。如果样本量数量级非常大,则推荐增大这个值。我之前的一个项目例子,有大概10万样本,建立决策树时,我选择了min_samples_split=10。可以作为参考。 | 同左 |
叶子节点最少样本数min_samples_leaf | 这个值限制了叶子节点最少的样本数,如果某叶子节点数目小于样本数,则会和兄弟节点一起被剪枝。 默认是1,可以输入最少的样本数的整数,或者最少样本数占样本总数的百分比。如果样本量不大,不需要管这个值。如果样本量数量级非常大,则推荐增大这个值。之前的10万样本项目使用min_samples_leaf的值为5,仅供参考。 | 同左 |
叶子节点最小的样本权重和min_weight_fraction_leaf | 这个值限制了叶子节点所有样本权重和的最小值,如果小于这个值,则会和兄弟节点一起被剪枝。 默认是0,就是不考虑权重问题。一般来说,如果我们有较多样本有缺失值,或者分类树样本的分布类别偏差很大,就会引入样本权重,这时我们就要注意这个值了。 | 同左 |
最大叶子节点数max_leaf_nodes | 通过限制最大叶子节点数,可以防止过拟合,默认是”None”,即不限制最大的叶子节点数。如果加了限制,算法会建立在最大叶子节点数内最优的决策树。如果特征不多,可以不考虑这个值,但是如果特征分成多的话,可以加以限制,具体的值可以通过交叉验证得到。 | 同左 |
类别权重class_weight | 指定样本各类别的的权重,主要是为了防止训练集某些类别的样本过多,导致训练的决策树过于偏向这些类别。这里可以自己指定各个样本的权重,或者用“balanced”,如果使用“balanced”,则算法会自己计算权重,样本量少的类别所对应的样本权重会高。当然,如果你的样本类别分布没有明显的偏倚,则可以不管这个参数,选择默认的”None” | 不适用于回归树 |
节点划分最小不纯度min_impurity_split | 这个值限制了决策树的增长,如果某节点的不纯度(基尼系数,信息增益,均方差,绝对差)小于这个阈值,则该节点不再生成子节点。即为叶子节点 。 | 同左 |
数据是否预排序presort | 这个值是布尔值,默认是False不排序。一般来说,如果样本量少或者限制了一个深度很小的决策树,设置为true可以让划分点选择更加快,决策树建立的更加快。如果样本量太大的话,反而没有什么好处。问题是样本量少的时候,我速度本来就不慢。所以这个值一般懒得理它就可以了。 | 同左 |
除了这些参数要注意以外,其他在调参时的注意点有:
csc_matrix
稀疏化,在预测前调用csr_matrix稀疏化。
关于DecisionTreeClassifier 和 DecisionTreeRegressor 中的方法
首先实例化,实例化的参数根据上表选择
利用fit(X,y)函数构建决策树
采用predict(testSet)预测类别或者也测目标值
次用score(testSet)计算分类误差(分类树)或者均方误差(回归树)