提问人:Hack-R 提问时间:1/30/2017 最后编辑:Hack-R 更新时间:1/31/2017 访问量:1457
将写入 double 的 Java 代码更改为将 double[] 写入 CSV(用例 = WEKA 库)
Changing Java code that writes double to CSV to write double[] to CSV (use case = WEKA library)
问:
我使用 WEKA 库编写了一个 Java 程序,
- 训练分类算法
- 使用经过训练的算法对未标记的数据集运行预测
- 将结果写出到 .csv 文件
问题在于它目前写出离散的分类结果(即算法猜测某行属于哪个类别)。我想要的是写出给定类的概率(例如,如果我将行分类为“垃圾邮件”或“非垃圾邮件”,那么我希望垃圾邮件的概率是结果)。
我的理解是,要做到这一点,我需要使用而不是在我的代码中。来自WEKA:distributionForInstance
classifyInstance
如果您对所有类的分布感兴趣,请使用 方法 distributionForInstance(Instance)。此方法返回双精度 数组,其中包含每个类的概率。
我遇到的问题是,使用 classifyInstance
时,我正在处理 double 数据类型,而使用 distributionForInstance
时,我正在处理 double[]
数据类型,并且显然没有正确调整我的代码。
下面是写出谨慎预测的工作代码:
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);
// label instances
for (int i = 0; i < newTest.numInstances(); i++) {
double clsLabel = clf.classifyInstance(newTest.instance(i));
labeled.instance(i).setClassValue(clsLabel);
}
System.out.println("Predictions complete! Writing output file to csv...");
BufferedWriter outFile = new BufferedWriter(new FileWriter("C:/Users/hackr/Desktop/silverbullet_output.csv"));
for (int i = 0; i < labeled.size(); i++)
{
outFile.write(labeled.get(i).toString());
outFile.write("\n");
}
System.out.println("Output file written.");
System.out.println("Completed successfully!");
outFile.close();
}
}
现在我正在处理的代码如下:
for (int i = 0; i < labeled.size(); i++)
{
double[] clsLabel = clf.distributionForInstance(newTest.instance(i));
//outFile.write(labeled.get(i).toString());
outFile.write(Double.toString(clsLabel[i]));
outFile.write("\n");
}
并抛出一个
索引越界
错误。
我还移动了 的创建,因为显然当数据类型更改时它无法再找到符号,除非我将其移动到循环内。clsLabel
for
答:
假设你的输出将类似于数据透视表,类标签为列,并且我假设从你的类中返回的每个类的分数,你需要遍历数组并为每个值创建一个字段,或者只列出值。我不知道double[]数组中的值如何与类标签相关,但不知何故,您必须进行这种关联。 也许如果分类器无法分类,它会返回一个空数组,这就是您收到 IOOB 异常的原因。
评论
改写我的评论。
你得到的结果本身就是一个.这意味着你不是从分布函数中得到一个值,而是将整个分布作为一个值数组。clf.distributionForInstance(newTest.instance(i));
double[]
若要正确显示整体分布,需要单独遍历结果集并打印值:
for (int i = 0; i < labeled.size(); i++) {
double[] clsLabel = clf.distributionForInstance(newTest.instance(i));
for(double d : clsLabel) {
outFile.write(Double.toString(d));
}
outFile.write("\n");
}
假设有 2 个类别(预测了 2 个类别,如“垃圾邮件”和“非垃圾邮件”),则以下工作有效:
BufferedWriter outFile = new BufferedWriter(new FileWriter("silverbullet_rro_output.csv"));
StringBuilder builder = new StringBuilder();
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();
评论
i
i
for(double d : clsLabel) { write(Double.toString(d)) }