美文网首页机器学习
机器学习之决策树ID3/C4.5/CART学习算法比较

机器学习之决策树ID3/C4.5/CART学习算法比较

作者: 郑壮杰 | 来源:发表于2019-01-13 16:42 被阅读0次
    一、概述
    • 决策树是机器学习中最基础、应用最广泛的算法模型,常用于解决分类和回归问题。
    • 决策树的构建是一种自上而下的递归分裂学习方法,其学习的关键在于如何选择最优划分属性。一般情况下,随着划分过程不断进行,决策树的分支结点所包含的样本会尽可能属于同一类别,即结点的纯度(purity)越来越高。
    • 度量样本集合纯度有三种常用的评估准则:ID3、C4.5和CART。本文将从构造、应用和实现三个角度,对比这三种模型的异同点。
    二、决策树学习算法
    2.1 相亲数据集
    编号 年龄 长相 工资 编程 类别
    1 不会 不见
    2 年轻 一般 中等
    3 年轻 不会 不见
    4 年轻 一般
    5 年轻 一般 不会 不见
    2.2 ID3(Iterative Dichotomiser 3)--信息增益

      信息熵(information entropy)是度量样本集合纯度最常用的一种指标。对于样本集合D,类别数为K,信息熵定义为:
    H(D)=-\sum_{k=1}^K\frac{|C_k|}{|D|}\log_2\frac{|C_k|}{|D|}
      其中,C_k是样本集合D中属于第k(k=1,2,3...K)类的样本子集,|C_k|表示该子集的元素个数,|D|表示样本集合的元素个数。特征属性A的条件熵H(D|A)定义为:
    H(D|A)=\sum_{i=1}^n\frac{|D_i|}{|D|}H(D_i)=\sum_{i=1}^n\frac{|D_i|}{|D|}(-\sum_{k=1}^K\frac{|D_{ik}|}{|D_i|}\log_2\frac{|D_{ik}|}{|D_i|})
      其中,|D_i|表示D中特征A取第i个值的样本子集,D_{ik}表示D_i中属于第k类的样本子集。因此,特征A的信息增益等于两者之差:
    g(D,A)=H(D)-H(D|A)
      以表2.1中相亲数据为例,该数据包含5个样本集,正样本占比\frac{2}{5},负样本占比\frac{3}{5}。于是,根据公式计算出根节点的信息熵为:
    H(D)=-\frac{3}{5}\log_2\frac{3}{5}-\frac{2}{5}\log_2\frac{2}{5}=0.971
      然后,计算当前属性集合{年龄,长相,工资,编程}中每个属性的条件熵。以属性“年龄”为例,它有2个可能的取值:{老,年轻}。若使用该属性对D进行划分,则可得到2个子集,分别为:D_1(年龄=老),D_2(年龄=年轻)。

    • 子集D_1包含编号{1}的1个样例,其中正样本占比p_1=\frac{0}{1},负样本占比p_2=\frac{1}{1}
    • 子集D_2包含编号{2,3,4,5}的4个样例,其中正样本占比p_1=\frac{2}{4},负样本占比p_2=\frac{2}{4}
      根据公式计算出属性=年龄的条件熵为:
      H(D|年龄)=\frac{1}{5}H(老)+\frac{4}{5}H(年轻)=\frac{1}{5}(-0)+\frac{4}{5}(-\frac{2}{4}\log_2\frac{2}{4}-\frac{2}{4}\log_2\frac{2}{4})=0.8
      依此类推:
      H(D|长相)=\frac{1}{5}H(帅)+\frac{3}{5}H(一般)+\frac{1}{5}H(丑)=0+\frac{3}{5}(-\frac{2}{3}\log_2\frac{2}{3}-\frac{1}{3}\log_2\frac{1}{3})+0=0.551
      H(D|工资)=\frac{3}{5}H(高)+\frac{1}{5}H(中等)+\frac{1}{5}H(低)=\frac{3}{5}(-\frac{2}{3}\log_2\frac{2}{3}-\frac{1}{3}\log_2\frac{1}{3})+0+0=0.551
      H(D|编程)=\frac{3}{5}H(不会)+\frac{2}{5}H(会)=\frac{3}{5}(0)+\frac{2}{5}(0)=0
      每个属性对应的信息增益为:
      g(D,年龄)=0.171,g(D,长相)=0.42,g(D,工资)=0.42,g(D,编程)=0.971
        由此可得,特征“编程”的信息增益最大,使用特征“编程”来进行划分所得的纯度提升越大。图2.1给出了基于“编程”对根节点进行划分的结果:
      图2.1 基于编程属性对根节点划分
        然后,决策树学习算法对每个分支节点做进一步划分。以图2.1中第一个分支节点(编程=会)为例,该节点包含的样本集合D_1有{2,4}两个样本,可用的属性集合有{年龄,长相,工资},基于D_1计算出各属性的信息增益,继续划分树节点,直到满足停止分裂的条件。
        最后,ID3对取值较多的特征有所偏好,特征取值越多意味着确定性越高,也就是条件熵越小,信息增益越大。如果将前面的编号也作为一个划分属性,其信息增益为0.971,它将产生5个分支,每个分支结点仅包含一个样本,显然这样划分出来的决策树不具备泛化能力,无法对新样本进行有效预测。因此,C4.5对ID3进行优化,通过引入信息增益比,对取值较多的特征进行惩罚,避免出现过拟合的特性,提升决策树的泛化能力。

    信息熵和条件熵计算的scala-spark实现:

    /**
        * 计算信息熵
        *
        * @param df
        * @param column
        * @return
        */
      def calculate(df: DataFrame, column: String = "label"): Double = {
        val counts = df.select(column).groupBy(column).agg(count(column)).collect().map(row => row.getLong(1))
        val totalCount = counts.sum.toDouble
        if (totalCount == 0) {
          return 0
        }
        counts.map {
          count =>
            var impurity = 0.0
            if (count != 0) {
              val freq = count / totalCount
              impurity -= freq * log2(freq)
            }
            impurity
        }.reduce((v1, v2) => v1 + v2)
      }
    
      /**
        * 计算每个特征的条件熵
        *
        * @param df
        * @param column
        * @return
        */
      def calculateFeature(df: DataFrame, column: String): Double = {
        val counts = df.select(column).groupBy(column).agg(count(column)).collect()
        val totalCount = counts.map(row => row.getLong(1)).sum.toDouble
        if (totalCount == 0) {
          return 0
        }
        val impurity = counts.map {
          row =>
            val featureValue = row.get(0).toString.toDouble
            val featureCount = row.getLong(1)
            val freq = featureCount / totalCount
            val tmp = df.filter(col(column) === featureValue)
            freq * calculate(tmp, "label")
        }.reduce((v1, v2) => v1 + v2)
        impurity
      }
    
    2.3 C4.5--信息增益比

      特征A对于数据集D的信息增益比定义为:
    g_R(D,A)=\frac{g(D,A)}{H_A(D)}
    其中
    H_A(D)=-\sum_{i=1}^n\frac{|D_i|}{|D|}\log_2\frac{|D_i|}{|D|}
    称为数据集D关于A的取值熵。因此,可以根据上面的公式求出每个特征的取值熵:
    H_{年龄}(D)=-\frac{1}{5}\log_2\frac{1}{5}-\frac{4}{5}\log_2\frac{4}{5}=0.722
    H_{长相}(D)=-\frac{1}{5}\log_2\frac{1}{5}-\frac{3}{5}\log_2\frac{3}{5}-\frac{1}{5}\log_2\frac{1}{5}=1.371
    H_{工资}(D)=-\frac{3}{5}\log_2\frac{3}{5}-\frac{1}{5}\log_2\frac{1}{5}-\frac{1}{5}\log_2\frac{1}{5}=1.371
    H_{编程}(D)=-\frac{3}{5}\log_2\frac{3}{5}-\frac{2}{5}\log_2\frac{2}{5}=0.971
    最终可计算出各个特征的信息增益比:
    g_R(D,年龄)=\frac{g(D,年龄)}{H_{年龄}(D)}=\frac{0.171}{0.722}=0.2368
    g_R(D,长相)=\frac{g(D,长相)}{H_{长相}(D)}=\frac{0.42}{1.371}=0.3063
    g_R(D,工资)=\frac{g(D,工资)}{H_{工资}(D)}=\frac{0.42}{1.371}=0.3063
    g_R(D,编程)=\frac{g(D,编程)}{H_{编程}(D)}=\frac{0.971}{0.971}=1
    通过信息增益比,特征年龄对应的指标上升了,而特征长相和工资有所下降。

    2.4 CART--基尼指数(Gini)

      CART决策树使用基尼指数来选择划分属性,Gini描述的是数据的纯度,其定义为:
    Gini(D)=1-\sum_{k=1}^n(\frac{|C_k|}{|D|})^2
      其中,C_k是样本集合D中属于第k(k=1,2,3...K)类的样本子集,|C_k|表示该子集的元素个数,|D|表示样本集合的元素个数。如果所有样本都属于同一个类别,则|C_k|=|D|Gini(D)=0,此时impurity最小。CART利用基尼指数构造二叉决策树。如果特征是离散型变量,将样本按特征A的取值切分成两份;如果特征是连续型变量,CART的处理方式和C4.5相同,先将特征值进行升序排序,然后把左边第一个值(index=1)作为一个分类,右边其他值作为另一个分类,计算其Gini指数,然后移动index的位置,直到计算完所有的分类结果,然后选取Gini最小的位置对应的index作为切分点。特征A的Gini指数定义为:
    Gini(D|A)=\sum_{i=1}^n\frac{|D_i|}{|D|}Gini(D_i)
    当n=2时,该公式可以简化为:
    Gini(D|A)=\frac{|D_1|}{|D|}Gini(D_1) + \frac{|D_2|}{|D|}Gini(D_2)

    使用CART分类准则,选取年龄维度,把老作为特征标签,那么年轻就被划分到另外一类

    老(总数=1) 年轻(总数=4)
    类别 不见 见、不见、见、不见

    Gini(D|年龄=老)=\frac{1}{5}(1-(\frac{1}{1})^2-(\frac{0}{1})^2)+\frac{4}{5}(1-(\frac{1}{2})^2-(\frac{1}{2})^2)=0.4
    Gini(D|年龄=年轻)=\frac{1}{5}(1-(\frac{1}{1})^2-(\frac{0}{1})^2)+\frac{4}{5}(1-(\frac{1}{2})^2-(\frac{1}{2})^2)=0.4

    帅(总数=1) 一般、丑(总数=4)
    类别 不见 见、不见、见、不见

    Gini(D|长相=帅)=\frac{1}{5}(1-(\frac{1}{1})^2-(\frac{0}{1})^2)+\frac{4}{5}(1-(\frac{1}{2})^2-(\frac{1}{2})^2)=0.4
    Gini(D|长相=丑)=\frac{1}{5}(1-(\frac{1}{1})^2-(\frac{0}{1})^2)+\frac{4}{5}(1-(\frac{1}{2})^2-(\frac{1}{2})^2)=0.4

    一般(总数=3) 帅、丑(总数=2)
    类别 见、不见 不见

    Gini(D|长相=一般)=\frac{3}{5}(1-(\frac{2}{3})^2-(\frac{1}{3})^2)+\frac{2}{5}(1-(\frac{1}{2})^2-(\frac{1}{2})^2)=0.47

    高(总数=3) 中等、低(总数=2)
    类别 见、不见 见、不见

    Gini(D|工资=高)=\frac{3}{5}(1-(\frac{2}{3})^2-(\frac{1}{3})^2)+\frac{2}{5}(1-(\frac{1}{2})^2-(\frac{1}{2})^2)=0.47

    会(总数=2) 不会(总数=3)
    类别 不见

    Gini(D|编程=会)=\frac{2}{5}(1-(\frac{2}{2})^2)+\frac{3}{5}(1-(\frac{3}{3})^2)=0
    因此,特征编程的Gini指数最小,选择该特征作为最优的切分点。

    三、小结

      通过比较ID3、C4.5和CART三种决策树的构造准则,在同一个样本集上,表现出不同的划分行为。

    • ID3和C4.5在每个结点上可以产生多个分支,而CART每个结点只会产生两个分支
    • C4.5通过引入信息增益比,弥补了ID3在特征取值比较多时,由于过拟合造成泛化能力变弱的缺陷
    • ID3只能处理离散型变量,而C4.5和CART可以处理连续型变量
    • ID3和C4.5只能用于分类任务,而CART可以用于分类和回归任务

    参考文献:
    [1]诸葛越,葫芦娃.百面机器学习
    [2]周志华.机器学习

    相关文章

      网友评论

        本文标题:机器学习之决策树ID3/C4.5/CART学习算法比较

        本文链接:https://www.haomeiwen.com/subject/imuqdqtx.html