机器学习算法——决策树

决策树的定义

        在机器学习的各种算法中,决策树是一种非常重要的分类算法。从计算机科学的角度来看,在数据结构中也有“树”的结构,对于特定的问题建立“树”后,可以用于快速的查找、分类。决策树本质上也是来自于数据结构的“搜索树”。

        在数据结构中,“树”常常是指有根树。另外还有自由树,其本质更接近于图,是图论的讨论内容。而有根树常常使用递归的方法来定义:一棵要么是空的(不含有任何结点,称为空树),要么由以下元素组成:

T=\left \{ r, \ T_1,\ T_2, \ ...,\ T_n \right \}

其中rT的一个结点,称为根结点T_1T_2,...,T_n都是树,称为T子树

        另外诸如内部结点、叶结点的严格定义此处不再赘述。而决策树对树的概念赋予了实际意义,在李航《统计学习方法》中,决策树是如下定义的:

        定义5.1(决策树)        分类决策树模型是一种描述对实例进行分类的树形结构,决策树由结点(node)和有向边(directed edge)组成。结点有两种类型:内部结点(internal node)和叶节点(leaf node)。内部结点表示一个特征或属性,叶结点表示一个类。

决策树的基本特征

        从上面的定义来看,决策树类似一种程序流程图,可以视为一堆if语句的判断分支结构。例如,在小学评选荣誉的时候,可能就会有这么一种决策树:

当然,实际的评选还有各种复合荣誉,还需要考虑多方面因素,但此处仅做示例。我们可以看到,这样一个流程图正符合决策树的定义,其中每个内部结点(如“成绩”,“日常表现”等)表示一个特征或属性,而每个叶节点就是决策树输出的样本的类,即所获荣誉的类别。它有一个简单的性质就是完备且互斥,即每个样本从根节点开始,有且仅有一条路径前往其所属的类别,例如给定一个成绩优秀、但并非班干部,且日常表现中规中矩的人,在上述决策树中会被分类到“学习积极分子”。

        类别在每个叶节点都是确定的,因而决策树可以视为一个分段的函数,在每个段内都是常值。即相当于将整个特征空间划分为若干块,在每个块内给出一个静态的预测,表示这个块的类别。它一定是静态的,在叶节点处必须直接决定其类别,而不能单纯把原函数“分情况讨论”。

        决策树的每个分支都只能是给定特征满足的某个条件,例如,在上面的荣誉评选结果中,一旦选择了“成绩”和“日常表现”分开来看的方法,那么就不能再将其直接联系到一起。例如,不能再创造所谓的“加权成绩”,在选定好特征后,决策树只能按照给定的特征划分空间,例如成绩优秀与不优秀,日常表现良好与不良,而不能再产生“成绩分数*0.7+日常表现分数*0.3>80”这样的内部节点分支。这表明,决策树无法学习特征之间的相关性。从几何上来看,它在划分区域时,只能垂直坐标轴画线,而不能画斜线,如:

        垂直划线的性质使得决策树有很多新的特点。决策树的学习可以随意划线,因而可以解决非线性问题。例如在以下二类划分中,绿色“+”与红色“×”分别代表正类与负类,显然其是一个非线性问题,但可以通过决策树的多次划分顺利分类:

        只要划分足够细,那么分类问题必然可以得到解决(极端情况就是每一个叶节点只包含一个样本),但是,因为划的线永远垂直于坐标轴,因此特征选择会产生较大的影响,例如对于一个简单的线性分类问题,可能就会产生悲剧的结果:

        在数据量特别大时,决策树对于此类线性问题反而效果极差,因此在特征选择时要慎重考虑决策树无法学习特征之间的相关性这一特点。当然决策树能够解决非线性问题使得其更具优势,上述的对角线尽管无法直接划线解决,但通过多段拟合仍然能够解决问题。而能够解决非线性问题的能力,使得决策树仍然是一种相当重要的算法。

决策树与概率分布

       决策树还可以表示一些复杂的条件概率分布问题,但其本质上仍是进行分类。例如,某一系列样本具有特征x,其另有一随机变量y0\leqslant x\leqslant 10\leqslant y\leqslant 1x+y服从[0,\ 1]上的均匀分布,而我们认为1\geqslant y>0.4时该样本属于A类,否则属于B类。应用决策树时,我们往往把叶节点划分到,使得特征在叶节点的取值范围内,所产生的条件概率能够决定性倾向于某一类,从而能强行根据概率最大的原则决定其类别。上面这个例子中,因为z=x+y服从均匀分布,因此

P(0.4<y\leqslant 1)=P(0.4<z-x\leqslant 1)=P(0.4+x<z\leqslant 1)=0.6-x

所以在x>0.1时,这个概率小于0.5,因此可以强行把它划到B类;否则就强行把它划到A类。决策树就以x为特征,以是否大于0.1为判据,表达出了在给定x的条件下样本类别的概率分布。 

决策树的学习

        决策树的学习过程实际上就是选择分类规则的问题。在二叉搜索树中,根据样本的分布合理排列各种判断的先后,也会对二叉搜索树的算法效率产生提升。同时,对训练数据能够进行正确的分类的决策树必然存在,但泛化能力也是必须考虑的因素,实际中不可能应用把每个训练数据都单独作为一个叶节点的决策树,这种情况会导致严重的过拟合。综合上述考虑,决策树的学习算法必须考虑到三个因素:1.分类规则的合理选择和排列;2.决策树模型的总体复杂度;3.决策树模型的拟合能力,因而其允许存在一定的误差。

        决策树学习算法大致可以分为特征选择、决策树的生成、决策树的剪枝三个过程。

        特征选择实际上就是考虑分类规则的合理选择和排列。对分类起更重要作用的特征应当首先筛选出来,例如对于高考的筛选,首先就依靠总分排名,随后就轮流比较语文、数学、英语,据说最近还会考虑学业水平考试的成绩,这就是把特征根据对分类的直接影响力排列。我们随后会引入一些定义,严格量化这个“影响力”。

        决策树的生成就是根据直接影响力,逐个选择内部结点的排布,在满足停止条件后再根据每个叶结点包含的训练数据的属性,确定这个叶结点的实际类别。

        决策树生成的停止条件常常是局部的,例如说再增加一个分支可能并不会对分类的效果产生较大的增益,那么就不再生成,或者说某个分支的深度足够深、某个叶结点含有的样本量已经足够小时,即停止。而这样生成的决策树,在对某一分支进行停止条件的判断时往往难以考虑到决策树全局的复杂度,因而需要运用剪枝算法,在生成结束后对决策树再进行一次调整。

特征选择过程

        如前文所述,特征选择过程实际上是一个挑选对分类起重要作用的特征的过程。如何表征一个特征能起到多大作用?无非就是实际拿这个特征划分一下,观察按照某个界限划分之后,得到的两个区域中是不是更好分类了。什么叫“更好分类”?经验上来说,以二分类为例子,假设划分前整体区域中正类和负类的样本量差不多,而划分后两个区域仍然是正类负类数量持平,那划分便几乎没有起到什么作用。而如果一刀划下去,泾渭分明,难题瞬间解决,或者说剩余下的两类只有很少的“杂质”,那么这个划分可谓神之一手。

        想象储气罐里的一堆空气,我们要分开其中的氧分子和氮分子,如果氧分子都排列在左侧,氮分子都排列在右侧,那可太美妙了!但是事实是,在空间中怎么切一刀,它们都是融合在一起,分不开。那么根据常温下物理空间的差异划分两种气体,实在没有办法,这个特征完全起不到作用,应当抛弃。工业上分离氧气和氮气,是使用低温冷凝的方法,在液态条件下,氧气的沸点高,所以加热时氮气先沸腾,那么这下子氧气和氮气分子就分离开了。

        气体完全分离和完全混合,对应着物理中一个重要的概念:熵(entropy)。这个字是胡刚复先生在普朗克于中国演讲时提及“entropy”时,生造出的一个字。气体完全分离,对应着熵为0,即高度有序状态,而完全混合,就是高度无序状态,熵达到极大值。在信息论里同样有“熵”的概念。而“有序”“无序”之差异,正好是我们想要的判断分类是否有效的一个量化指标。分类是否有效,无非就是希望分类过后至少有一边的“纯净度”得到提高,从而能帮助下一次分类。哪一种分类后纯净度更高,那哪一种分类就更有用。

        信息论中的熵是有严格定义的。对于一个随机变量,假设其是离散分布的,即有

P(X=x_i)=p_i, \ i=1,\ 2, ..., \ n

 那么这个随机变量的定义为

H(X)=-\sum_{i=1}^{n}p_i\text{ln}\ p_i

自然对数也可以替换为以2为底的对数,这是因为在计算机科学中2的次幂的数据更为常用,2的次幂也更常用于数据大小的计量。同时定义0\text{ln} \ 0=0。因为熵与随机变量X的具体取值无关,其只与X的分布特性有关,因而H(X)又记为H(p),表示熵是分布的函数。

        应用约束问题的拉格朗日乘子法求H(p)的极值,引入拉格朗日函数:

L(p_1,p_2,...,p_n,\lambda)=-\sum_{i=1}^{n}p_i\text{ln}\ p_i+\lambda(\sum_{i=1}^{n}p_i-1)

        因而求偏导,令偏导数为0,得

\frac{\partial L}{\partial p_i}=\lambda-\text{ln}\ p_i-1=0\\ \frac{\partial L}{\partial \lambda}=\sum_{i=1}^{n}p_i-1=0

        由第一式可得p_i均相等,而第二式进一步得到p_i=\frac{1}{n}。显然函数的Hesse矩阵\left ( \frac{\partial^2 H(p)}{\partial p_i\partial p_j} \right )严格负定,因而在p_1=p_2=...=p_n=\frac{1}{n}点熵取得严格极大值\text{ln} \ n。在某个p_i=1,其它p_j=0时,熵取得最小值0。这也符合我们此前的想法,当p_1=p_2=...=p_n=\frac{1}{n}时,变量完全没有任何倾向,均匀随机分布,因而最为无序,熵最大;当某个p_i=1时,说明变量完全确定,因而最为有序,熵最小。

        当随机变量仅有两个值时,即X服从伯努利分布时,

H(p)=-p\text{ln}\ p-(1-p)\text{ln}\ (1-p)

其函数图像如下:

         这同样启发我们寻找更多简单计算的函数作为熵的替代品,毕竟我们本身不需要求熵,而是希望用这种量化指标来度量划分的效果。首先可以选用简单的二次函数抛物线来拟合上述曲线,于是二分类时的“杂度函数”在某个区域可以写为:

L(S)=x(1-x)

x即为S区域内正类所占的比例。当正类负类近似相等时,取得最大值0.25,当一方占绝对优势时,取得最小值0。

        基尼指数在此基础上推广得到:

\text{Gini}(p)=\sum_{i=1}^{n}p_i(1-p_i)=1-\sum_{i=1}^{n}p_i^2 

        更多与上述曲线性质类似的函数也可以应用,重要的是能表征分类的效果,即某个区域的“纯度”。各类“杂度函数”在实际应用中取得的效果是差不多的。

        有了这一指标,我们能够正式拥有一个评估的算法,开始进行比较合理的划分了。

        以熵为例,我们要比较划分前后熵函数的减少量,用以判断划分的优劣。类似于条件期望,我们定义条件熵H(Y|X)为在确定特征X后,某个随机变量Y的分布的熵。也同样类似于条件期望,条件熵定义为熵函数的条件期望:

H(Y|X)=\sum_{i=1}^np_iH(Y|X=x_i)

        直观来讲,就是根据X的各个取值划分了若干个区域,对于一个样本,其特征X落在不同区域的概率是不同的,但确定一个区域之后,我们直接能够计算这个区域内Y分布的熵,用特征X落在各个区域的概率进行加权,也就是得到了这个熵函数的数学期望值。众所周知,数学期望值有充分的实际意义,可以表征这个划分结束后整体的“杂度”。

        那么划分取得的收益,就应该是杂度的减少值,定义为信息增益。严格来说,就是特征A对数据集D的信息增益g(D,A),满足

g(D,A)=H(D)-H(D|A)

H(D|A)就是按照特征A划分后的条件熵。一般地,似乎还有一个名称:互信息(mutual information)。

        我们可以根据信息增益最大化的原则来选取划分的标准。其对应的根据信息增益选择特征的算法的思路即是:对训练数据集D(当然之后还会对划分后的子集继续划分),计算每个特征的信息增益,即划分后熵函数的减少量,比较所有信息增益的大小,选择信息增益最大的特征作为首要的划分特征。重复此操作直到停止。

        用具体表达式写下来,设训练数据集D共存在K个类C_1,\ C_2,\ ...,\ C_K,某个特征An个取值a_1,\ a_2,\ ...,\ a_n,根据n个取值将D划分为n个子集D_1,\ D_2,\ ...,\ D_n,而某个子集D_i中,属于某个类C_k的那一部分为C_{ki},于是对于特征A的信息增益可以这么计算:

        先计算原来的熵,我们用频率估计概率,则p_i=\frac{|C_i|}{|D|},因此

H(D)=-\sum_{i=1}^{K}\frac{|C_i|}{|D|}\text{ln}\ \frac{|C_i|}{|D|}

        接下来,我们算条件熵。在某个子集D_i中,其熵仍然是和上述一样的算法:

H(D_j)=H(D|A=a_j)=-\sum_{i=1}^{K}\frac{|C_{ij}|}{|D_j|}\text{ln}\ \frac{|C_{ij}|}{|D_j|}

        然后同样用频率估计概率,计算特征A取值到a_j的概率为\frac{|D_j|}{|D|},因而条件熵为

H(D|A)=\sum_{j=1}^{n}\frac{|D_j|}{|D|}H(D|A=a_j)

        以上均可以直接算出来,从而信息增益也能够根据定义算出来。具体的算例,可以在李航《统计学习方法》中找到,在此不再赘述。

        纯粹以熵作为判断依据,还有一个小问题,我们谈到熵的最大值为\text{ln} \ n,它是与取值的个数有关的!因此取值较多的特征,其条件熵也会增大,从而会使得取值较多的特征无缘无故就占据了优势地位,而无论其分类效果是否足够好。鉴于此,还会引入信息增益比的概念,将信息增益与数据集D单纯关于特征A的分布的熵相比:

g_R(D, A)=\frac{g(D,A)}{H(p_A)}

p_A就是数据集D中特征A各个取值的分布,即H(p_A)=-\sum_{j=1}^{n}\frac{|D_j|}{|D|}\text{ln} \frac{|D_j|}{|D|}

决策树的生成

        在拥有特征选择方法后,决策树的生成也就顺水推舟了。例如ID3算法,即递归使用信息增益为判断依据生成决策树;而C4.5算法,即使用信息增益比为判断依据生成决策树。以ID3算法为例:

停止条件:最大信息增益小于某个阈值\varepsilon,或树只具有一类元素,或树的所有元素特征相同。停止时,以树中实例数最大的类作为整棵树的类标记。

递归执行以下算法:

输入:数据集D,特征集A=\left \{ A_1,A_2,..., A_m \right \}

输出:树T

计算以各个特征A_i划分D时的信息增益,取其中最大值对应的特征A_g,若不满足停止条件,则对A_g的各个可能值将D划分为D_1, D_2,...,D_l

对每个D_k,以D_k为数据集,A-\left \{ A_g \right \}为特征集调用该算法得到子树T_k,汇总所有T_k得到树T

决策树的剪枝

        如前文所述,决策树的生成过程中停止条件是五花八门的,但总的来说,每一个分支都是努力在自己的考虑范围内如何尽可能分得好,“在自己的考虑范围内”,因为是递归算法,算法一旦跑到嵌套进去了,那就与其它兄弟姐妹树没关系了。所以这样的算法也只能考虑到局部,往往难以考虑到决策树全局的复杂度,因而需要运用剪枝算法。

        回顾学习过程需要考虑的三个问题:1.分类规则的合理选择和排列;2.决策树模型的总体复杂度;3.决策树模型的拟合能力。第一个问题,我们在特征选择过程已经较好地解决了它。而第三个问题则是在生成时作为停止条件有一定牵涉,第二个问题我们完全没有考虑过。因此剪枝过程主要集中于决策树模型的拟合能力和总体复杂度的控制,要在不损失过多拟合能力的条件下,尽可能控制总体复杂度。这样,一般就与其它机器学习算法相同,我们定义一个损失函数,来量化这一标准,并通过最小化损失函数来找到我们心目中最好的决策树。

        决策树学习的损失函数可以定义为

C_\alpha(T)=\sum_{t=1}^{|T|}|S_t|H(S_t)+\alpha|T|

其中|T|表示树T叶结点总数,而S_t即是每个叶结点所对应的区域,|S_t|使其样本点数量,H(S_t)表示这个区域的熵,表征这个区域最终的“杂度”,显式写出来就是:

H(S_t)=\sum_{k=1}^K\frac{|C_k\cap S_t|}{|S_t|}\text{ln}\ \frac{|C_k\cap S_t|}{|S_t|}

        观察式子,我们可以发现,“杂度”一项求和,主要用于表征最后分类的误差,而后一项,主要就是表征模型的复杂度,也就是最后划分的子区域的数量。\alpha正是需要慢慢试探的调整两者平衡的参数,就是既要拟合得好,又不能太复杂导致过拟合。

        决策树的剪枝算法就是慢慢试探尝试减少损失函数的过程:

        首先计算好每个结点的熵H(S_t)。不只是叶结点的,内部结点的同样需要计算。从内部结点到其下属的子树,其熵必然是减小的(否则生成算法中,划分产生的信息增益小于阈值,根本不会生成这棵子树),但是这个减少量是否能补偿其复杂度的增加量,这是需要重新考虑的,因而我们需要计算这些值,定量确定到底要不要保留这棵树。如果删掉这颗子树,发现损失函数总体还是减小了,那么就毅然决然地删掉它。

        重复这样的过程,最后不需要删除任何子树时,修剪完毕。

CART算法简介

        CART(classification and regression tree),即分类与回归树。决策树不仅可以用于离散的分类问题,还可以用于回归问题。这样的决策树,同样是需要生成和剪枝两个过程的。

        用决策树来解决回归问题,仍然不能违背决策树的一般性质。一般来说,由于特征的取值是连续的,我们用二分的方法来划分整体区域。解决回归问题,也只是将整体特征空间划分为多个区域,在每个区域内部取静态的值。

        怎么决定每个叶节点对应的取值呢?一般来说我们采用平方误差\sum_i(y_i-f(x_i))^2来表征预测的误差,而要使得在每个区域内平方误差最小,根据概率统计已经证明过的结论,f(x_i)在每个区域内都应该取所有实例y_i的均值。

        那么,如何划分呢?由于特征是连续的,而样本量是有限的,我们没法再找熵函数了,但是我们的预测误差的判断标准已经变了:只要平方误差最小就可以了!当然我们还可以有更多的误差函数,但无论如何我们的目标就是让误差函数最小化。在连续的空间上,我们要对所有的特征量,逐步找到使得两侧的平方误差之和达到最小。

        具体来说,每个样本有一系列特征量(x_1, x_2, ...,x_n),我们先锁定x_1,然后找一个切分点s把空间分成x_1<sx_1\geqslant s两部分,算平方误差:

\sum _{x_1<s}(y-\bar{y}_1)^2+\sum _{x_1\geqslant s}(y-\bar{y}_2)^2

这里\bar{y}_i是各个区域内所有样本的y值的平均,这是因为我们考虑平方误差。如果更换误差函数,选择的代表整个区域的\bar{y}_i值也会变化。

        好的!这只是一次计算!而接下来,把s挪个位置,再算!因为特征空间是连续的,所以s实际上需要把整个空间扫描一遍(实际上还是离散的,因为样本量是有限的,我们关注的是划分的方式),直到找到一个使得平方误差最小的位置,把它记下来。

        还没结束!这只是x_1,我们还要依次考虑x_2, ...,x_n,直到找到使得误差函数最小的那个x_i和对应的切分点s_i,才能做第一次切分。

        然后递归进行上面的过程,对于每个子区域都要继续计算,直到满足某些停止条件,比如说每个区域内的样本量都足够小或误差足够小等等。

        用动画来演示第一次的划分,可以是这样的:

        整体是一个复杂的计算过程。

        而CART分类树的生成同样也有变化,同样采用二叉决策树,选择基尼系数为标准选择最优切分点,对每个特征,每次只做二切分。具体的过程与上类似,因此不做赘述。

        CART树的剪枝同样采用原本的损失函数:

C_\alpha(T)=\sum_{t=1}^{|T|}|S_t|H(S_t)+\alpha|T|

        对于不同的\alpha,可以剪出不同的树T_\alpha,因而当\alpha逐次增大时,剪枝需要一步步推进,从而得到一系列子树序列,但是,如果不知道到底要增大到多少才能继续推进一次剪枝,那么计算也会很麻烦。但此处有一个比较好的性质,对于一个内部结点t,当\alpha趋近于无穷时,决策树的复杂度主导损失函数,因此剪枝得到的子树必然就是单节点树,此时的损失函数为

C_\alpha(t)=C(t)+\alpha

其中C(t)是误差项。而刚生成的树的损失函数为

C_\alpha(T_t)=C(T_t)+\alpha|T_t|

如果结点t下的子树要被剪掉,一定有C_\alpha(T_t)>C_\alpha(t),即

C(T_t)+\alpha|T_t|>C(t)+\alpha

即得

\alpha>\frac{C(t)-C(T_t)}{|T_t|-1}

        由上面的式子,每个内部结点临界的\alpha值时可以确定的。因而一旦给定一个\alpha,我们能够快速确定哪些地方要被剪掉,从而确定剪枝后的树是什么形态。进而,我们能够比较方便地确定在\alpha不断变化时所有可能得到的子树{T_0, T_1, T_2, ..., T_m}

        这个性质有什么用呢?就是能更好地确定模型的选择。数据集一般有训练集、验证集和测试集,验证集即是专门用来选择模型的。我们把所有模型应用交叉验证法等方法,就可以直接确定最优的决策树,而不需要慢慢去调参了!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值