1. 引言

    决策树(decision tree)是一种基本的分类和回归方法,由于其采用的是一种树形的结构,因此,具有很强的解释性和计算速度,也正是因为这些特点,使得决策树在很多行业都得到了应用,比如风控行业等。决策树的建模过程一般分为三个步骤:特征选择、决策树的生成和决策树的剪枝,根据这三个步骤所采用的规则,衍生出了很多不同的模型,比较经典的有Quinlan在1986年提出的ID3算法和1993年提出的C4.5算法,以及Breiman等人在1984年提出的CART算法,本文将以分类决策树为例,对这几个算法分别进行介绍,并用python进行实现。

2. 常用决策树模型介绍

2.1 决策树的定义

    决策树是由结点和有向边组成的树形结构,其中,结点包含两种类型:内部结点和叶结点。内部结点表示一个特征或者属性,叶结点则表示一个类。如下图所示,其中每个圆圈表示内部结点,每个正方形表示叶结点。

Python决策树分支图 python决策树模型_结点


    对于给定的训练数据集Python决策树分支图 python决策树模型_Python决策树分支图_02,其中,Python决策树分支图 python决策树模型_Python决策树分支图_03表示输入的特征向量,Python决策树分支图 python决策树模型_决策树_04为特征的个数,Python决策树分支图 python决策树模型_Python决策树分支图_05为类别标记,Python决策树分支图 python决策树模型_特征选择_06表示类别的个数,Python决策树分支图 python决策树模型_Python决策树分支图_07表示训练集的大小。决策树的思想大致如下:

  1. 首先,构建根结点,然后将整个训练集都放在根结点。
  2. 接着,从所有特征中选择一个最优特征,并根据该特征将训练数据集分割为多个子集,使得每一个子集有一个当前条件下的最好分类,如果某个子集已经基本分类正确,则将其作为叶结点,其对应的类别作为该叶结点的类别,否则,对每个子集继续选择最优的特征进行分割,如此递归下去,直到所有的子集基本被正确分类为止。最后,每个叶结点都代表一个子集,也是特征空间中的一个子区域,每个子区域之间都是不相交的。
  3. 最后,由于第二步为了将训练集划分正确,往往构建的决策树会过于庞大,这时,模型可能会出现过拟合,导致对新的测试数据可能分类效果不好,因此,需要对决策树自下而上进行剪枝,去掉一些过于细分的叶结点,使其回退到父结点或者更高的结点,然后将父结点或者更高的结点作为新的叶结点。

Python决策树分支图 python决策树模型_决策树_08进行预测时,会根据决策树的分支情况,将实例Python决策树分支图 python决策树模型_决策树_08划分到其归属的叶结点,并将该叶结点对应的类别作为实例Python决策树分支图 python决策树模型_决策树_08的预测类别,从而达到分类的效果。下面,我们将根据决策树的三个步骤,对各个算法的思想进行介绍和对比。

2.2 ID3算法

适用场景:特征和目标变量都是离散型

2.2.1 特征选择——信息增益

    特征选择是指决策树在每一次分支时,从所有的特征中选择能够对当前数据集具有最优分类能力的特征,这样可以提高模型的学习效率。ID3决策树的特征选择采用的是信息增益的方法。在介绍信息增益的概念之前,需要先介绍一下条件熵的概念。

Python决策树分支图 python决策树模型_决策树_11是一个取有限个值的离散随机变量,则其熵的计算公式如下:
Python决策树分支图 python决策树模型_Python决策树分支图_12其中,Python决策树分支图 python决策树模型_Python决策树分支图_13表示Python决策树分支图 python决策树模型_决策树_11取某个类别时的概率,当Python决策树分支图 python决策树模型_结点_15时,定义Python决策树分支图 python决策树模型_Python决策树分支图_16,由于熵只依赖于Python决策树分支图 python决策树模型_决策树_11的分布,因此,也可以将Python决策树分支图 python决策树模型_决策树_11的熵记作Python决策树分支图 python决策树模型_特征选择_19,即
Python决策树分支图 python决策树模型_Python决策树分支图_20从熵的计算公式可以发现,当随机变量的不确定性越大时,熵的值会越大,其取值范围为:
Python决策树分支图 python决策树模型_决策树_21

Python决策树分支图 python决策树模型_决策树_11的条件下随机变量Python决策树分支图 python决策树模型_结点_23的不确定性,其计算公式如下:
Python决策树分支图 python决策树模型_Python决策树分支图_24其中,Python决策树分支图 python决策树模型_Python决策树分支图_13

Python决策树分支图 python决策树模型_决策树_11的信息而使得类Python决策树分支图 python决策树模型_结点_23的信息的不确定性减少的程度。其计算公式如下:
Python决策树分支图 python决策树模型_特征选择_28当信息增益越大时,表示给定Python决策树分支图 python决策树模型_决策树_11后,对Python决策树分支图 python决策树模型_结点_23进行分类后的不确定性越低,也就是说Python决策树分支图 python决策树模型_决策树_11Python决策树分支图 python决策树模型_结点_23的分类能力越强。因此,ID3在每一次分支时,采用信息增益作为每个结点特征选择的规则。

2.2.2 ID3决策树的构造

    ID3算法构造决策树的思想大致如下:首先从根结点开始,对结点,对结点计算所有可能特征的信息增益,选择信息增益最大的特征作为结点的特征,由该特征的不同取值建立子结点,再对子结点递归地调用以上方法,构建决策树,直到所有特征的信息增益均很小或没有特征可以选择为止,最终得到一个决策树。其具体的算法步骤如下:

  1. 给定训练数据集Python决策树分支图 python决策树模型_Python决策树分支图_33,特征集Python决策树分支图 python决策树模型_结点_34,阈值Python决策树分支图 python决策树模型_Python决策树分支图_35;
  2. Python决策树分支图 python决策树模型_Python决策树分支图_33中所有实例属于同一类Python决策树分支图 python决策树模型_Python决策树分支图_37,则T为单结点树,并将类Python决策树分支图 python决策树模型_Python决策树分支图_37作为该结点的类标记,返回决策树Python决策树分支图 python决策树模型_结点_39;
  3. Python决策树分支图 python决策树模型_特征选择_40,则Python决策树分支图 python决策树模型_结点_39为单结点树,并将Python决策树分支图 python决策树模型_Python决策树分支图_33中实例数最大的类Python决策树分支图 python决策树模型_Python决策树分支图_37作为该结点的类标记,返回决策树Python决策树分支图 python决策树模型_结点_39
  4. 否则,计算Python决策树分支图 python决策树模型_结点_34中各特征对Python决策树分支图 python决策树模型_Python决策树分支图_33的信息增益,选择信息增益最大的特征Python决策树分支图 python决策树模型_特征选择_47
  5. 如果Python决策树分支图 python决策树模型_特征选择_47的信息增益小于阈值Python决策树分支图 python决策树模型_Python决策树分支图_35,则Python决策树分支图 python决策树模型_结点_39为单结点树,并将Python决策树分支图 python决策树模型_Python决策树分支图_33中实例数最大的类Python决策树分支图 python决策树模型_Python决策树分支图_37作为该结点的类标记,返回决策树Python决策树分支图 python决策树模型_结点_39;
  6. 否则,对Python决策树分支图 python决策树模型_特征选择_47的每一可能值Python决策树分支图 python决策树模型_结点_55,依Python决策树分支图 python决策树模型_决策树_56Python决策树分支图 python决策树模型_Python决策树分支图_33分割为若干非空子集Python决策树分支图 python决策树模型_特征选择_58,将Python决策树分支图 python决策树模型_特征选择_58中实例数最大的类作为标记,构建子结点,由结点及其子结点构成树Python决策树分支图 python决策树模型_结点_39,返回Python决策树分支图 python决策树模型_结点_39
  7. 对第Python决策树分支图 python决策树模型_决策树_62个子结点,以Python决策树分支图 python决策树模型_特征选择_58为训练集,以Python决策树分支图 python决策树模型_决策树_64为特征集,递归地调用2~6步,得到子树Python决策树分支图 python决策树模型_结点_65,返回Python决策树分支图 python决策树模型_结点_65

以上就是ID3决策树的构造过程,但是该过程构建的决策树往往会出现过拟合,因此,需要对树进行剪枝。

2.2.3 ID3决策树的剪枝

Python决策树分支图 python决策树模型_结点_67Python决策树分支图 python决策树模型_决策树_68Python决策树分支图 python决策树模型_结点_69是树Python决策树分支图 python决策树模型_结点_67的某个叶结点,该叶结点有Python决策树分支图 python决策树模型_Python决策树分支图_71个样本点,其中Python决策树分支图 python决策树模型_结点_72类的样本点有Python决策树分支图 python决策树模型_特征选择_73个,Python决策树分支图 python决策树模型_Python决策树分支图_74Python决策树分支图 python决策树模型_Python决策树分支图_75为叶结点Python决策树分支图 python决策树模型_结点_69上的经验熵,\alpha \geqslant 0为惩罚参数,则决策树的损失函数可以定义为:
Python决策树分支图 python决策树模型_决策树_77其中,经验熵为:
Python决策树分支图 python决策树模型_决策树_78将损失函数中的第一项记作:
Python决策树分支图 python决策树模型_Python决策树分支图_79则损失函数可以表达为:
Python决策树分支图 python决策树模型_结点_80其中,Python决策树分支图 python决策树模型_特征选择_81表示模型对训练数据的预测误差,即模型对训练数据的拟合程度,Python决策树分支图 python决策树模型_决策树_68表示模型的复杂度,参数Python决策树分支图 python决策树模型_结点_83则表示惩罚参数,当Python决策树分支图 python决策树模型_结点_83越大时,则会选择越简单的树,反之,则选择较复杂的树。可以看出,决策树的剪枝不仅考虑模型的拟合程度,还考虑模型的复杂度,因此,相比决策树的构造过程,决策树的剪枝过程是一个全局优化的过程。决策树的剪枝步骤具体如下:

  1. 给定ID3算法生成的决策树Python决策树分支图 python决策树模型_结点_39,参数Python决策树分支图 python决策树模型_结点_86;
  2. 递归地从树的叶结点向上回缩,设一组叶结点回缩到其父结点之前与之后的整体树分别为Python决策树分支图 python决策树模型_特征选择_87Python决策树分支图 python决策树模型_决策树_88,其对应的损失函数值分别为Python决策树分支图 python决策树模型_Python决策树分支图_89Python决策树分支图 python决策树模型_结点_90,如果Python决策树分支图 python决策树模型_Python决策树分支图_91,则进行剪枝,将其父结点变为新的叶结点。
  3. 重复步骤2,直到不能继续为止,此时得到损失函数最小的子树Python决策树分支图 python决策树模型_决策树_92

以上就是关于ID3算法的整个过程,下面介绍一个与ID3算法非常接近的决策树算法,即C4.5。

2.3 C4.5算法

适用场景:特征和目标变量都是离散型

2.3.1 特征选择——信息增益比

    ID3选择的信息增益是一个绝对值的概念,对于不同的数据集,信息增益值往往不一样,对于分类问题困难时,其经验熵比较大,对应的信息增益值也会比较大,反之则比较小,因此,为了克服这个问题,C4.5对ID3算法的特征选择准则进行了改进。C4.5选取的特征选择准则是信息增益比,其定义就是将信息增益Python决策树分支图 python决策树模型_特征选择_93与训练数据集Python决策树分支图 python决策树模型_决策树_94的经验熵Python决策树分支图 python决策树模型_决策树_95之比,其计算公式如下:
Python决策树分支图 python决策树模型_决策树_96

2.3.2 C4.5决策树的构造

     C4.5算法构造决策树的过程与ID3类似,只是将特征选择准则改为信息增益比,其他的都是一样的。

  1. 给定训练数据集Python决策树分支图 python决策树模型_Python决策树分支图_33,特征集Python决策树分支图 python决策树模型_结点_34,阈值Python决策树分支图 python决策树模型_Python决策树分支图_35;
  2. Python决策树分支图 python决策树模型_Python决策树分支图_33中所有实例属于同一类Python决策树分支图 python决策树模型_Python决策树分支图_37,则T为单结点树,并将类Python决策树分支图 python决策树模型_Python决策树分支图_37作为该结点的类标记,返回决策树Python决策树分支图 python决策树模型_结点_39;
  3. Python决策树分支图 python决策树模型_特征选择_40,则Python决策树分支图 python决策树模型_结点_39为单结点树,并将Python决策树分支图 python决策树模型_Python决策树分支图_33中实例数最大的类Python决策树分支图 python决策树模型_Python决策树分支图_37作为该结点的类标记,返回决策树Python决策树分支图 python决策树模型_结点_39
  4. 否则,计算Python决策树分支图 python决策树模型_结点_34中各特征对Python决策树分支图 python决策树模型_Python决策树分支图_33的信息增益比,选择信息增益比最大的特征Python决策树分支图 python决策树模型_特征选择_47
  5. 如果Python决策树分支图 python决策树模型_特征选择_47的信息增益比小于阈值Python决策树分支图 python决策树模型_Python决策树分支图_35,则Python决策树分支图 python决策树模型_结点_39为单结点树,并将Python决策树分支图 python决策树模型_Python决策树分支图_33中实例数最大的类Python决策树分支图 python决策树模型_Python决策树分支图_37作为该结点的类标记,返回决策树Python决策树分支图 python决策树模型_结点_39;
  6. 否则,对Python决策树分支图 python决策树模型_特征选择_47的每一可能值Python决策树分支图 python决策树模型_结点_55,依Python决策树分支图 python决策树模型_决策树_56Python决策树分支图 python决策树模型_Python决策树分支图_33分割为若干非空子集Python决策树分支图 python决策树模型_特征选择_58,将Python决策树分支图 python决策树模型_特征选择_58中实例数最大的类作为标记,构建子结点,由结点及其子结点构成树Python决策树分支图 python决策树模型_结点_39,返回Python决策树分支图 python决策树模型_结点_39
  7. 对第Python决策树分支图 python决策树模型_决策树_62个子结点,以Python决策树分支图 python决策树模型_特征选择_58为训练集,以Python决策树分支图 python决策树模型_决策树_64为特征集,递归地调用2~6步,得到子树Python决策树分支图 python决策树模型_结点_65,返回Python决策树分支图 python决策树模型_结点_65
2.3.3 C4.5决策树的剪枝

    C4.5决策树的剪枝与ID3算法的一样,这里不再具体赘述。

2.4 CART算法

适用场景:支持数值型和离散型变量,支持分类和回归问题

2.4.1 特征选择——MSE或基尼指数

Python决策树分支图 python决策树模型_特征选择_06个类,样本点属于第Python决策树分支图 python决策树模型_结点_72类的概率为Python决策树分支图 python决策树模型_Python决策树分支图_133,则概率分布的基尼指数的定义为:
Python决策树分支图 python决策树模型_结点_134如果样本集合Python决策树分支图 python决策树模型_决策树_94根据特征Python决策树分支图 python决策树模型_Python决策树分支图_136是否取某一可能值Python决策树分支图 python决策树模型_结点_137被分割成Python决策树分支图 python决策树模型_结点_138Python决策树分支图 python决策树模型_决策树_139两部分,即:
Python决策树分支图 python决策树模型_结点_140则在特征Python决策树分支图 python决策树模型_Python决策树分支图_136的条件下,集合Python决策树分支图 python决策树模型_决策树_94的基尼指数定义为:
Python决策树分支图 python决策树模型_决策树_143当基尼指数越大时,表示数据的不确定性越大,因此,CART分类树每次分支时,选择当前基尼指数Python决策树分支图 python决策树模型_Python决策树分支图_144最小的特征作为当前结点的特征选择。

2.4.2 CART决策树的构造

    (一) 回归树的构造

Python决策树分支图 python决策树模型_决策树_11Python决策树分支图 python决策树模型_结点_23分别为输入和输出变量,并且Python决策树分支图 python决策树模型_结点_23是连续变量,给定训练数据集:
Python决策树分支图 python决策树模型_决策树_148则回归树在每次分支时,会依次从特征集中选择第Python决策树分支图 python决策树模型_决策树_149个变量Python决策树分支图 python决策树模型_结点_150和它取的值Python决策树分支图 python决策树模型_Python决策树分支图_151,作为切分变量和切分点,并定义两个区域:
Python决策树分支图 python决策树模型_结点_152然后计算两个区域中Python决策树分支图 python决策树模型_结点_23的均值分别作为两个区域的预测值Python决策树分支图 python决策树模型_Python决策树分支图_154Python决策树分支图 python决策树模型_结点_155,接着,计算两个区域的平方误差和,并从中选择可以平方误差和最小的变量和切分点作为当前的最优切分变量Python决策树分支图 python决策树模型_决策树_149和最优切分点Python决策树分支图 python决策树模型_Python决策树分支图_151,具体地,求解:
Python决策树分支图 python决策树模型_Python决策树分支图_158重复以上划分过程,直到满足停止条件为止,这样便形成了一棵回归树,这样的回归树通常称为最小二乘回归树。具体的算法步骤如下:

  1. 输入训练数据集Python决策树分支图 python决策树模型_Python决策树分支图_33;
  2. 遍历变量Python决策树分支图 python决策树模型_Python决策树分支图_160,求解:
    Python决策树分支图 python决策树模型_决策树_161确定使得上式达到最小值的最优切分变量Python决策树分支图 python决策树模型_Python决策树分支图_160和最优切分点Python决策树分支图 python决策树模型_决策树_163
  3. 用选定的最小值对Python决策树分支图 python决策树模型_结点_164划分区域并决定相应的输出值:
  4. 继续对两个子区域调用步骤2、3,直至满足停止条件;
  5. 将输入空间h划分为Python决策树分支图 python决策树模型_Python决策树分支图_165区域Python决策树分支图 python决策树模型_决策树_166,生成决策树:
    Python决策树分支图 python决策树模型_结点_167

    (二) 分类树的构造

    分类树则采用基尼指数选择最优特征,其算法步骤如下:

  1. 输入训练数据集D;
  2. 从根结点开始,计算现有特征Python决策树分支图 python决策树模型_结点_34取每个可能值Python决策树分支图 python决策树模型_特征选择_169时的基尼指数:
    Python决策树分支图 python决策树模型_决策树_170
  3. 选择基尼指数最小的特征及其对应的切分点作为最优特征和最优切分点,依最优特征和最优切分点,从现结点生成两个子结点,将训练集依特征分配到两个子结点中去;
  4. 对两个子结点递归地调用步骤2、3,直至满足停止条件为止;
  5. 生成CART决策树。
2.4.3 CART决策树的剪枝

Python决策树分支图 python决策树模型_决策树_171底端开始不断剪枝,直到Python决策树分支图 python决策树模型_决策树_171的根结点,形成一个子树序列Python决策树分支图 python决策树模型_特征选择_173;接着,通过交叉验证法在独立验证集上对子树序列进行测试,从中选择最优子树。

    从前面ID3算法我们可以知道,剪枝时的损失函数不仅考虑决策树对训练集的拟合程度,还考虑模型的复杂度,具体的公式如下:
Python决策树分支图 python决策树模型_结点_80CART首先从整体树Python决策树分支图 python决策树模型_决策树_171开始剪枝,对Python决策树分支图 python决策树模型_决策树_171的任意内部结点Python决策树分支图 python决策树模型_结点_69,以t为单结点树的损失函数是:
Python决策树分支图 python决策树模型_Python决策树分支图_178Python决策树分支图 python决策树模型_结点_69为根结点的子树Python决策树分支图 python决策树模型_Python决策树分支图_180的损失函数是:
Python决策树分支图 python决策树模型_决策树_181Python决策树分支图 python决策树模型_决策树_182时,即Python决策树分支图 python决策树模型_特征选择_183时,Python决策树分支图 python决策树模型_Python决策树分支图_184Python决策树分支图 python决策树模型_结点_69有相同的损失函数值,而Python决策树分支图 python决策树模型_结点_69的结点少,因此Python决策树分支图 python决策树模型_结点_69Python决策树分支图 python决策树模型_Python决策树分支图_180更可取,对Python决策树分支图 python决策树模型_Python决策树分支图_180进行剪枝。

Python决策树分支图 python决策树模型_决策树_171中每一内部结点Python决策树分支图 python决策树模型_结点_69,计算:
Python决策树分支图 python决策树模型_结点_192Python决策树分支图 python决策树模型_决策树_171中减去Python决策树分支图 python决策树模型_特征选择_194最小的Python决策树分支图 python决策树模型_Python决策树分支图_180,将得到的子树作为Python决策树分支图 python决策树模型_决策树_196,同时将最小的Python决策树分支图 python决策树模型_特征选择_194设为Python决策树分支图 python决策树模型_Python决策树分支图_198Python决策树分支图 python决策树模型_决策树_196为区间Python决策树分支图 python决策树模型_特征选择_200的最优子树,如此剪枝下去,直至根结点,在这一过程中,不断地增加Python决策树分支图 python决策树模型_结点_83值,产生新的区间。
    最后,利用独立的验证数据集,测试子树序列Python决策树分支图 python决策树模型_Python决策树分支图_202中各棵子树的平方误差或基尼指数,平方误差或基尼指数最小的子树即为最优的决策树,其所在的Python决策树分支图 python决策树模型_结点_83区间即为最终Python决策树分支图 python决策树模型_结点_83的取值。具体的剪枝算法步骤如下:

  1. 给定CART算法生成的决策树Python决策树分支图 python决策树模型_Python决策树分支图_205,初始化k=0,Python决策树分支图 python决策树模型_结点_206
  2. 自下而上地对各内部结点Python决策树分支图 python决策树模型_特征选择_207计算Python决策树分支图 python决策树模型_决策树_208Python决策树分支图 python决策树模型_Python决策树分支图_209以及Python决策树分支图 python决策树模型_特征选择_210其中,Python决策树分支图 python决策树模型_特征选择_211表示以Python决策树分支图 python决策树模型_特征选择_207为根结点的子树,Python决策树分支图 python决策树模型_决策树_213为对训练数据的预测误差,Python决策树分支图 python决策树模型_Python决策树分支图_209Python决策树分支图 python决策树模型_特征选择_211叶结点个数。
  3. 自上而下地访问内部结点Python决策树分支图 python决策树模型_特征选择_207,如果有Python决策树分支图 python决策树模型_特征选择_217,则进行剪枝,并对叶结点Python决策树分支图 python决策树模型_特征选择_207以多数表决法决定其类,得到树Python决策树分支图 python决策树模型_结点_39
  4. Python决策树分支图 python决策树模型_结点_220
  5. 如果Python决策树分支图 python决策树模型_结点_39不是由根结点单独构成的树,则回到步骤2
  6. 采用交叉验证法在子树序列Python决策树分支图 python决策树模型_结点_222中选取最优子树Python决策树分支图 python决策树模型_特征选择_223

3. 常用决策树模型的python实现

    python中sklearn主要支持的是CART决策树,因为CART可适用的场景更广,不过,特征选择的准则sklearn也提供了两种选择,一种是“entropy”,对应本文介绍的信息增益,另一种是“gini”,对应本文的基尼指数,本文直接继承了sklearn.tree中的DecisionTreeClassifier,增加了对决策树的绘制函数,python绘制决策树需要安装graphviz,安装后如果出现中文乱码的话,可以参考这篇文章《graphviz Windows中文乱码》。具体的代码如下:

import os
from sklearn.tree import DecisionTreeClassifier, export_graphviz


class DecisionTreeClassifier(DecisionTreeClassifier):
    def draw_tree(self, model, feature_names, save_path):
        """
        绘制决策树
        :param model: 决策树模型
        :param feature_names: 结点名称. [list]
        :param save_path: 文件保存路径
        :return:
        """
        # 生成决策树的路径dot文件,保存到save_path
        export_graphviz(model, out_file=save_path,
                        feature_names=feature_names,
                        filled=True, rounded=True,
                        special_characters=True)

        # 替换dot文件中的字体为Microsoft YaHei,以防止中文乱码
        with open(save_path, 'r', encoding='utf-8') as f:
            dot_data = f.read()

        dot_data = dot_data.replace('fontname=helvetica', 'fontname="Microsoft YaHei"')

        with open(save_path, 'w', encoding='utf-8') as f:
            f.write(dot_data)

        # 生成决策树图像,格式默认为png格式
        os.system('dot -Tpng {0} -o {1}'.format(save_path, save_path.replace('dot', 'png')))

    绘制的决策树图形大致如下:

Python决策树分支图 python决策树模型_结点_224


具体的项目代码还是参考本人的github地址:

4. 总结

    决策树由于其解释性强,计算速度快,非线性能力强,在一些对模型解释性强的行业得到了很多的应用,比如风控行业。另外,由于特征选择、决策树生成和决策树剪枝的不同,决策树衍生出了很多的算法,每个算法都有其对应的优缺点,因此,在使用时需要加以鉴别,比如ID3算法,由于不是二叉树的形式,因此该算法往往更倾向于选择类别多的特征。