Weka开发[10]—NBTree源码介绍

转自 Koala++'s blog 感谢原作者


     我不多的读者之一发E-mail给我,说他没有看出NBTreeJ48的区别是什么,当时我也没什么空,所以拖到今天才草草看了看。大概讲一下。


       下面是J48中的buildClassifier代码:

 public void buildClassifier(Instances instances) throws Exception {
    ModelSelection modSelection;
    if (m_binarySplits)

        modSelection = new BinC45ModelSelection(m_minNumObj, instances);

       modSelection = new C45ModelSelection(m_minNumObj, instances);

       m_root = new C45PruneableClassifierTree(modSelection,

    else

!m_unpruned,m_numFolds, !m_noCleanupm_Seed);

}

public void buildClassifier(Instances instances) throws Exception {

    NBTreeModelSelection modSelection =

 

    m_root.buildClassifier(instances);

这里有一个比较特殊的ModelSelection类,这个类以前没提过,它是决定树的模型类,比如上面J48代码中的BinC45ModelSelection表示对于连续属性,分裂时它只分出两个子结点。多扯两句,其实BinC45ModelSelectionC45ModelSelection类,包括以后要讲的NBTreeModelSelection内容都差不多,***ModelSelection类中的selectModel函数返回一个ClassifierSplitModel对象,ClassifierSplitModel故名思意是如何分裂的一个模型。

考虑到NBTree也不是什么经典算法,有人可能不知道是怎么回事,大概讲一下:与决策树的构造方法相似(认为相同也可以)先构造出一个决策树,再在每一个叶子结点构造一个贝叶斯分类器(这也就是为什么默认m_minNumObj是30原因)。具体的内容见论文:Scaling Up the Accuracy of Naive-Bayes Classifiers: A Decision-Tree Hybrid。

NBTreeSplit[] currentModel;

NBTreeNoSplit noSplitModel = null;

    到现在为止,列出来的代码的确与J48差不多,它们的主要区别是在NBTreeNoSplit类中。下面先列出J48中所用的NoSplit类中的buildClassifer函数:

throws Exception {

    m_numSubsets = 1;

    再列出NBTreeNoSplit类中的buildClassifer函数:

    m_nb = new NaiveBayesUpdateable();

    m_disc.setInputFormat(instances);

    m_nb.buildClassifier(temp);

       m_errors = crossValidate(m_nb, temp, new Random(1));

    m_numSubsets = 1;

区别还是挺明显的,除了m_numSubset=1这个标志是叶子结点的语句。在NBTreeNoSplit类的buildClassifier中,在叶子结点构造一个m_nb Naive Bayes分类器,不过又说回来,讲了半天,也就是这一点点区别产生了NBTree这个新的分类器。

public void buildClassifier(Instances data) throws Exception {

   cleanup(new Instances(data, 0));

}

    对于分类一个样本,在NBTreeclassifyInstance函数中,返回:

    刚才说对m_root是一个NBTreeClassifierTree对象,但NBTreeClassifier没有实现classifyInstance函数,那么m_root调用的classifyInstance实际上是ClassifierTree类的函数。在其classifyInstance中:

    currentProb = getProbs(j, instance, 1);

       maxIndex = j;

    }

这一段代码没什么意思,样本属于哪个类别概率最高,那么它就被分类为该类别。这里面的getProbs函数中才是我们关心的:

private double getProbs(int classIndex, Instance instance, double weight)

throws Exception {

    double prob = 0;

    if (m_isLeaf) {

    return weight * localModel().classProb(classIndex, instance, -1);

    } else {

int treeIndex = localModel().whichSubset(instance);

       if (treeIndex == -1) {

           for (int i = 0; i < m_sons.length; i++) {

              prob += son(i).getProbs(classIndex, instance,

              }

           return prob;

           if (son(treeIndex).m_isEmpty) {

instance, treeIndex);

              return son(treeIndex).getProbs(classIndex,

           }

    }

    如果不是叶子结点:先得到这个样本属于应该是哪个子结点的,如果treeIndex=-1表示这个属属性值是缺失的,计算它的方法就是用对每个子结点分开算,再加起来。如果不是缺失的,如果子结点是空的,与是子结点的计算方法相同,否则,递归。

public double classProb(int classIndex, Instance instance, int theSubset)

m_disc.input(instance);

    return m_nb.distributionForInstance(temp)[classIndex];

    刚才所提到的m_nb这个Naive Bayes分类器调用distributionForInstanceNBTree差不多讲完了,最后来点打击人的,我真感觉这个分类器没有太大的必要搞懂,不过提出它的作者我认为算是一个想象力丰富的人,至于NBTree 的应用,我仅知道它在VFDTc中用到了,还在它的几个改进版中用到过,其它的用到它的地方我也不知道,有人知道,请告诉我。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值