OpenCV 3.1.0:保存并加载经过训练的SVM
OpenCV 3.1.0: Save and load trained SVMs
目前,我正在尝试训练不同的SVM来识别不同的情绪。例如,为了识别快乐的情绪,我训练了一个SVM,其中快乐的人的图像是积极的,人们表达其他情绪的图像,如愤怒、恐惧、厌恶。。。作为底片。这些图像存储在一个数据库中,我将该数据库划分为训练部分和测试部分。
当我训练SVM时,我会立即使用它们来测试数据库测试图像的准确性,这很好。但我也保存了经过训练的SVM,因为我想在另一个程序中使用它们,不想每次启动另一个项目时都对它们进行再培训。
因此,我在另一个程序中加载了SVM,但结果非常糟糕。准确率接近零。因此,我试图在训练计划中保存并立即加载SVM,但在这里,准确率现在接近零。
搜索了一段时间后,我发现如果我加载了SVM,并打印了SVM类型、内核类型和支持向量,它们与SVM.xml文件中的相同。所以我认为问题是预测没有以正确的方式执行。我也不知道我是否保存了我的SVM并以适当的方式加载它们。
目前,我试图寻找解决方案,但没有成功。我尝试过的一些链接是:
训练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]);
// Test SVMs
data_file.open(filenameLabelsTestingImages[i]);
data_file << "Numbern";
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 << "Numbern";
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_despe.xml…
我使用变量data_file为每个测试的SVM创建一个.txt文件。因此,首先我训练和测试SVM来识别情绪愤怒,在测试SVM时,我使用了所有的测试图像。因此,所有这些图像的预测(1=正/-1=负)都被写入一个文本文件。
参数startTest和stopTest用于验证阳性图像(预测值为1)是否在需要识别为阳性的图像范围内。在数据库的测试图中,我按情绪顺序排列了所有图像,所以先是愤怒,然后是蔑视,。。。
2D矩阵testing_mat包含来自所有测试图像的数据,这些数据被提供给SVM以预测情绪。
所以我的问题是,在我加载SVM之后,他们没有给我正确的预测。
经过一段时间的搜索,我发现如果我使用线性内核,那么根本没有问题。这样我就可以保存并加载SVM,并且预测是正确的。所以我开始寻找为什么它适用于线性内核而不适用于其他内核的原因。
答案是,根据Github上的问题#5054,OpenCV 3.1中存在一个错误。我尝试了提议的解决方案,但仍然没有奏效。最终我下载了OpenCV2.4,现在一切都很好。
- 在 SVM-Struct 中未定义对 sqrt 的引用(已使用 -lm)
- 为什么根据测量位置测量经过的时间时会有很大的不同?
- 如何将经过训练的机器学习模型保存在python中并将其加载到C++中进行预测?
- 经过最后一个数组元素末尾的指针是否应该等于超过整个数组末尾的指针?
- 是否存在经过认证(ISO 26262或类似)C++标准库?
- 使用 SVM 进行分类,使用来自 Bag of Word 的词汇构建
- SVM 规模:找不到命令
- 在c++中运行经过训练的keras模型
- const-ref传递的模板化参数是否经过优化,以便在足够小时按值传递
- 将svm分类器设置为HOG检测器
- 在不使用经过训练的模型的情况下检测/分割面部和面部特征:openCV C++
- C/C++ 经过的流程周期,不包括断点处
- 如何在不同的平台/技术中使用经过训练的神经网络?
- 如何比较两个经过的时间?
- 为什么这个经过的时间(帧时间)计算会锁定我的游戏
- SVM 训练时间是否取决于输入数据的内容?
- 如何隐藏TensorFlow.js代码和经过训练的模型
- OPENCV 3.4.1获取经过定制训练的线性SVM HOG DETECTMULTISCALE的原始形式
- 如何使用C_API导入经过训练的 tf.contrib.learn.dnnclassifier
- OpenCV 3.1.0:保存并加载经过训练的SVM