更改 Java 将 double 写入 CSV 的代码以将 double[] 写入 CSV(用例 = WEKA 库)
Changing Java code that writes double to CSV to write double[] to CSV (use case = WEKA library)
我使用
的 WEKA 库编写了一个 Java 程序
- 训练class化算法
- 使用经过训练的算法对未标记的数据集运行预测
- 将结果写入 .csv 文件
问题在于它目前写出离散的 class化结果(即算法猜测某行属于哪个类别)。我想要的是写出给定 class 的概率(例如,如果我将行 class 化为 "spam" 或 "not spam" 那么我希望垃圾邮件的概率是结果)。
我的理解是,要做到这一点,我需要在我的代码中使用 distributionForInstance
而不是 classifyInstance
。来自 WEKA:
If you're interested in the distribution over all the classes, use the
method distributionForInstance(Instance). This method returns a double
array with the probability for each class.
我 运行 遇到的问题是 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");
}
并抛出一个
Index out of bounds
错误。
我还移动了 clsLabel
的创建,因为显然当数据类型更改时它无法再找到该符号,除非我将它移动到 for
循环内。
假设您的输出类似于枢轴 table,其中 class 标签作为列,并且从您的 classfier I 返回的每个 class 的得分假设,您需要遍历数组并为每个值创建一个字段,或者只列出这些值。我不知道 double[] 数组中的值如何与 class 标签相关联,但是您必须以某种方式建立这种关联。
也许如果 classifier 不能 classify,它 returns 一个空数组,这就是你得到 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 个类别,例如 "spam" 和 "not spam")以下工作:
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();
我使用
的 WEKA 库编写了一个 Java 程序- 训练class化算法
- 使用经过训练的算法对未标记的数据集运行预测
- 将结果写入 .csv 文件
问题在于它目前写出离散的 class化结果(即算法猜测某行属于哪个类别)。我想要的是写出给定 class 的概率(例如,如果我将行 class 化为 "spam" 或 "not spam" 那么我希望垃圾邮件的概率是结果)。
我的理解是,要做到这一点,我需要在我的代码中使用 distributionForInstance
而不是 classifyInstance
。来自 WEKA:
If you're interested in the distribution over all the classes, use the method distributionForInstance(Instance). This method returns a double array with the probability for each class.
我 运行 遇到的问题是 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");
}
并抛出一个
Index out of bounds
错误。
我还移动了 clsLabel
的创建,因为显然当数据类型更改时它无法再找到该符号,除非我将它移动到 for
循环内。
假设您的输出类似于枢轴 table,其中 class 标签作为列,并且从您的 classfier I 返回的每个 class 的得分假设,您需要遍历数组并为每个值创建一个字段,或者只列出这些值。我不知道 double[] 数组中的值如何与 class 标签相关联,但是您必须以某种方式建立这种关联。 也许如果 classifier 不能 classify,它 returns 一个空数组,这就是你得到 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 个类别,例如 "spam" 和 "not spam")以下工作:
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();