Weka中实现一个分类器比较重要的有一下3个方法:
buildClassifier(Instances instances)
double[] distributionForInstance(Instanceinstance)
double classifyInstance(Instance instance) throwsException;
其中后2个只要实现其中之一即可,因此我们在分析过程中主要围绕这几个方法进行。
朴素贝叶斯法是基于贝叶斯定理与特征条件独立假设的分类方法。简单来说,朴素贝叶斯分类器假设样本每个特征与其他特征都不相关。在进行贝叶斯分类时最重要的2个参数是类先验概率P(Ci)和类条件独立概率P(x|Ci)。
1. 重要参数
在NativeBayes中定义了2个字段
protected Estimator[][] m_Distributions; 其中保存的是用于计算P(x|Ci)参数;
protected Estimator m_ClassDistribution; 其中保存的是P(Ci)
2. 训练分类器
下面我们看一下其训练过程,主要在方法buildClassifier(Instances instances)中,该方法用于训练类条件概率或计算概率所需要的参数。其主要代码如下(我们只分析比较重要的部分):
public void buildClassifier(Instancesinstances) throws Exception {
……
for(int j = 0; j < m_Instances.numClasses(); j++) {
//该循环主要用于为每个class创建Estimator类
switch(attribute.type()) {
caseAttribute.NUMERIC:
if(m_UseKernelEstimator) {
m_Distributions[attIndex][j]= new KernelEstimator(numPrecision);
}else {
m_Distributions[attIndex][j]= new NormalEstimator(numPrecision);
}
break;
caseAttribute.NOMINAL:
m_Distributions[attIndex][j]= new DiscreteEstimator(attribute.numValues(), true);
break;
default:
thrownew Exception("Attribute type unknown to NaiveBayes");
}
}
attIndex++;
}
//Compute counts
//此处扫描样本训练参数
EnumerationenumInsts = m_Instances.enumerateInstances();
while(enumInsts.hasMoreElements()) {
Instanceinstance = (Instance) enumInsts.nextElement();
updateClassifier(instance);
}
//Save space
m_Instances= new Instances(m_Instances, 0);
}
从上面代码可以看出首先定义一个Estimator类型的数组用于存放类条件概率P(xi|C),根据估计算法的不同数组Estimator不同的元素可能为其子类中的一个(KernelEstimator,NormalEstimator或DiscreteEstimator)。
然后调用updateClassifier扫描所有的训练样本并更新m_Distributions[attIndex][j](表示属性attIndex在类j下的概率/参数)中的参数。
2.1 概率估计算法
针对不同类型的属性,类条件概率估计方法是不同的:
当属性类型是离散型时,类条件概率P(Xi =xi|C = c)可以根据类c中属性等于xi的训练实例的比例来估计。该代码如下:
public void addValue(double data, doubleweight) {
m_Counts[(int)data] +