Несоответствие результатов десятикратной перекрестной проверки в WEKA

Вчера я использовал 2 способа реализации 10-кратной перекрестной проверки в weka, но результаты противоречивы.

Способ 1: напрямую вызвать метод eval.crossValidateModel(),

 J48 j48 = new J48();
 j48.buildClassifier(ins);  // ins is the Instances object
 Evaluation eval = new Evaluation(ins);
 eval.crossValidateModel(j48, ins, 10, new Random(1)); // 10-fold cross validation
 ... // get results by eval.getXX(0) or eval.getXXX(1)

Способ 2: используя методы testCV() и trainCV() в каждой складке,

 ins.randomize(new Random(1)); // ins is the Instances object
 ins.stratify(10); // randomize the dataset then split into 10 folds

 for(int i=0; i<10; i++){       
    Instances trainData = ins.trainCV(10, i);
    Instances testData = ins.testCV(10, i);
    J48 j48 = new J48();
    j48.buildClassifier(trainData);

    Evaluation eval = new Evaluation(trainData);
    eval.evaluateModel(j48, testData);
    ... // get results by eval.getXX(0) or eval.getXXX(1)
 }

Согласно документам weka api, 2 вышеуказанных способа должны иметь одинаковые результаты, т. е. средние результаты (например, точность, полнота) способа 2 должны быть равны результатам способа 1. Но правда в том, что они не совпадают. то же самое, может ли кто-нибудь выяснить ошибку в моем коде или предоставить другие хорошие методы оценки? Спасибо вам всем!


person Yongfeng    schedule 22.06.2018    source источник
comment
Я также заметил, что есть некоторые решения с графическим интерфейсом для получения результатов в каждой складке Weka: результаты каждого умножения в 10-кратном CV, результаты также несовместимы с тем, который использует crossValidateModel.   -  person Yongfeng    schedule 22.06.2018


Ответы (2)


Если вы посмотрите на код метода weka.classifiers.Evaluation.crossValidateModel (в зависимости от вашей версии, объект делегата), вы увидите, что он использует метод weka.core.Instances.trainCV(int,int,Random). Кроме того, вам необходимо инициализировать объект Evaluation с априорными классами полного набора данных.

Вот обновленный код:

Evaluation eval = new Evaluation(ins);  // init evaluation
rand = new Random(1);
int numFolds = 10;  // 10-fold CV
ins.randomize(rand); // randomize the data
ins.stratify(numFolds); // stratify the randomized data for 10-fold CV
J48 template = new J48();  // classifier template for evaluation
//template.setOptions(...);  // if further options need to be set

for (int i = 0; i < numFolds; i++) {       
  Instances trainData = ins.trainCV(numFolds, i, rand);
  Instances testData = ins.testCV(numFolds, i);
  Classifier cls = AbstractClassifier.makeCopy(template);  // copy of classifier template
  cls.buildClassifier(trainData);
  eval.evaluateModel(cls, testData);  // accumulate statistics
}

... // get results by eval.getXX(0) or eval.getXXX(1)
person fracpete    schedule 23.06.2018
comment
Да, исходный код crossValidateModel() использует случайное начальное число при вызове trainCV(int,int,Random), но я пытался использовать trainCV(int,int,Random), но результаты также выходят за рамки результатов Способа 1. Другой вопрос заключается в том, что нам нужно инициализировать объект Evaluation с помощью trainData, а не ins. - person Yongfeng; 24.06.2018
comment
Согласно моим испытаниям, результаты СПОСОБА 1 и СПОСОБА 2 согласуются с результатами, полученными при использовании Weka GUI в Explorer и Модули экспериментатора соответственно. Я заметил, что на форуме Weka так много связанных вопросов, это ошибка в Weka? - person Yongfeng; 24.06.2018
comment
Experimenter и Explorer по-разному обрабатывают перекрестную проверку. Проводник объединяет результаты одного запуска перекрестной проверки в одном объекте оценки (например, в командной строке). Экспериментатор рассматривает каждую пару сгибов как отдельную оценку. Вот почему Экспериментатор может рассчитать среднее/стандартное отклонение, а Исследователь — нет. - person fracpete; 25.06.2018
comment
Я думаю, вы правы, но в официальном примере использования не используется метод случайного начального числа в trainCV() в каждом сгибе, см. CrossValidationSingleRun.java. Другой вопрос, почему вы используете метод makecopy() вместо создания экземпляра объекта J48? - person Yongfeng; 25.06.2018
comment
Это старый пример, который я написал много лет назад (когда больше занимался проектом Weka). Вещи изменились между ними. В любом случае, в настоящее время мы находимся в процессе перемещения вики. Обновлю там код. Используется метод makeCopy, поэтому вам нужно настроить классификатор только один раз. Например, если вы выполняете перекрестную проверку для получения статистики, а затем создаете окончательную модель на основе полного набора данных для развертывания. Каждый раз просто создавая копию своего шаблона методом makeCopy (и менять настройки нужно только в одном месте). - person fracpete; 26.06.2018

Way1 — это основной метод, который широко используется в графическом интерфейсе Weka, поэтому crossValidationModel() может давать такие же средние результаты с Weka Explorer, как и следующие операции.

1. Откройте программное обеспечение Weka.

2. Войдите в модуль Проводник.

3.Выберите набор данных на вкладке Предварительная обработка.

4. Выберите J48 и 10-кратную перекрестную проверку на вкладке Классификация.

5.Нажмите кнопку start, чтобы получить результаты в окне Вывод классификатора.

Way2 — это альтернативный метод, с помощью которого мы можем получить результаты каждой складки. Результаты каждого сгиба совпадают с результатами в Weka Experimenter, как и следующие операции.

  1. Откройте программное обеспечение Weka.

  2. Войдите в модуль Experimenter

  3. Нажмите кнопку Создать, чтобы создать простой эксперимент на вкладке Настройка.

  4. Установите параметры в Назначение результатов, Наборы данных и Алгоритмы.

  5. Нажмите кнопку Start на вкладке Run, результаты каждого сгиба сохраняются в файле, указанном в Назначение результатов.

В целом, эти 2 метода определенно возвращают 2 результата различия, согласно исходному коду, указанному на его офисном веб-сайте https://weka.wikispaces.com/Generating+cross-validation+folds+(Java+approach), вышеуказанные методы должны давать согласованные результаты, но на самом деле это точные напротив, возможно это баг Weka.

person Yongfeng    schedule 23.06.2018