决策树算法原理及实现

欢迎大家查看实现的完整代码。。。

决策树模型

    分类决策树模型是一种描述对实例进行分类的树形结构。决策树由结点和有向边组成。结点有两种类型:内部节点和叶节点,内部节点表示一个特征或属性,叶节点表示一个分类类别。
    分类的时候,从根节点开始,按照某种策略对实例的每一个特征进行测试,根据测试结果,将实例分配到其子结点;此时,每一个子结点对应着该特征的一个取值。如此递归向下移动,直至达到满足下面递归终止条件之一:

  1. 当前节点包含的所有样本全部属于同一类别;
  2. 当前节点的待选属性集为空集,或者是当前节点的所有样本在所有待选属性集上的取值一样。

对于第二种情形,将当前节点标记为叶节点,并将它的类别标记为所含样本最多的类别(各个类别所含样本数相等,则任意选择一个类别作为其类别)

数据集特征划分选择

    我们知道,对于当前的节点的所有待选的特征(属性)集A={A1,A2,A3},选择哪一个特征来划分当前数据集呢???直观上地,我们当然希望选择的这个特征将数据集划分到几个子集中,使得每一个子集尽可能的属于同一个类别,即,每一个子集的纯度(Purity)越高越好。这里我将介绍常见的三个量化指标,信息增益(Information Gain)信息增益率(Information Gain Ratio)基尼指数(Gini Index)
1. 信息增益
    信息增益是通过信息熵(更多关于它的介绍,看这里理论来度量样本集合纯度的一个指标,我们假定当前的样本集合为D,其中第k{1,2,,|Y|}个类别所占当前样本集合的比例为pk,那么当前样本集合的信息熵为,

Entropy(D)=k=1|Y|pklog2pk|Y|

很显然,这个值越小,则当前数据集的纯度就越高。
    我们假定当前待选属性集中某个属性AV个取值{A1,A2,,AV},那么我们选择用它来划分当前数据集,就会产生V个分支节点(子集),其中第v个分支节点为包含当前数据集D中所有在属性A上取值为Av的样本集合,记为,Dv,那么我们使用属性A来划分数据集D的信息增益为,
info_gain(D,A)=Entropy(D)v=1V|Dv||D|Entropy(Dv)
一般来说,信息增益越大,则使用属性A来划分数据集得到的子集,整体而言纯度就会越高,因此我们选择的属性就为,
A=argmaxAA info_gain(D,A)A
细心的你,可能发现了这种计算策略往往更加偏向于选择那些取值比较多的属性,也就是上面提到的V会比较大,因为这些属性天然的会将数据集划分为纯度都比较高的子集(如ID属性等),然而这样的决策树往往泛化能力较差,对未知数据不能准确预测。所以我们要对那些取值较多的属性在计算信息增益时进行改进
决策树算法原理及实现
2. 信息增益率
    在前面提到的信息增益的基础上,做出如下改进,
info_gain_ratio(D,A)=info_gain(D,A)HA(D)
其中,
HA(D)=v=1V|Dv||D|log2|Dv||D|
对于取值较多的属性AHA(D)的值就会较大,这符合我们的预期。然而,这种指标往往又会选择那些属性取值较少的属性,所以C4.5算法并没有直接选择那些信息增益率最大的划分属性,而是采用了一种折衷的方案,先找出信息增益高于平均水平的那些属性,然后再在这些属性中选择信息增益率最大的属性作为当前数据集的划分属性
决策树算法原理及实现
3. 基尼指数
    数据集的划分属性选择使用基尼指数(CART决策树)来计算,
gini(D)=k=1|Y|kkYpkpk=k=1|Y|pk(1pk)=1k=1|Y|pk2
直观地来看,基尼指数反映了从数据集中任意抽取两个样本,其类别不一样的概率,故,gini(D)越小,那么数据集的纯度就越高。因此属性A的基尼指数为,
gini_index(D,A)=v=1V|Dv||D|gini(Dv)
我们从待选属性集中选择的属性为,
A=argmaxAA gini_index(D,A)A

剪枝(Pruning)

    对于某些决策树可能过拟合,泛化误差比较大,那么我们可以适当的剪去某些节点来降低过拟合的风险。
    一般地,有两种剪枝策略,预剪枝(Prepruning)后剪枝(Post-pruning), 顾名思义,预剪枝就是在决策树的生成过程中,在每一个节点通过某种选择策略选择某个属性划分数据集,我们计算在划分后决策树的泛化性能(测试误差)是否有提升来决定当前节点是否需要划分其子节点(没有泛化性能提升,则将当前节点直接标记为叶节点);后剪枝就是从训练集已经训练出了一棵完整的决策树,然后我们对树中每一个非叶子节点进行考察,判断剪去该节点是否能提升泛化性能,若能,则将该节点标记为叶节点。
    对于在每一个节点上考察该节点有或没有是否能够提升泛化性能???我们一般采用采用的性能评估办法,如留出法、交叉验证法、自助法等进行评估。
    值得一提的是,对于预剪枝策略,虽然降低了过拟合(overfitting)的风险并降低了训练开销,但同时也带来了欠拟合(underfitting)的风险(当前节点可能不能带来泛化性能提升,但在此节点基础上的后续划分可能带来性能提升),而后剪枝策略往往能够降低欠拟合风险。



    最后简单的说一下,关于数据集中的属性值为连续的处理策略,采用将这个属性的连续值进行二分来进行离散化处理的办法。具体的做法是,将这些值从小到大进行排序,而划分点就从每两个相邻的值的平均数中取,那么取哪一个平均值了???我们可以计算每一个可能的划分点将这个属性划分后,将这个数据集就会划分为两个子集,而计算它的信息增益,我们就选择信息增益最大的那个划分点。。。