2014-10-20 143 views
3

我一直在这一段时间卡住了。 OpenCV的SVM实现似乎不适用于线性内核。我相当肯定代码中没有错误:当我将kernel_type更改为RBF或POLY时,保持其他所有内容都是正常的,它可以工作。OpenCV线性SVM不训练

我说它不起作用的原因是,我保存生成的模型并检查出来。它显示支持向量计数为1.在RBF或多项式内核中不是这种情况。

代码本身没有什么特别之处,我之前使用过OpenCV的SVM实现,但从来没有线性内核。我尝试在POLY内核中将degree设置为1,并且它导致相同的模型。这让我相信这里有些东西是错误的。

的代码结构,如果需要的话:

Mat trainingdata; //acquire from files. done and correct. 
Mat testingdata;  //acquire from files. done and correct again. 
Mat labels;   //corresponding labels. checked and correct. 

SVM my_svm; 
SVMParams my_params; 
my_params.svm_type = SVM::C_SVC; 
my_params.kernel_type = SVM::LINEAR; //or poly, with my_params.degree = 1. 
my_param.C = 0.02; //doesn't matter if I set it to 20000, makes no difference. 

my_svm.train(trainingdata, labels, Mat(), Mat(), my_params); 
//train_auto(..) function with 10-fold cross-validation takes the same time as above (~2sec)! 
Mat responses; 
my_svm.predict(testingdata, responses); 
//responses matrix is all wrong. 

我有从其它类中的一个类和600 500个样本进行测试,和正确的分类我得到有:1/500和600分之597。

最疯狂的部分: 我已经做了相同的实验与libSVM的MATLAB包装相同的数据,它的工作原理。只是试图做一个OpenCV版本。

+0

你确定数据是线性可分的吗?它与更好的内核一起工作的事实强烈地暗示了非线性可分的数据......您是否正在使用线性内核来训练libSVM? – 2014-10-20 06:16:25

+0

你知道SVM的公式吗?将C设置为0.02或20000时应该有所不同。请确保正确设置。所有参数不能相同。你也应该设置epsilon参数为0.001,默认值是别的AFAIK。最后一件事,当你运行'train_auto()'而不是'train()'时会发生什么? – guneykayim 2014-10-20 06:51:08

+1

尝试适应标准示例示例/ cpp/points_classifier.cpp还有svm分类器。我检查过它,它工作。 – 2014-10-20 12:49:55

回答

2

这不是一个错误,你总是只能得到一个支持向量与线性CvSVM

OpenCV将线性SVM优化到一个支持向量。
这里的想法是支持向量定义了分类边界,并且做实际的分类只需要分离超平面并且它可以仅由一个向量定义。

参数C并不重要,如果您的训练数据是线性可分的。也许这是你的情况。

+0

我不明白如何分离超平面_needs_只有一个支持向量。此外,我之前使用过线性支持向量机,并且获得了许多支持向量(这与支配和泛化的思想很相符)。 – 2015-04-28 14:27:14

+0

而'C'则适用于噪音会影响分类的情况;噪音的存在并不是一个巨大的假设(至少在这种情况下)。 – 2015-04-28 14:29:35

+0

当svm正在训练时,它会使用一定数量的支持向量,位于边缘或内部(如果我们使用“软”边距)。但是当opencv存储训练好的分类器时 - 它所需要的唯一信息只有一个向量(垂直于超平面),它定义了分辨超平面。 http://www.songho.ca/math/plane/plane。html – Temak 2015-04-28 14:37:36