В данный момент я пытаюсь тренировать разные SVM для распознавания разных эмоций. Так, например, чтобы распознать эмоцию счастливой, я тренирую SVM с изображениями счастливых людей как позитива и изображений, где люди выражают другие эмоции, такие как гнев, страх, отвращение, … как негативы. Изображения хранятся в базе данных, которую я разделил на разделы обучения и тестирования.
Когда я обучаю SVM, я сразу же использую их для проверки точности тестовых изображений базы данных, и это прекрасно работает. Но я также сохраняю обученные SVM, потому что я хотел бы использовать их в другой программе и не хочу переучивать их каждый раз, когда я запускаю другую программу.
Таким образом, я загрузил SVM в другую программу, но результаты были очень плохими. Точность была около нуля процентов. Поэтому я попытался сохранить и немедленно загрузить SVM в программу обучения, но и здесь точность была теперь около нуля процентов.
После некоторого поиска я обнаружил, что если я загрузил SVM и напечатал тип SVM, тип ядра и векторы поддержки, они были такими же, как в файле .xml SVM. Поэтому я думаю, что проблема в том, что прогноз не выполняется правильно. Я также не знаю, сохраняю ли я свои SVM и загружаю ли их соответствующим образом.
В данный момент я пытался найти решение, но безуспешно. Некоторые из ссылок, которые я пробовал:
Обучите SVM и сохраните его с OpenCV 3.0
Как загрузить ранее сохраненный классификатор svm?
Загрузить тренированный SVM — Эмгу CV
opencv 3 (C ++) автоматически обучаемая проблема загрузки SVM
Код, который я использую для обучения SVM и их немедленного тестирования без повторной загрузки:
trainData = ml::TrainData::create(training_mat, ROW_SAMPLE, label_mat);
svm = SVM::create();
svm->setType(SVM::C_SVC);
svm->setKernel(SVM::RBF);
svm->trainAuto(trainData);
svm->save(svmSaveNames[i]);
// Test SVMs
data_file.open(filenameLabelsTestingImages[i]);
data_file << "Number\n";
startTest = stopTest;
stopTest = startTest + emotionCountersTesting[i];
int numberRightClassified = 0;
int numberClassified = 0;
for (int j = 0; j < numberOfTestImg; j++)
{
cv::Mat testing_one_image_mat(1, numberOfFeatures, CV_32F);
for (int k = 0; k < numberOfFeatures; k++)
{
testing_one_image_mat.at<float>(0, k) = testing_mat.at<float>(j, k);
}
int value_svm = svmNew->predict(testing_one_image_mat);
if (value_svm == 1)
{
if (j >= startTest && j < stopTest)
{
numberRightClassified++;
}
numberClassified++;
}
data_file << value_svm << endl;
}
data_file.close();
Так что это работает нормально, пока я не изменю код, чтобы сначала сохранить SVM, а затем снова загрузить их для прогнозирования, как следует
trainData = ml::TrainData::create(training_mat, ROW_SAMPLE, label_mat);
svm = SVM::create();
svm->setType(SVM::C_SVC);
svm->setKernel(SVM::RBF);
svm->trainAuto(trainData);
svm->save(svmSaveNames[i]);
Ptr<SVM> svmNew = SVM::create();
svmNew = SVM::load<SVM>(svmSaveNames[i]);
//cout << "The type is " << svmNew->getType() << endl;
//cout << "The kernel type is " << svmNew->getKernelType() << endl;
//cout << "The support vectors are " << svmNew->getSupportVectors() << endl;
// Test SVMs
data_file.open(filenameLabelsTestingImages[i]);
data_file << "Number\n";
startTest = stopTest;
stopTest = startTest + emotionCountersTesting[i];
int numberRightClassified = 0;
int numberClassified = 0;
for (int j = 0; j < numberOfTestImg; j++)
{
cv::Mat testing_one_image_mat(1, numberOfFeatures, CV_32F);
for (int k = 0; k < numberOfFeatures; k++)
{
testing_one_image_mat.at<float>(0, k) = testing_mat.at<float>(j, k);
}
//int value_svm = svm -> predict(testing_one_image_mat);
int value_svm = svmNew->predict(testing_one_image_mat);
if (value_svm == 1)
{
if (j >= startTest && j < stopTest)
{
numberRightClassified++;
}
numberClassified++;
}
data_file << value_svm << endl;
}
data_file.close();
Массив svmSaveNames содержит строки с именами для сохранения различных SVM, таких как svm_anger.xml, svm_contempt.xml, …
Я использую переменную data_file для создания файла .txt для каждого проверяемого SVM. Итак, сначала я тренируюсь и проверяю SVM, например, чтобы распознать эмоциональный гнев, и во время тестирования этого SVM я использую все тестовые изображения. Таким образом, прогноз всех этих изображений (1 = положительный / -1 = отрицательный) записывается в текстовый файл.
Параметры startTest и stopTest используются для проверки того, находится ли положительное изображение, предсказание дает значение 1, в диапазоне изображений, которые необходимо распознать как положительные. В тестовой карте базы данных я упорядочил все образы по эмоциям, поэтому сначала гнев, потом презрение, …
2D matrix testing_mat содержит данные всех тестовых изображений, которые передаются SVM для прогнозирования эмоций.
Поэтому моя проблема в том, что после загрузки SVM они не дают мне правильного прогноза.
Пройдя некоторое время, я обнаружил, что если я использую линейное ядро, то это не проблема. Тогда я могу сохранить и загрузить SVM, и прогноз верен. Поэтому я начал искать причину, по которой он работает для линейного ядра, а не для других ядер.
Ответ в том, что в OpenCV 3.1 есть ошибка в зависимости от проблемы # 5054 на Github. Я попробовал предлагаемое решение, но оно все равно не сработало. В конце концов я загрузил OpenCV 2.4 и теперь все работает хорошо.
Других решений пока нет …