Weka算法Classifier-tree-J48源码分析(四)总结

本文详细介绍了Weka中分类树如何对新的实例进行分类的过程。包括如何处理缺失值、如何控制分类树精度、连续值离散化的方法以及分类树的剪枝策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、ClassifyInstance

首先先说一下构造好的分类树是如何对一个新的Instance进行区分。

直观上,会对树进行一个检索,从根节点根据属性的不同,最终走到叶子节点,得到具体的分类。

但Weka在实现上,是遍历了这个Instance属于不同的class的可能性,并从中选出了一个最大的,代码如下:

[java] view plaincopy
  1.  public double classifyInstance(Instance instance)   
  2.    throws Exception {  
  3.   
  4.    double maxProb = -1;  
  5.    double currentProb;  
  6.    int maxIndex = 0;  
  7.    int j;  
  8.   
  9.    for (j = 0; j < instance.numClasses(); j++) {  
  10.      currentProb = getProbs(j, instance, 1);  
  11.      if (Utils.gr(currentProb,maxProb)) {  
  12. maxIndex = j;  
  13. maxProb = currentProb;  
  14.      }  
  15.    }  
  16.   
  17.    return (double)maxIndex;  
  18.  }  
而getProbs函数关键代码如下:

[java] view plaincopy
  1.    if (m_isLeaf) {  
  2.      return weight * localModel().classProb(classIndex, instance, -1);  
  3.    } else {  
  4.      int treeIndex = localModel().whichSubset(instance);  
  5.      if (treeIndex == -1) {  
  6. double[] weights = localModel().weights(instance);  
  7. for (int i = 0; i < m_sons.length; i++) {  
  8.   if (!son(i).m_isEmpty) {  
  9.     prob += son(i).getProbs(classIndex, instance,   
  10.                 weights[i] * weight);  
  11.   }  
如果是一个叶子节点,则直接从本节点的分布就能确定当前instance属于相关class的可能性,否则就要取出treeIndex进行判断,这里的treeIndex==-1代表这个Instance属于不同的branch,换句话说,本节点的Model不能对此Instance给出一个确定的划分。

在分类树中这种情况理论上是不会出现的,weka在这里其实是用treeIndex==-1来处理了相关属性缺失的情况。

whichSubset代码如下:

[java] view plaincopy
  1.  public final int whichSubset(Instance instance)   
  2.       throws Exception {  
  3.      
  4.    if (instance.isMissing(m_attIndex))  
  5.      return -1;  
  6.    else{  
  7.      if (instance.attribute(m_attIndex).isNominal())  
  8. return (int)instance.value(m_attIndex);  
  9.      else  
  10. if (Utils.smOrEq(instance.value(m_attIndex),m_splitPoint))  
  11.   return 0;  
  12. else  
  13.   return 1;  
  14.    }  
  15.  }  
如果属性缺失,则直接返回-1,如果是离散值,则根据属性进行选择,如果是连续值,则通过训练时得到的分裂点进行判断。



二、总结

接下来可以回答第二篇博客开头时提到的4个问题了。

1、如何控制分类树的精度。

答:使用minNoObj参数来控制分类树的精度,节点停止分裂的条件有5个:

(1)所有的instances已经属于同一个分类(selectModel里)

(2)instances数量小于2*minNoObj(selectModel里)

(3)一个分裂产生的信息增益石0(selectModel里)

(4)对离散值进行分裂节点的计算时,超过一个的Bag里的instance数量小于minNoObj(spliter里)

(5)对连续值进行分裂计算时,有效instances数量小于2*minNoObj(spliter里)

2、如何处理缺失的值(MissingValue)

答:对缺失值得处理分两种,其一是训练阶段的缺失值处理,方法是直接忽略掉这条记录。在分类阶段对缺失值得处理是,忽略该属性,使其在不同的branch上进行计算,最后将概率结果进行合并。

3、如何对连续值进行离散化。

答:Spliter首先对连续值进行排序,之后从前到后遍历每一个值当做分裂点,对分裂结果计算信息增益率最大的作为最终分裂点构建不同的branch。

4、如何进行分类树的剪枝。

答:具体实现参见第二篇博客的collapse方法和prune方法。剪枝过程是一个单一的自底向上的遍历,一般有三种情况:第一种情况是保持树的原状;第二种情况是仅保留上一决策结点输出最大的那个;第三种情况就是将子树替换为叶节点,其类别选择训练集中的最大类别。这三种情况都需要分别估算对应的错误率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值