OpenCV 线性 SVM 未训练

Posted

技术标签:

【中文标题】OpenCV 线性 SVM 未训练【英文标题】:OpenCV Linear SVM not training 【发布时间】:2014-12-15 01:33:10 【问题描述】:

我已经坚持了一段时间了。 OpenCV 的 SVM 实现似乎不适用于线性内核。我相当确定代码中没有错误:当我将 kernel_type 更改为 RBF 或 POLY 时,保持其他所有内容不变,它可以工作。

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

代码本身并没有什么特别之处,我之前使用过 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.

我有一个类的 500 个样本和另一个类的 600 个样本要测试,我得到的正确分类是:1/500 和 597/600。

最疯狂的部分: 我在 libSVM 的 MATLAB 包装器上使用相同的数据进行了相同的实验,并且它可以工作。 只是试图做一个 OpenCV 版本。

【问题讨论】:

你确定数据是线性可分的吗?它与更高级的内核一起工作的事实强烈表明非线性可分数据......您是否使用线性内核训练 libSVM? 你知道SVM的公式吗?将 C 设置为 0.02 或 20000 时应该会有差异。请确保设置正确。它不能对所有参数都相同。此外,您应该将 epsilon 参数设置为 0.001,默认值是其他 AFAIK。最后一件事,当你运行 train_auto() 而不是 train() 时会发生什么? 尝试改编标准示例examples/cpp/points_classifier.cpp 还有svm分类器。我已经检查过了,它确实有效。 @SchighSchagh 我复制了我在 libSVM 中所做的实验。它在那里就像一个魅力。 @guneykayim 我知道 SVM 的公式,并且我了解 C 对模型的作用。这就是为什么我对 C 的价值没有产生任何影响感到惊讶的原因。 train_auto() 什么都不做。给我C = 1。我试过了。 【参考方案1】:

线性 CvSVM 总是只能获得一个支持向量,这不是错误。

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

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

【讨论】:

我不明白分离超平面如何需要只有一个支持向量。此外,我之前使用过线性 SVM,并获得了许多支持向量(这与过拟合和泛化的想法很好地配合)。 C 在噪声会影响分类的情况下会很有用;噪声的存在并不是一个巨大的假设(至少在这种情况下)。 当 svm 训练时,它使用一些位于边缘或内部的支持向量(如果我们使用“软”边缘)。但是当 opencv 存储经过训练的分类器时——它需要的唯一信息是一个向量(垂直于超平面),它定义了区分超平面。 songho.ca/math/plane/plane.html 是的,如果我们有噪音,C 很有用。但是如果我们没有噪声并且数据是线性可分的,那么 C 不会影响训练。 哦,是的,我同意。我不记得 nSV 用于这个实验,但我确信我见过大于一的数字。

以上是关于OpenCV 线性 SVM 未训练的主要内容,如果未能解决你的问题,请参考以下文章

OpenCV和SVM分类器在自动驾驶中的车辆检测

Opencv 3 SVM 训练

Opencv 3 SVM 训练

SVM 训练 C++ OpenCV

训练自定义 SVM 以在 OpenCV 中与 HOGDescriptor 一起使用

在 OpencV 中训练 SVM 分类器?