无法在 weka java *WEKA*DUMMY*STRING*FOR*STRING*ATTRIBUTES* 中获取类标签

Posted

技术标签:

【中文标题】无法在 weka java *WEKA*DUMMY*STRING*FOR*STRING*ATTRIBUTES* 中获取类标签【英文标题】:unable to obtain a class label in weka java *WEKA*DUMMY*STRING*FOR*STRING*ATTRIBUTES* 【发布时间】:2014-07-15 22:23:31 【问题描述】:

我正在尝试使用 weka 库和在线教程对 java 中的实例进行分类。

我在我的设备中构建了一个模型,并使用此代码从磁盘加载了该模型。

public void makeModel() throws Exception
    
        ArffLoader loader = new ArffLoader();
    loader.setFile(new File("data.arff"));

   Instances structure = loader.getDataSet();
    structure.setClassIndex(1);

// train NaiveBayes

NaiveBayesMultinomial n = new NaiveBayesMultinomial();
FilteredClassifier f = new FilteredClassifier();
StringToWordVector s = new StringToWordVector();

s.setUseStoplist(true);
s.setWordsToKeep(100);

f.setFilter(s);

f.setClassifier(n);
structure.numAttributes();
 f.buildClassifier(structure);
Instance current;


Evaluation eval = new Evaluation(structure);
 eval.crossValidateModel(f, structure, 10, new Random(1));
 System.out.println(eval.toSummaryString("\nResults\n======\n", false));



// output generated model
//System.out.println(f);
 ObjectOutputStream oos = new ObjectOutputStream(
                            new FileOutputStream("classifier.model"));
 oos.writeObject(f);
 oos.flush();
 oos.close();
    

------------ 输出-------------

结果

正确分类的实例 20158 79.6948 % 错误分类的实例 5136 20.3052 % Kappa 统计量 0.6737 平均绝对误差 0.0726 均方根误差 0.2025 相对绝对误差 38.7564 % 根相对平方误差 66.1815 % 病例覆盖率(0.95 水平) 96.4142 % 平均相对。区域大小(0.95 水平) 27.7531 % 实例总数 25294


然后我使用相同的模型对未标记的实例进行分类。

public void classify() throws Exception
    
        FilteredClassifier cls = (FilteredClassifier) weka.core.SerializationHelper.read("classifier.model");


Instances unlabeled = new Instances(
                         new BufferedReader(
                           new FileReader("test.arff")));

 // set class attribute
 unlabeled.setClassIndex(0);

 // create copy
 Instances labeled = new Instances(unlabeled);

 // label instances
 for (int i = 0; i < unlabeled.numInstances(); i++) 
     System.out.println(labeled.instance(i).classValue());
     System.out.print(", actual: " + labeled.classAttribute().value((int)labeled.instance(i).classValue()));
   double clsLabel = cls.classifyInstance(unlabeled.instance(i));
   labeled.instance(i).setClassValue(clsLabel);
   System.out.println(", predicted: " + labeled.classAttribute().value((int) clsLabel));
 
 // save labeled data
System.out.println("ended");


    

---------- 输出---------- -----

1.0 ,实际:Bud1? is a This is a new string.txtIlocblobR(??????@?@?@?@E?DSDB `@?@?@,预测:*WEKA*DUMMY*STRING*FOR*STRING*ATTRIBUTES* 2.0 , 实际:这是一个新的新字符串 ,预测:*WEKA*DUMMY*STRING*FOR*STRING*ATTRIBUTES* 结束了


但是,我的错误是预测实际上是 *WEKA*DUMMY*STRING*FOR*STRING*ATTRIBUTES*,而它应该给我一个类标签。

【问题讨论】:

【参考方案1】:

在保存分类器的同时也保存Instances(只是header,不需要数据):

Instances instancesSample = new Instances(structure, 0);
instancesSample.setClassIndex(1);
...
ObjectOutputStream oos = new ObjectOutputStream(
                        new FileOutputStream("classifier.model"));
oos.writeObject(f);
oos.writeObject(instancesSample);
oos.flush();
oos.close();

加载模型后,将保存的实例加载为instancesSample。 分类时:

ObjectInputStream objectInputStream = new ObjectInputStream(new BufferedInputStream(new FileInputStream("classifier.model")));
FilteredClassifier cls = (FilteredClassifier)= (Classifier) objectInputStream.readObject();
Instances instancesSample = (Instances) objectInputStream.readObject();
objectInputStream.close();

int classIndex = 1;
Instances ins = unlabeled[i];
double clsLabel = cls.classifyInstance(ins);
String prediction = instancesSample.attribute(classIndex).value((int) clsLabel));
System.out.println(", predicted: " + prediction);

【讨论】:

嗨,对不起,但我不太了解从以前保存的文件中加载的部分?你指的是哪个文件? 您正在将模型文件保存到 classifier.model。同样将Instances structure 保存到文件中。这就是我所指的。【参考方案2】:

我已将这些行添加到我的分类方法中。

ArffLoader loader = new ArffLoader();
    loader.setFile(new File("data.arff"));

   Instances structure = loader.getDataSet();
    structure.setClassIndex(1);

为了获得类标签,我把它改成了这个

System.out.println(", predicted: " + structure.classAttribute().value((int) clsLabel));

【讨论】:

以上是关于无法在 weka java *WEKA*DUMMY*STRING*FOR*STRING*ATTRIBUTES* 中获取类标签的主要内容,如果未能解决你的问题,请参考以下文章

Weka java.lang.reflect.InvocationTargetException

如何在 weka 中可视化 j48 树

Weka J48 分类器:无法处理数字类?

LibSVM 使用 Weka 命令行

java.sql.SQLException:无法为 jdbc weka.experiment.DatabaseUtils.connectToDatabase 找到合适的驱动程序(DatabaseUti

通过 Java 代码在 Weka GUI 和 Weka 中得到不同的结果