文档章节

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

pior
 pior
发布于 2015/10/20 20:22
字数 1345
阅读 66
收藏 0
点赞 0
评论 0

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

       下面是J48中的buildClassifier代码:

public void buildClassifier(Instances instances) throws Exception {
 
    ModelSelection modSelection;
 
    if (m_binarySplits)
        modSelection = new BinC45ModelSelection(m_minNumObj, instances);
    else
       modSelection = new C45ModelSelection(m_minNumObj, instances);
    if (!m_reducedErrorPruning)
       m_root = new C45PruneableClassifierTree(modSelection, 
!m_unpruned,m_CF, m_subtreeRaising, !m_noCleanup);
    else
       m_root = new PruneableClassifierTree(modSelection, 
!m_unpruned,m_numFolds, !m_noCleanup, m_Seed);
       m_root.buildClassifier(instances);
}


    下面是NBTree中的buildClassifier代码:

public void buildClassifier(Instances instances) throws Exception {
    
    NBTreeModelSelection modSelection = 
        new NBTreeModelSelection(m_minNumObj, instances);
 
    m_root = new NBTreeClassifierTree(modSelection);
    m_root.buildClassifier(instances);
}


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

从上面讲的我们已经可以看出J48NBTree在代码中选择了不同的构造树的模型,当然它们是不同的(当然这更是一句废话),另一点值得说的是在J48m_minNumObj默认值是2,而在NBTreem_minNumObj的默认值是30

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

我们先看一下NBTreeModelSelection类,找到selectModel函数,刚才说这个函数与别的***MocelSelection差不多,我也是有根据,可以看到NBTreeModelSelection中的两个警告,这两个变量在NBTreeModelSelection中是没用的,明显是拷贝的。请注意下面三个变量:

NBTreeSplit[] currentModel;
    NBTreeSplit bestModel = null;
NBTreeNoSplit noSplitModel = null;


    NBTreeSplitNBTreeNoSplit都继承自ClassifierSplitModelselectModel函数中注释也不少,我也不解释代码了,大概就是:比如在样本都属于一个样本这种情况就不分裂了,那么就返回noSplitModel对象,否则,针对第j个属性,调currentModel[i].buildClassifier函数,最后根据getErrors来决定哪一个属性是最好的分裂属性。

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

public final void buildClassifier(Instances instances) 
throws Exception {
    m_distribution = new Distribution(instances);
    m_numSubsets = 1;
}


    再列出NBTreeNoSplit类中的buildClassifer函数:

public final void buildClassifier(Instances instances) throws Exception {
    m_nb = new NaiveBayesUpdateable();
    m_disc = new Discretize();
    m_disc.setInputFormat(instances);
    Instances temp = Filter.useFilter(instances, m_disc);
    m_nb.buildClassifier(temp);
    if (temp.numInstances() >= 5) {
       m_errors = crossValidate(m_nb, temp, new Random(1));
    }
    m_numSubsets = 1;
}


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

m_root是一个NBTreeClassifierTree对象,我们再看一下NBTreeClassifierTree对象,我们直接看 buildClassifier函数:

public void buildClassifier(Instances data) throws Exception {
    super.buildClassifier(data);
   cleanup(new Instances(data, 0));
   assignIDs(-1);
}


    可以看到它直接调用的父类的buildClssifier,而它的父类就是ClassifierTree,在J48中同样使用的是ClssifierTree类。

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

return m_root.classifyInstance(instance);


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

for (j = 0; j < instance.numClasses(); j++) {
    currentProb = getProbs(j, instance, 1);
    if (Utils.gr(currentProb, maxProb)) {
       maxIndex = j;
       maxProb = currentProb;
    }
}


这一段代码没什么意思,样本属于哪个类别概率最高,那么它就被分类为该类别。这里面的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) {
           double[] weights = localModel().weights(instance);
           for (int i = 0; i < m_sons.length; i++) {
              if (!son(i).m_isEmpty) {
              prob += son(i).getProbs(classIndex, instance, 
weights[i] * weight);
              }
           }
           return prob;
       } else {
           if (son(treeIndex).m_isEmpty) {
return weight * localModel().classProb(classIndex, 
instance, treeIndex);
           } else {
              return son(treeIndex).getProbs(classIndex, 
instance, weight);
           }
       }
    }
}


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

    如果是叶子结点:localModel返回的是ClassifierSplitModel对象,该对象调用classProb函数,我们看一下NBTreeNoSplit函数的classProb函数:

public double classProb(int classIndex, Instance instance, int theSubset)
throws Exception {
m_disc.input(instance);
    Instance temp = m_disc.output();
    return m_nb.distributionForInstance(temp)[classIndex];
}


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


本文转载自:

共有 人打赏支持
pior
粉丝 25
博文 151
码字总数 22496
作品 0
济南
高级程序员
Weka开发[11]—J48源代码介绍

这次介绍一下J48的源码,分析J48的源码似乎真还是有用的,同学改造J48写过VFDT,我自己用J48进行特征选择(当然很失败)。 J48的buildClassfier函数: public void buildClassifier(Instance...

pior
2015/10/20
190
0
Weka开发[6]-参数设置

这一次介绍的非常简单,会用传命令行参数的人就不用浪费时间看这一篇了,这一篇介绍weka中一些类参数传递的问题。 首先要传递参数当然要知道参数有哪些,有什么作用,要知道这些,建议用Wek...

pior
2015/10/17
79
0
用 WEKA 进行数据挖掘

什么是 数据挖掘?您会不时地问自己这个问题,因为这个主题越来越得到技术界的关注。您可能听说过像 Google 和 Yahoo! 这样的公司都在生成有关其所有用户的数十亿的数据点,您不禁疑惑,“它...

红薯
2010/05/21
9.9K
12
Weka开发[5]-半监督算法

这次介绍一个我现在正在做的半监督算法,因为我只是提出一个框架,半监督算法只是一个工具,可是为了找这个工具也让我花了不少功夫。现在介绍的暂时不是Weka的一部分,但开发者是waikato大学...

pior
2015/10/17
46
0
Weka 开发[1]-Instances类

言归正传,开始介绍Weka,先google一下,把Weka软件下载下来,在Weka的目录中有一个weka.jar的包。 把包添加到工程中后,就可以调用weka中的函数了。 再介绍一点weka的基本知识,在weka的目录...

pior
2015/10/17
217
0
Weka manual 3.6翻译: 1.1 简介

第一章 Weka命令行入门 1.1简介 在最初的实验,Weka所包含的图形用户界面是相当足够,若深入使用则建议使用命令行界面,因为它提供了一些功能(这些功能在图形用户界面下不可用) - 并使用少...

Honghe
2012/11/24
0
0
人工智能之机器学习与数据挖据之WEKA使用与实践

阅读对象 只要你想读,你就读呗!最好点个赞再走。。。:-) 本文尽量通过例子和直观描述,来说明人工智能中机器学习和数据挖据的主要概念,分类,和使用方法,并通过例子描述如何使用它来促进...

我是吴文华
05/18
0
0
数据预处理和weka.filters的使用--数据挖掘学习和weka使用(三)

上一篇介绍了arff格式,这是weka专有格式,一般情况需要我们从其他数据源抽取或者获得。weka支持从cvs转化,也可以从数据库中抽取,界面如下图 weka安装目录有一个data目录,里面有一些测试数...

长平狐
2013/11/25
1K
0
Weka开发[7]-LibSVM

首先要提的是LibSVM是一个库,Lib很明显是library的缩写,有些人不知道怎么会认为它是一种算法。它是由中国台湾的Chih-Chung Chang和Chih-Jen Lin等人开发的,他们用多种语言实现写了LibSVM。...

pior
2015/10/17
187
0
RIpple-DOwn Rule算法和weka中Rider使用--数据挖掘学习和weka使用(五)

RIpple-DOwn Rule算法简介 RIpple-DOwn Rule算法(链波下降规则)是一种专家系统方法论,它是澳大利亚新南威尔士大学的Compton教授于1989年提出。它是一种用于知识表示和获取的方法。从某种意...

长平狐
2013/11/25
240
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

pbgo: 基于Protobuf的迷你RPC/REST框架

https://www.oschina.net/p/pbgo

chai2010
17分钟前
0
0
rsync工具介绍、常用选项以及通过ssh同步

linux下的文件同步工具 rsync rsync是非常实用的一个同步工具,可以从a机器到b机器传输一个文件,也可以备份数据,系统默认没有这个工具,要使用命令 yum install -y rsync 安装。 rsync的命...

黄昏残影
32分钟前
0
0
OSChina 周四乱弹 —— 表妹要嫁人 舅妈叮嘱……

Osc乱弹歌单(2018)请戳(这里) 【今日歌曲】 @哈哈哈哈哈嗝:一定要听——The Pancakes的单曲《咁咁咁》 《咁咁咁》- The Pancakes 手机党少年们想听歌,请使劲儿戳(这里) @clouddyy :...

小小编辑
今天
66
4
流利阅读笔记30-20180719待学习

重磅:让人类得老年痴呆的竟是它? Lala 2018-07-19 1.今日导读 去年奥斯卡最佳动画长片《寻梦环游记》里有一句经典台词:“比死亡更可怕的,是遗忘”。在电影中,年迈的曾祖母会重复说一样的...

aibinxiao
今天
3
0
1.16 Linux机器相互登录

Linux机器之间以密码方式互相登录 运行命令#ssh [ip address],标准命令:#ssh [username]@ip, 如果没有写用户名,则默认为系统当前登录的用户 命令#w查看系统负载,可查看到连接到该主机的...

小丑鱼00
今天
0
0
about git flow

  昨天元芳做了git分支管理规范的分享,为了拓展大家关于git分支的认知,这里我特意再分享这两个关于git flow的链接,大家可以看一下。 Git 工作流程 Git分支管理策略   git flow本质上是...

qwfys
今天
2
0
Linux系统日志文件

/var/log/messages linux系统总日志 /etc/logrotate.conf 日志切割配置文件 参考https://my.oschina.net/u/2000675/blog/908189 dmesg命令 dmesg’命令显示linux内核的环形缓冲区信息,我们可...

chencheng-linux
今天
1
0
MacOS下给树莓派安装Raspbian系统

下载镜像 前往 树莓派官网 下载镜像。 点击 最新版Raspbian 下载最新版镜像。 下载后请,通过 访达 双击解压,或通过 unzip 命令解压。 检查下载的文件 ls -lh -rw-r--r-- 1 dingdayu s...

dingdayu
今天
1
0
spring boot使用通用mapper(tk.mapper) ,id自增和回显等问题

最近项目使用到tk.mapper设置id自增,数据库是mysql。在使用通用mapper主键生成过程中有一些问题,在总结一下。 1、UUID生成方式-字符串主键 在主键上增加注解 @Id @GeneratedValue...

北岩
今天
2
0
告警系统邮件引擎、运行告警系统

告警系统邮件引擎 cd mail vim mail.py #!/usr/bin/env python#-*- coding: UTF-8 -*-import os,sysreload(sys)sys.setdefaultencoding('utf8')import getoptimport smtplibfr......

Zhouliang6
今天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部