OpenCV 3.1.0:保存和加载训练的SVM [英] OpenCV 3.1.0: Save and load trained SVMs

查看:2283
本文介绍了OpenCV 3.1.0:保存和加载训练的SVM的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

目前,我试图训练不同的SVM来识别不同的情绪。例如,为了识别情绪快乐,我训练一个SVM与幸福的人的图像作为阳性和图像,人们表达其他情绪,如愤怒,恐惧,厌恶,...作为负面。图像存储在我已在训练部分和测试部分中分区的数据库中。



当我训练SVM时,我立即使用它们来测试精度数据库的测试图像和这工作正常。但我也保存了训练有素的SVM,因为我想在另一个程序中使用它们,并且不想在每次启动其他程序时重新训练它们。



加载SVM在其他程序,但结果是非常糟糕。精度接近零百分比。所以我试图保存和immedialty负载SVM在训练计划,但在这里的准确性现在接近零百分之。



搜索一段时间后,我发现如果我已经加载SVM,并打印SVM类型,内核类型和支持向量,他们是相同的在SVM .xml文件。所以我认为问题是预测不是以正确的方式执行。我也不知道如果我保存我的SVMs,并以适当的方式加载它们。



目前我尝试搜索解决方案,但没有取得任何成功。我尝试的一些链接是:



训练SVM并使用OpenCV 3.0保存



如何加载先前存储的svm分类?



加载训练SVM - Emgu 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]);

//测试SVMs
data_file.open(filenameLabelsTestingImages [i]);
data_file<< Number\\\
;
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 {
testing_one_image_mat.at< float>(0,k)= test_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();

所以这个工作正常,直到我改变代码保存SVMs,然后再次加载它们为预测如下

  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<< 类型是< svmNew-> getType()<< endl;
// cout<< 内核类型是< svmNew-> getKernelType()<< endl;
// cout<< 支持向量是< svmNew-> getSupportVectors()<< endl;

//测试SVMs
data_file.open(filenameLabelsTestingImages [i]);
data_file<< Number\\\
;
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 {
testing_one_image_mat.at< float>(0,k)= test_mat.at< float>(j,k) ;
}

// int value_svm = svm - >预测(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为每个测试的SVM创建一个.txt文件。所以首先我训练和测试SVM来识别例如情绪愤怒,而测试这个SVM我使用所有的测试图像。因此,所有这些图像(1 =正/ -1 =负)的预测被写入文本文件。



参数startTest和stopTest用于验证图像,预测给出值1,在需要被识别为正的图像的范围内。在数据库的测试映射中,我通过那里的情感命令所有的图像,所以首先愤怒然后蔑视,...



2D矩阵testing_mat包含所有测试的数据



所以我的问题是,在我加载SVM后,他们不给我正确的预测。 p>

解决方案

搜索一段时间后,我发现如果我使用线性内核没有问题。因此,我可以保存和加载SVM,预测是正确的。所以我开始寻找一个为什么它为线性内核而不是其他内核工作的原因。



答案是在OpenCV 3.1中有一个错误根据在Github上发布#5054 。我试过提出的解决方案,但它仍然没有工作。最终我加载了OpenCV 2.4,现在一切正常。


At the moment I am trying to train different SVMs for the recognition of different emotions. So for example to recognize the emotion happy I train a SVM with images of happy people as positives and images where people express other emotions such as anger, fear, disgust, ... as negatives. The images are stored in a database that I have partitioned in a training section and testing section.

When I have trained the SVMs, I immediatly use them to test the accuracy on the test images of the database and this works fine. But I also save the trained SVMs because I would like to use them in another programm and don't want to retrain them every time I start the other program.

Thus I loaded the SVMs in the other program but the results were very bad. The accuracy was near zero percent. So I tried to save and immedialty load the SVMs in the training program but also here the accuracy was now near zero percent.

After searching for a while I found out that if I have loaded the SVMs and I print the SVM type, kernel type and supportvectors that they are the same as in the SVM .xml file. So I think that the problem is that the prediction is not executed in the right way. I also don't know if I save my SVMs and load them in the appropriate way.

At the moment I have tried searching for a solution but without any success. Some of the links that I have tried are:

Train SVM and save it with OpenCV 3.0

How to load previously stored svm classifier?

Load Trained SVM – Emgu CV

opencv 3 (C++) auto trained SVM loading issue

The code that I use to train the SVMs and to test them immediately without loading them again is:

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();

So this works fine until I change the code to save the SVMs first and then load them again for prediction as follow

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();

The array svmSaveNames contains strings with names for saving the different SVMs like svm_anger.xml, svm_contempt.xml, ...

I use the variable data_file to create a .txt file for every SVM that is tested. So first I train and test the SVM to recognize for example the emotion anger and while testing this SVM I use all the test images. So the prediction of all those images (1 = positive / -1 = negative) is written to a textfile.

The parameters startTest and stopTest are used to verify if the positive images, prediction gives value 1, is in the range of the images that are needed to be recognized as positive. In the testing map of the database I ordered all the images by there emotion so first anger then contempt,...

The 2D matrix testing_mat contains the data from all the test images that is given to the SVM to predict the emotion.

So my problem is that after I have loaded the SVMs they don't give me the right prediction.

解决方案

After searching for a while I found out that if I use a linear kernel there is no problem at all. So then I can save and load the SVM and the prediction is correct. So I started to search for a reason why it works for the linear kernel and not for the other kernels.

The answer is that there is a bug in OpenCV 3.1 according to issue #5054 on Github. I tried the proposed solution but it still didn't work. Eventually I donwloaded OpenCV 2.4 and now everything works well.

这篇关于OpenCV 3.1.0:保存和加载训练的SVM的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆