weka[9] - Naive Bayes

Naive Bayes就不做具体介绍了,很简单的一个模型。直接看代码

BuildClassify:

// can classifier handle the data?
    getCapabilities().testWithFail(instances);

    // remove instances with missing class
    instances = new Instances(instances);
    instances.deleteWithMissingClass();

    m_NumClasses = instances.numClasses();

    // Copy the instances
    m_Instances = new Instances(instances);

    // Discretize instances if required
    if (m_UseDiscretization) {
      m_Disc = new weka.filters.supervised.attribute.Discretize();
      m_Disc.setInputFormat(m_Instances);
      m_Instances = weka.filters.Filter.useFilter(m_Instances, m_Disc);
    } else {
      m_Disc = null;
    }
前面还是老样子,预处理下。后面就是把样本属性值离散化一下。具体方法参考 http://ijcai.org/Past%20Proceedings/IJCAI-93-VOL2/PDF/022.pdf

 // Reserve space for the distributions
    m_Distributions = new Estimator[m_Instances.numAttributes() - 1]
      [m_Instances.numClasses()];
    m_ClassDistribution = new DiscreteEstimator(m_Instances.numClasses(), 
                                                true);
m_Distributions存放的是P(C|x), m_Distributions存放的是P(C).

    int attIndex = 0;
    Enumeration enu = m_Instances.enumerateAttributes();
    while (enu.hasMoreElements()) {
      Attribute attribute = (Attribute) enu.nextElement();

      // If the attribute is numeric, determine the estimator 
      // numeric precision from differences between adjacent values
      double numPrecision = DEFAULT_NUM_PRECISION;
      if (attribute.type() == Attribute.NUMERIC) {
	m_Instances.sort(attribute);//按attribute将数据进行排序(从小到大)
	if ((m_Instances.numInstances() > 0)
	    && !m_Instances.instance(0).isMissing(attribute)) {
	  double lastVal = m_Instances.instance(0).value(attribute);//该属性的最小值
	  double currentVal, deltaSum = 0;
	  int distinct = 0;
	  for (int i = 1; i < m_Instances.numInstances(); i++) {
	    Instance currentInst = m_Instances.instance(i);
	    if (currentInst.isMissing(attribute)) {
	      break;//已经排好序,缺失放最后,意味着后面的数据该属性都缺失
	    }
	    currentVal = currentInst.value(attribute);//当前样本对应属性的值
            //如果不是最小-lastVal
	    if (currentVal != lastVal) {
	      deltaSum += currentVal - lastVal;//deltaSum记录了最大值和最小值的差
	      lastVal = currentVal;
	      distinct++;//numeric的时候,该属性的不同取值个数
	    }
	  }
	  if (distinct > 0) {
	    numPrecision = deltaSum / distinct;
	  }
	}
      }

上面这一段是为了得到numPrecision, 参考代码中的注释,可以知道,上面的deltaSum是该属性的最大差值。

这个numPrecision会在后面构造estimator的时候用到,如果是连续的属性,可以理解成分区的一个参数。

接着往下看

      for (int j = 0; j < m_Instances.numClasses(); j++) {
	switch (attribute.type()) {
	case Attribute.NUMERIC: 
	  if (m_UseKernelEstimator) {
	    m_Distributions[attIndex][j] = 
	      new KernelEstimator(numPrecision);
	  } else {
	    m_Distributions[attIndex][j] = 
	      new NormalEstimator(numPrecision);
	  }
	  break;
	case Attribute.NOMINAL:
	  m_Distributions[attIndex][j] = 
	    new DiscreteEstimator(attribute.numValues(), true);
	  break;
	default:
	  throw new Exception("Attribute type unknown to NaiveBayes");
	}
      }
      attIndex++;
    
如果属性是连续的,再选择用kernel的还是normal的。 这里的构造需要用到numPrecision. 具体的这个estimator如何构造,参考weka.estimator这个package。

如果属性是离散的,直接调用离散的estimator。

这里的这个attIndex,对应的是最外层while循环的。

 // Compute counts
    Enumeration enumInsts = m_Instances.enumerateInstances();
    while (enumInsts.hasMoreElements()) {
      Instance instance = 
	(Instance) enumInsts.nextElement();
      updateClassifier(instance);
    }
下面就是增量式学习了,每个样本调用updataClassifier更新结果。

  public void updateClassifier(Instance instance) throws Exception {

    if (!instance.classIsMissing()) {
      Enumeration enumAtts = m_Instances.enumerateAttributes();
      int attIndex = 0;
      while (enumAtts.hasMoreElements()) {
	Attribute attribute = (Attribute) enumAtts.nextElement();
	if (!instance.isMissing(attribute)) {
	  m_Distributions[attIndex][(int)instance.classValue()].
            addValue(instance.value(attribute), instance.weight());
	}
	attIndex++;
      }
      m_ClassDistribution.addValue(instance.classValue(),
                                   instance.weight());
    }
  }
这里很清楚,我们每次更新的是

1.m_Distribution: 对应的是P(x|C)

2.m_ClassDistribution: 对应的是P(C)


最后,作为总结的一句话,Naive Bayes要求每个属性独立,这个条件太强,导致他的效果不是很好。下一篇看看Bayes Network。


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值