2017-01-30 1 views
1

Я написал программу на Java с использованием библиотеки WEKA, чтоИзменение Java код, который записывает двойной CSV записать двойной [] в CSV (использование прецедентного = библиотека ВЕКА)

  1. тренирует алгоритм классификации
  2. прогонов прогнозы на немеченом наборе данных с использованием обученного алгоритма
  3. выписывает результаты в файл .csv

проблема заключаются в том, что она в данный момент записывает результаты дискретной классификации (т.е. whic h, алгоритм догадывается, что строка попадает в). Я хочу записать вероятность данного класса (например, если я классифицирую строки как «спам» или «не спам», тогда я хочу, чтобы вероятность спама была результатом).

Я понимаю, что для этого мне нужно использовать distributionForInstance вместо classifyInstance в моем коде. От WEKA:

Если вы заинтересованы в распределении по всем классам, используйте метод 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();  
}  
} 

Сейчас код я работаю имеет следующее:

и бросает

Индекс за пределами

погрешность.

Я также переместил создание clsLabel, потому что, видимо, он больше не мог найти символ, когда тип данных изменился, если только я не переместил его в цикл for.

+0

на основе беглого взгляда, его можно индексы не выстраиваются в очередь, так что' i' может причинить вам выйти за пределы. Функция возвращает массив результатов, а не один результат, хранящийся в индексе 'i'. Вам нужно будет пройти через результирующий набор, чтобы получить то, что вы ожидаете. 'for (double d: clsLabel) {write (Double.toString (d))}' – Brendan

+1

@HackR (ну, он обрезает ваше имя при использовании «-»). Возможно, это не все, но я считаю, что это начало. Если это сработает, я переведу свой комментарий как ответ. – Brendan

+0

@Brendan Update - да, это полностью сработало! :) Спасибо –

ответ

1

Rewuring мой комментарий.

В результате вы получите от 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();  
+0

Спасибо большое. Единственное, что я делаю по-другому прямо сейчас, это то, что я положил новую строку в цикл. Поскольку в строке есть 2 класса, это дает мне 2x столько строк, сколько мне нужно, но я могу исправить этот бит довольно легко. –

1

Предполагая, что ваш вывод будет чем-то вроде сводной таблицы, с метками класса в виде столбцов и оценкой для каждого класса, возвращаемого из вашего класса, я полагаю, вам нужно будет перебрать массив и сделать поле для каждого значение или просто перечислить значения. Я не знаю, как значения в массиве double [] соотносятся с метками класса, но каким-то образом вам придется сделать эту связь. Возможно, если классификатор не может классифицировать, он возвращает пустой массив, поэтому вы получаете исключение IOOB.

+0

Спасибо. Похоже, вы и Брендон описываете одно и то же. Я даю ему попробовать. ** Обновление **: Это правильно. Код в ответе Брендона упростил тест, поэтому я буду отмечать его как ответ, но я тоже продолжу ваше голосование. Еще раз спасибо. –

Смежные вопросы