使用自己的 Java 代码和模型在 WEKA 中获取预测百分比

Posted

技术标签:

【中文标题】使用自己的 Java 代码和模型在 WEKA 中获取预测百分比【英文标题】:Get prediction percentage in WEKA using own Java code and a model 【发布时间】:2014-03-07 15:01:10 【问题描述】:

概述

我知道可以通过 GUI 和命令行选项获得训练的 WEKA 模型中每个预测的百分比,如文档文章 "Making predictions" 中方便地解释和演示的那样。

预测

我知道记录在案的三种方法可以得到这些预测:

    command line GUI Java 代码/使用 WEKA API,我在回答 "Get risk predictions in WEKA using own Java code" 时能够做到这一点 第四个需要生成的 WEKA .MODEL 文件

我有一个训练有素的.MODEL 文件,现在我想使用它和预测百分比对新实例进行分类,类似于下面的文件(GUI 资源管理器的输出,CSV格式):

inst#,actual,predicted,error,distribution,
1,1:0,2:1,+,0.399409,*0.7811
2,1:0,2:1,+,0.3932409,*0.8191
3,1:0,2:1,+,0.399409,*0.600591
4,1:0,2:1,+,0.139409,*0.64
5,1:0,2:1,+,0.399409,*0.600593
6,1:0,2:1,+,0.3993209,*0.600594
7,1:0,2:1,+,0.500129,*0.600594
8,1:0,2:1,+,0.399409,*0.90011
9,1:0,2:1,+,0.211409,*0.60182
10,1:0,2:1,+,0.21909,*0.11101

predicted 列是我想从 .MODEL 文件中获取的内容。


我知道的

根据我对 WEKA API 方法的经验,可以使用以下代码获得这些预测(PlainText 插入到 Evaluation 对象中)但我不想这样做 k -fold 由Evaluation 对象提供的交叉验证。

StringBuffer predictionSB = new StringBuffer();
Range attributesToShow = null;
Boolean outputDistributions = new Boolean(true);

PlainText predictionOutput = new PlainText();
predictionOutput.setBuffer(predictionSB);
predictionOutput.setOutputDistribution(true);

Evaluation evaluation = new Evaluation(data);
evaluation.crossValidateModel(j48Model, data, numberOfFolds,
        randomNumber, predictionOutput, attributesToShow,
        outputDistributions);

System.out.println(predictionOutput.getBuffer());

来自 WEKA 文档

请注意,.MODEL 文件对来自 .ARFF 或相关输入的数据进行分类,在 "Use Weka in your Java code" 和 "Serialization" aka 中讨论了“如何在您自己的 Java 代码中使用 .MODEL 文件进行分类新实例”(为什么是模糊的标题 smfh)。

使用自己的Java代码进行分类

通过“反序列化”加载.MODEL文件,以下适用于> 3.5.5的版本:

// deserialize model
Classifier cls = (Classifier) weka.core.SerializationHelper.read("/some/where/j48.model");

Instance 对象是数据,它被馈送到classifyInstance。此处提供了一个输出(取决于结果属性的数据类型):

// classify an Instance object (testData)
cls.classifyInstance(testData.instance(0));

"How to reuse saved classifier created from explorer(in weka) in eclipse java"这个问题也有很好的答案!

Javadocs

我已经检查了 Classifier(经过训练的模型)和 Evaluation(以防万一)的 Javadocs,但没有一个直接明确地解决这个问题。

唯一最接近我想要的是ClassifierclassifyInstances方法:

对给定的测试实例进行分类。实例在分类时必须属于数据集。请注意,分类器必须实现 this 或 distributionForInstance()。


如何同时使用 WEKA .MODEL 文件使用我自己的 Java 代码(也就是使用 WEKA API)对新实例进行分类和预测?

【问题讨论】:

【参考方案1】:

这个答案只是从How to reuse saved classifier created from explorer(in weka) in eclipse java 更新我的答案。

我将展示如何获得预测的实例值和预测百分比(或分布)。示例模型是在 Weka Explorer 中创建并保存的 J48 决策树。它是根据 Weka 提供的标称天气数据构建的。它被称为“tree.model”。

import weka.classifiers.Classifier;
import weka.core.Instances;

public class Main 

    public static void main(String[] args) throws Exception
    
        String rootPath="/some/where/"; 
        Instances originalTrain= //instances here

        //load model
        Classifier cls = (Classifier) weka.core.SerializationHelper.read(rootPath+"tree.model");

        //predict instance class values
        Instances originalTrain= //load or create Instances to predict

        //which instance to predict class value
        int s1=0;

        //perform your prediction
        double value=cls.classifyInstance(originalTrain.instance(s1));

        //get the prediction percentage or distribution
        double[] percentage=cls.distributionForInstance(originalTrain.instance(s1));

        //get the name of the class value
        String prediction=originalTrain.classAttribute().value((int)value); 

        System.out.println("The predicted value of instance "+
                                Integer.toString(s1)+
                                ": "+prediction); 

        //Format the distribution
        String distribution="";
        for(int i=0; i <percentage.length; i=i+1)
        
            if(i==value)
            
                distribution=distribution+"*"+Double.toString(percentage[i])+",";
            
            else
            
                distribution=distribution+Double.toString(percentage[i])+",";
            
        
        distribution=distribution.substring(0, distribution.length()-1);

        System.out.println("Distribution:"+ distribution);
    

这个输出是:

The predicted value of instance 0: no  
Distribution: *1, 0

【讨论】:

哎呀我错过/误解了distributionForInstance()!感谢您的完整回答,我相信未来的其他 WEKA 用户会很感激它^_^ 你摇滚! 如果我有一个模型的二元结果,比如“true”或“false”,并且这对应于一个包含两个元素的数组,那么结果变量的分布是否正确?是数组[0],“假”是数组[1]? 我相信这是正确的。如果要检查类值在该数组中的顺序,请查看“String prediction=originalTrain.classAttribute().value((int)value);”上方包含的行。其中 value 将是数组的索引。 谢谢沃尔特先生。我真的很感激!

以上是关于使用自己的 Java 代码和模型在 WEKA 中获取预测百分比的主要内容,如果未能解决你的问题,请参考以下文章

从我自己的 JAVA 代码中使用 SVM 和 Weka 时的实例权重异常

Weka - 如何在 Java 中使用分类器

使用weka分类器后,提取分类模型的源代码

使用weka分类器后,提取分类模型的源代码

使用weka分类器后,提取分类模型的源代码

使用weka分类器后,提取分类模型的源代码