【问题标题】:Correctly labeling predicted classes when using the Java WEKA library使用 Java WEKA 库时正确标记预测的类
【发布时间】:2017-01-31 23:55:44
【问题描述】:

我有一个程序可以训练具有 2 类分类结果的算法,然后针对未标记的数据集运行并写出预测(2 类中的每一个的概率)。

针对该程序运行的所有数据集都将具有与结果相同的 2 个类。考虑到这一点,我运行了预测并使用了一些事后统计数据来确定哪一列结果描述了哪个结果,然后对它们进行硬编码:

public class runPredictions {
public static void runPredictions(ArrayList al2) throws IOException, Exception{
    // Retrieve objects
    Instances newTest = (Instances) al2.get(0);
    Classifier clf = (Classifier) al2.get(1);

    // Print status
    System.out.println("Generating predictions...");

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

    BufferedWriter outFile = new BufferedWriter(new FileWriter("silverbullet_rro_output.csv"));
    StringBuilder builder = new StringBuilder();

    builder.append("Prob_Retain"+","+"Prob_Attrite"+"\n");
    for (int i = 0; i < labeled.size(); i++)      
    {
        double[] clsLabel = clf.distributionForInstance(newTest.instance(i));
        for(int j=0;j<2;j++){
           builder.append(clsLabel[j]+""); 
           if(j < clsLabel.length - 1)
               builder.append(",");
        }
        builder.append("\n");
    }
    outFile.write(builder.toString());//save the string representation
    System.out.println("Output file written.");
    System.out.println("Completed successfully!");
    outFile.close();    
}    
}

问题在于,2 列中的哪一列描述了 2 个结果类别中的哪一个是不固定的。这似乎与哪个类别首先出现在训练数据集中有关,这完全是任意的。所以当这个程序使用其他数据集时,硬编码的标签是向后的。

所以,我需要一种更好的方法来标记它们,但是查看 ClassifierdistributionForInstance 的文档并没有发现任何有用的信息。

更新

我想出了如何将它打印到屏幕上(感谢this),但仍然无法将其写入 csv:

for (int i = 0; i < labeled.size(); i++)      
    {
        // Discreet prediction
        double predictionIndex = 
            clf.classifyInstance(newTest.instance(i)); 

        // Get the predicted class label from the predictionIndex.
        String predictedClassLabel =
            newTest.classAttribute().value((int) predictionIndex);

        // Get the prediction probability distribution.
        double[] predictionDistribution = 
            clf.distributionForInstance(newTest.instance(i)); 

        // Print out the true predicted label, and the distribution
        System.out.printf("%5d: predicted=%-10s, distribution=", 
                          i, predictedClassLabel); 

        // Loop over all the prediction labels in the distribution.
        for (int predictionDistributionIndex = 0; 
             predictionDistributionIndex < predictionDistribution.length; 
             predictionDistributionIndex++)
        {
            // Get this distribution index's class label.
            String predictionDistributionIndexAsClassLabel = 
                newTest.classAttribute().value(
                    predictionDistributionIndex);

            // Get the probability.
            double predictionProbability = 
                predictionDistribution[predictionDistributionIndex];

            System.out.printf("[%10s : %6.3f]", 
                              predictionDistributionIndexAsClassLabel, 
                              predictionProbability );

            // Attempt to write to CSV
            builder.append(i+","+predictedClassLabel+","+
                    predictionDistributionIndexAsClassLabel+","+predictionProbability);
                            //.charAt(0)+','+predictionProbability.charAt(0));

        }

        System.out.printf("\n");
        builder.append("\n");

【问题讨论】:

    标签: java weka


    【解决方案1】:

    我从 answeranswer 改编了下面的代码。基本上,你可以查询类属性的测试数据,然后获取每个可能的类的具体值。

    for (int i = 0; i < labeled.size(); i++)      
    {
    // Discreet prediction
    
    double predictionIndex = 
        clf.classifyInstance(newTest.instance(i)); 
    
    // Get the predicted class label from the predictionIndex.
    String predictedClassLabel =
        newTest.classAttribute().value((int) predictionIndex);
    
    // Get the prediction probability distribution.
    double[] predictionDistribution = 
        clf.distributionForInstance(newTest.instance(i)); 
    
    // Print out the true predicted label, and the distribution
    System.out.printf("%5d: predicted=%-10s, distribution=", 
                      i, predictedClassLabel); 
    
    // Loop over all the prediction labels in the distribution.
    for (int predictionDistributionIndex = 0; 
         predictionDistributionIndex < predictionDistribution.length; 
         predictionDistributionIndex++)
    {
        // Get this distribution index's class label.
        String predictionDistributionIndexAsClassLabel = 
            newTest.classAttribute().value(
                predictionDistributionIndex);
    
        // Get the probability.
        double predictionProbability = 
            predictionDistribution[predictionDistributionIndex];
    
        System.out.printf("[%10s : %6.3f]", 
                          predictionDistributionIndexAsClassLabel, 
                          predictionProbability );
    
        // Write to CSV
        builder.append(i+","+
                predictionDistributionIndexAsClassLabel+","+predictionProbability);
    
    
    }
    
    System.out.printf("\n");
    builder.append("\n");
    
    }
    
    
    // Save results in .csv file
    outFile.write(builder.toString());//save the string representation
    

    【讨论】:

    • 你说得对,我应该是一个不同的索引!它只是您正在评估的实例。我会更正
    • 再次感谢。所以第一行的 for 循环应该类似于for (int j = 0; j &lt; newTest.size(); j++) 对吗?对于 2 类(2 个标签)情况,i 将始终为 0 或 1,但是在您拥有 newTest.classAttribute().value(i) 的行上,我们是否不需要在某处使用 j 来访问 newTest 的右侧部分?
    • 我认为可能有一个小错误或缺少组件(见上面的评论),但我刚刚在我的版本中得到了这个工作,你值得称赞,所以我要编辑你的帖子使用我的版本并将其标记为解决方案。如果您想回滚我即将进行的编辑,只需调整您的版本,这非常酷。再次感谢您的帮助,非常感谢!
    猜你喜欢
    • 2017-10-12
    • 1970-01-01
    • 1970-01-01
    • 2013-09-25
    • 2017-12-07
    • 2019-08-30
    • 2015-03-23
    • 2013-04-22
    • 2013-10-17
    相关资源
    最近更新 更多