zoukankan      html  css  js  c++  java
  • 决策树(ID3,C4.5,CART)原理以及实现

    决策树

    决策树是一种基本的分类和回归方法.决策树顾名思义,模型可以表示为树型结构,可以认为是if-then的集合,也可以认为是定义在特征空间与类空间上的条件概率分布.

    [图片上传失败...(image-2e6565-1543139272117)]

    决策树的中间节点可以看做是对一种特征的判断,也是符合上一次判断特征某种取值的数据集,根节点代表所有数据集;叶子节点看做是判断所属的类别.

    决策树学习通常包括3个步骤: 特征选择. 决策树生成和决策树剪枝.

    目前常用的决策树算法有ID3, C4.5 和CART.

    特征选择

    在数据集中的所有特征列表中,选择分类效果最好的特征,或者说让分类效果尽可能的"纯",通俗的说就是让划分的每个结果的尽可能属于同一个类别,都是自己人. 那么, 分类效果最好,或者说纯度,怎么定义? 用什么衡量特征的分类效果呢? 不同的决策树算法采用不同的衡量指标.比如说,ID3采用信息增益,C4.5采用信息增益比率,CART分类回归树当用于分类时,采用Gini指数,用于回归问题时采用均方差差[计算划分之前的均方差,划分之后的均方差,再做差运算]. 无论是哪种指标,本质上,都是比较用特征划分前后两种状态之间的差异变化,变化越明显越好,而各种指标是对这种差异变化的量化. 但是不同的指标会有不同的倾向性,这种倾向性从指标计算公式上可以发现,而倾向性又会引出不同的问题,进而产生不同的优化方法.

    另一方面,最佳的特征的选择,总是需要对所有特征进行一次遍历,分别计算每种特征的划分效果,比较求最优特征的最佳特征划分值.

    信息增益

    计算信息增益之前,需要先引出信息熵的概念.熵是信息论中的一个非常重要的概念,信息熵的计算,对于一个数据集D,其中N中类别的第k类样本所占比例为pk,则数据集D的信息熵:

    (Ent(D)= -sum_{k=1}^{N}p_k log_2 p_k)

    从信息熵的计算公式可以知道,Ent(D)的取值范围在[0, (log_2n)], 最小,或者说节点最纯时[都是同一个类别],为0;最大,最混乱时[每种类别比例都相等],为(log_2n).

    知道了信息熵的计算公式,那么划分前,计算数据集的信息熵, 依据特征f的n种取值划分后的n个节点,分别计算信息熵,然后依据各个节点数据集的比率,加权平均,计算划分后的总的信息熵,前后两次做差,得到这次划分的信息增益,用来衡量特征f的划分效果如何.

    信息增益:
    信息增益表示得知特征f的信息而使得类Y的信息的不确定性较少的程度.

    (Gain(D,f) = Ent(D) - sum_{i=1}^{n} frac{|D_i|}{|D|}Ent(D_i))

    信息增益越大,特征划分效果越好. 信息增益指标,趋向于选择取值数目多的特征.[个人观点:特征取值越多,划分到每个子节点的数据越少,一定程度上,纯度越高,混乱程度越低,熵取值越小,进而,信息增益越大.比如说,ID特征,因为ID是唯一的,所有划分到每个ID取值节点上也就一个数据点,纯度100%,熵为0.]

    信息增益比率

    (GainRatio(D,f)=frac{Gain(D,f)}{IV(f)})

    其中,
    (IV(f) = -sum_{v=1}^{V}frac{|D_v|}{|D|}log_2frac{|D_v|}{|D|})

    (D_v)表示特征f取值为v的数据子集.

    因为信息增益会倾向于选择特征取值多的特征,所以,我们对多取值特征进行惩罚,除以特征f的固有值[或者说特征f的信息熵,f的信息熵越大,相应f的取值情况越多,惩罚力度越大].

    Gini指数

    假设数据集D有K个类,样本点属于第k类的概率为pk,则概率分布的基尼指数定义为:

    (Gini(D)=sum_{k=1}^Kp_k(1-p_k) =1 - sum_{k=1}^Kp_k^2)

    知道了gini指数的计算公式,计算划分前的gini指数,划分后,计算各个节点的gini指数值,然后根据划分后子节点的数据比例进行加权求和,得到划分后的总gini指数,最后对两次结果做差,得到特征f的划分效果, 差值越大,分类效果越好.

    均方差MSE[和,不平均]

    和分类时相似,计算划分前节点的均方差,划分后计算子节点的均方差,依据数据比例加权平均,再计算两次结果差值,差值越大越好.

    MAE也可以用作特征选择指标,和MSE类似.

    决策树生成

    决策树本质上也是一棵树,所以符合数据结构中树的一般性构造过程,也就是递归.

    既然是递归构建过程,首先要明白的是递归终止条件,否则就会陷入死循环.那么决策树的终止条件是什么呢?决策树中符合终止条件时,停止继续划分,生成叶节点.

    如果是分类树:

    1. 如果节点数据全是同一类别,停止递归[没有必要了,都是自己人];
    2. 如果特征列表为空,停止递归[在分类问题中,一般情况下,每种划分特征只会用一次,用完就扔了---负心汉];
    3. 如果所有样本在所有特征上取值都相同,停止递归[特征没用,不具有区分度---所有特征上取值都相同,千篇一律]

    如果是回归树,回归树通常会设定自定义的参数,比如均方差变化最小值,每个节点容忍的最小样本数,相应的条件:

    1. 均方差变化太小[小于预定义的阈值];
    2. 划分后节点的样本量太少[小于预定义的阈值,比如只有2,3个,小猫两三只没有必要继续划分了];
    [终止条件]检测数据集中的每个子项是否属于同一分类,or 特征集为空:
    
        If so:  return  类标签
    
        Else:
            寻找划分数据集的最好特征(--基于信息增益)
            划分数据集
            创建分支结点
                for    每个划分的子集
                    调用自己,并增加返回结果到分支结点中
    
            return    分支结点
    

    上面伪代码中存在一个问题, 类标签怎么确定?
    如果叶子节点都属于同一类别,那么给定所属类别即可;如果叶子节点数据属于不同的类别,大家进行投票决定,服从多数人的利益[少数服从多数].

    树剪枝

    因为在决策树的构建过程中,可能会存在过拟合现象,或者说决策树深度太深,太过于复杂;因此,我们可以对决策树进行剪枝处理.剪枝又分为预剪枝和后剪枝.

    预剪枝是指在决策树生成过程中,对每个节点在划分前先进行估计,如果当前的划分不能带来决策树泛化性能的提升[泛化性能可以用错误率,或者说均方差衡量],则停止划分将当前节点标记为叶节点.

    后剪枝过程是一个不断尝试的过程:找到叶子节点,尝试合并[将叶子节点的双亲变成叶子节点],比较合并前后的变化效果.变化效果需要定量分析,这个数据量指标分类问题可以使用错误率,回归树可以使用均方差, 而指标的计算需要数据,因此我们需要一定的测试数据,然后使用测试数据在已经生成的决策树上进行不断测试,假如合并后比合并前效果好,分类问题上就是错误率降低了,回归问题上均方差减少了,我们就进行合并处理[或者说是剪枝处理].

    其他问题

    决策树使用范围,或者说对数据集的要求: 标称数据或数值型数据.本质上,决策树只适用于标称型数据[也就是离散数据],但如果是连续数据[在特征取值上连续],我们需要进行离散处理.不同类型的决策树处理问题不同,有的决策树需要对数据进行预先离散化处理;但有的决策树本身可以处理连续数据.

    决策树在生成过程中会遇到各种各样的问题.有数据集的问题,也有决策树本身的问题,而决策树本身也有自己的适用范围,不可能适用于所有问题[一招鲜吃遍天impossible].比如说:

    • 连续数据: 离散化处理;
    • 空缺数据: 如果在某个特征上数据存在空缺值,怎么处理? 我们可以先将取特征上非空的数据子集,当做非空数据处理,然后将特征取值为空记录按照子节点数据的比率划分到所有子节点上.
    • etc.

    具体问题具体分析,依据不同的任务,数据集的不同特点选择适合的算法模型.

    代码实现

    repository 欢迎fork,star.

  • 相关阅读:
    codeforce1029B B. Creating the Contest(简单dp,简单版单调栈)
    spfa算法
    spfa算法
    HDU King (非连通图的差分约束,经典好题)
    HDU King (非连通图的差分约束,经典好题)
    差分约束系统相关证明(存在负环则无解证明)
    Java API 读取HDFS的单文件
    採用邻接矩阵创建图
    旧金山攻略
    一个jeecg整合activiti的学习样例,源代码下载
  • 原文地址:https://www.cnblogs.com/ysugyl/p/10016461.html
Copyright © 2011-2022 走看看