Я пытаюсь классифицировать экземпляр в java, используя библиотеку weka и обучающие онлайн.
Я построил модель на своем устройстве и загрузил эту модель с диска, используя этот код.
public void makeModel() throws Exception
{
ArffLoader loader = new ArffLoader();
loader.setFile(new File("data.arff"));
Instances structure = loader.getDataSet();
structure.setClassIndex(1);
// train NaiveBayes
NaiveBayesMultinomial n = new NaiveBayesMultinomial();
FilteredClassifier f = new FilteredClassifier();
StringToWordVector s = new StringToWordVector();
s.setUseStoplist(true);
s.setWordsToKeep(100);
f.setFilter(s);
f.setClassifier(n);
structure.numAttributes();
f.buildClassifier(structure);
Instance current;
Evaluation eval = new Evaluation(structure);
eval.crossValidateModel(f, structure, 10, new Random(1));
System.out.println(eval.toSummaryString("\nResults\n======\n", false));
// output generated model
//System.out.println(f);
ObjectOutputStream oos = new ObjectOutputStream(
new FileOutputStream("classifier.model"));
oos.writeObject(f);
oos.flush();
oos.close();
}
------------------------ Output-------------
Правильно классифицированные экземпляры 20158 79.6948% Неверно классифицированные экземпляры 5136 20.3052% Статистика Каппы 0.6737 Средняя абсолютная ошибка 0.0726 Средняя квадратичная ошибка 0.2025 Относительная абсолютная ошибка 38.7564% Корневая относительная ошибка квадрата 66.1815% Покрытие случаев (уровень 0.95) 96.4142% Среднее значение. размер региона (уровень 0.95) 27.7531% Общее количество экземпляров 25294
Затем я использовал ту же модель для классификации немеченного экземпляра.
public void classify() throws Exception
{
FilteredClassifier cls = (FilteredClassifier) weka.core.SerializationHelper.read("classifier.model");
Instances unlabeled = new Instances(
new BufferedReader(
new FileReader("test.arff")));
// set class attribute
unlabeled.setClassIndex(0);
// create copy
Instances labeled = new Instances(unlabeled);
// label instances
for (int i = 0; i < unlabeled.numInstances(); i++) {
System.out.println(labeled.instance(i).classValue());
System.out.print(", actual: " + labeled.classAttribute().value((int)labeled.instance(i).classValue()));
double clsLabel = cls.classifyInstance(unlabeled.instance(i));
labeled.instance(i).setClassValue(clsLabel);
System.out.println(", predicted: " + labeled.classAttribute().value((int) clsLabel));
}
// save labeled data
System.out.println("ended");
}
------------------------ Output------------- --------------
1.0, актуально: Bud1 - это новый новый string.txtIlocblob R (?????? E? DSDB '@? @, Предсказал: * WEKA * DUMMY * STRING * FOR * STRING * ATTRIBUTES *, actual: This - новая новая строка, предсказанная: * WEKA * DUMMY * STRING * FOR * STRING * ATTRIBUTES * закончился
Тем не менее, моя ошибка заключается в том, что предсказанный на самом деле * WEKA * DUMMY * STRING * FOR * STRING * ATTRIBUTES *, когда он должен был дать мне метку класса.
При сохранении классификатора также сохраняются экземпляры (только заголовок, данные не требуются):
Instances instancesSample = new Instances(structure, 0);
instancesSample.setClassIndex(1);
...
ObjectOutputStream oos = new ObjectOutputStream(
new FileOutputStream("classifier.model"));
oos.writeObject(f);
oos.writeObject(instancesSample);
oos.flush();
oos.close();
После загрузки модели загружайте сохраненные экземпляры как instancesSample
. При классификации:
ObjectInputStream objectInputStream = new ObjectInputStream(new BufferedInputStream(new FileInputStream("classifier.model")));
FilteredClassifier cls = (FilteredClassifier)= (Classifier) objectInputStream.readObject();
Instances instancesSample = (Instances) objectInputStream.readObject();
objectInputStream.close();
int classIndex = 1;
Instances ins = unlabeled[i];
double clsLabel = cls.classifyInstance(ins);
String prediction = instancesSample.attribute(classIndex).value((int) clsLabel));
System.out.println(", predicted: " + prediction);
Я добавил эти строки в свой метод классификации.
ArffLoader loader = new ArffLoader();
loader.setFile(new File("data.arff"));
Instances structure = loader.getDataSet();
structure.setClassIndex(1);
Чтобы получить метку класса, я изменил ее на это
System.out.println(", predicted: " + structure.classAttribute().value((int) clsLabel));
Instances structure
в файл. Вот о чем я говорю.