本文主要分析我Weka中J48在分类时处理缺失值的问题.在J48中,如果在当前节点上该样本的属性为空,它会按照一个当前节点上该属性的分布情况得到一个分布表,即如果该节点的训练样本的属性值分布为 [2,3,5] (样本量为10),则此时该样本按照[0.2,0.3,0.5]的权重进入当前节点的子树中.
- //WangYi 2007-10-7
- /*
- * 分类样本
- */
- public double classifyInstance(Instance instance)
- throws Exception {
-
- double maxProb = -1;
- double currentProb;
- int maxIndex = 0;
- int j;
-
- /*
- * 找到可能性最大的类别作为当前测试样本的类别
- */
- for (j = 0; j < instance.numClasses(); j++) {
- //对于类别j的可能性
- //wangyi 2008.4.1
- currentProb = getProbs(j, instance, 1);
- if (Utils.gr(currentProb,maxProb)) {
- maxIndex = j;
- maxProb = currentProb;
- }
- }
-
- return (double)maxIndex;
- }
-
- 该函数在 weka.classifiers.trees.ClassifierTree类文件中.该函数实现了分类一个测试样本的功能.
-
- /*
- * 在这里有DecisionTree处理未知值的解决办法
- */
- private double getProbs(int classIndex, Instance instance, double weight)
- throws Exception {
-
- double prob = 0;
-
- /*
- * 当前节点如果是叶子节点,返回instance在该classIndex下的可能性
- */
- if (m_isLeaf) {
- return weight * localModel().classProb(classIndex, instance, -1);
- } else {
- /*
- * 如果不是叶子节点则我们找该样本应该进入下一级哪一个子节点
- */
- int treeIndex = localModel().whichSubset(instance);
-
- /*
- * 当该样本的属性为?时,它将返回-1
- */
- 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);
- }
- }
- }
- }
-
- 该函数也在weka.classifiers.trees.ClassifierTree中.
-
- /*
- * C4.5Split中计算样本在当前节点 属性上的权重数值
- */
- public final double [] weights(Instance instance) {
-
- double [] weights;
- int i;
-
- if (instance.isMissing(m_attIndex)) {
- weights = new double [m_numSubsets];
- /*
- * 计算权重信息还是借助了 Split中保存的统计信息
- * (distribution),这个对象相信大家不会陌生
- */
- for (i=0;i<m_numSubsets;i++)
- weights [i] = m_distribution.perBag(i)/m_distribution.total();
- return weights;
- }else{
- return null;
- }
- }
复制代码