[_数据挖掘_] 决策树实现

参考"collective intelligence“相关章节的实现。

决策树使用广泛,对于理解内在的推理过程非常有帮助,非常适合那些属性是类别值的,或者数字属性有breakpoint的应用场景。但是缺点是不适合输出较多,元组的类别由多个属性的复杂组合决定的情况(比如说输出由两个属性的差值来决定)。

决策树由自上而下的递归算法来实现。下面是书中的实现的伪码,和经典的算法稍微有些差别,毕竟这是正对CI中的例子来的,但是还是有很好的借鉴性。

def buildtree(rows, scoref):

# rows 是还没有放入叶子节点的训练元组

#scoref 是度量函数,度量集合中元组的有序程度,可以使entropy,gini——impurity,vaviance

if len(rows) == 0:

         return 空节点

best_gain, best_criterial, best_sets = 0

for col in 训练元组的的每一个属性列:

          得到rows对应col属性的所有不同值column_values

          for v in column_values:

                  将col对应的属性在值v上进行划分,得到两个集合set1(此属性的值>=v,对于数值型属性;否则为==), set2(其他)

                  利用scoref计算set1, set2这种划分的度量值gain

                  if gain>best_gain 且 set1,set2的个数都不为0:

                          更新best_gain,

                          best_criterial = (此属性,划分所用到的属性的值),

                          best_sets = (set1, set2)

if best_gain > 0:

          tb = buildtree(best_sets[0], scoref)

          fb = buildtree(best_sets[1], scoref)

          创建节点node,记录分离准则

          node的左右分值分别是tb, fb

          返回 node

else:

           返回叶子节点

其他相关的一些问题。

1)检验

得到决策树tree后,因为tree的每个节点都保存了此节点上分离时的属性和基准值,所以对于输入值,很容易访问到对应的叶子节点。需要注意的一点是对于数值类型和非数值类型的比较是不一样的,参考上面的伪代码。

2)修剪

决策树的训练很可能出现过度拟合的现象,也就是说算法为了准确表达一些数据,创建了很多不必要的分支。这很大程度上是由于数据不准确或者是属性值不准确造成的,或者是某个非常特殊的训练元组。这些不必要的分支对集合的熵减少很小,因此显得没有必要,特别是对与很大的决策树而言更是如此。

解决的方法有两个一是在构造的过程中,每当要创建新的分支的时候判断,如果分离后的熵相比原来的减得很少,则不创建;二是当整个树创建好了以后进行检查,如果同属于一个父节点的两个叶子节点的熵相比不分离时的熵的话,那么合并两个叶子节点,原来的父节点变成了叶子节点,从下到上依次检查,注意,新合并的叶子节点也要再被检查,如果其兄弟节点也是叶子节点的话。

第一种方法有一个很大的问题是,每次分离时选取的是某一个集合的一种属性,此时的最佳分离(增益最大的分离)的增益小于阈值,也有可能出现对于他的一个子集的某种划分带来的增益可能就很大。所以一般选用第二种方法。但是这个阈值如何选取呢?

3)数据缺失的处理

对于要检验的数据,如果某个属性的值不好确定,或者无法确定,那么使用决策树也可以得到其类别的一个估计。方法是,和确定值时单分支游历不同,在需要分离此缺失值的属性的时候我们两边分支都进行游历。最后组合两边游历的结果,这样提供给了使用者一组候选结果,并且可以计算各候选项的权重供人决策。

4)处理数值型输出

如果输出一些数值而不是类标示,原来用于评判输出是分类值的标准如entropy就不是那么的合适了,因为此时的值并没有类别的概念,可能只是描述了一种程度。可以使用是variance,也就是计算数据集的方差来评判。这样可以使得属性值的分离朝着减少分支方差的方向进行,也就是分支上的数据值尽可能地集中。但是叶子节点是不是也需要改造呢?书上没有提,我觉得改造下更好,也可以利用方差来决定是不是不需要再进一步的划分了,然后在结果里面给出候选集。这样做和修剪的第一种方法是不一样的,因为我们此时只考虑结果集的方差,而不是用原有的和划分后的差来比较。不知道这样想是不是可行啊?

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值