cvSVM 训练对 HOGDescriptor 产生较差的结果

Posted

技术标签:

【中文标题】cvSVM 训练对 HOGDescriptor 产生较差的结果【英文标题】:cvSVM training produces poor results for HOGDescriptor 【发布时间】:2013-08-29 05:18:22 【问题描述】:

我的目标是训练一个支持向量机并获得支持向量,我可以将其插入到 opencv 的 HOGdescriptor 中进行对象检测。

我收集了 4000~ 个正数和 15000~ 个负数,我使用 opencv 提供的 SVM 进行训练。结果给了我太多的误报。(每张图像最多 20 个)我会剪掉误报并将它们添加到底片池中进行重新训练。我有时会得到更多的误报!我尝试将我的 hogdescriptor 的 L2HysThreshold 向上调整到 300,但没有显着改善。我的正面和负面池足够大吗?

SVM 训练也比预期快得多。我尝试使用大小为 2916 和 12996 的特征向量,分别使用灰度图像和彩色图像。 SVM 训练的时间从未超过 20 分钟。我使用 auto_train。我是机器学习的新手,但据我所知,使用像我这样大的数据集进行训练至少需要一天时间吗?

我相信 cvSVM 并没有做太多的学习,根据http://opencv-users.1802565.n2.nabble.com/training-a-HOG-descriptor-td6363437.html,它不适合这个目的。有 cvSVM 经验的人对此有更多意见吗?

我正在考虑使用 SVMLight http://svmlight.joachims.org/,但似乎没有办法可视化 SVM 超平面。我有哪些选择?

我使用 opencv2.4.3 并为 hogdescriptor 尝试了以下设置

hog.winSize = cv::Size(100,100);
hog.cellSize = cv::Size(5,5);
hog.blockSize = cv::Size(10,10);
hog.blockStride = cv::Size(5,5); //12996 feature vector

hog.winSize = cv::Size(100,100);
hog.cellSize = cv::Size(10,10);
hog.blockSize = cv::Size(20,20);
hog.blockStride = cv::Size(10,10); //2916 feature vector

【问题讨论】:

如果您使用的描述符是大约 3000 或 10,000 的维度,您不应该使用更多的训练数据吗?我记得,根据经验,训练数据的大小应该是问题维度的 10 倍左右。这不正确吗? 【参考方案1】:
    您的第一个描述符维度太大而无用。要形成任何可靠的 SVM 超平面,您需要至少与描述符维度相同数量的正样本和负样本。这是因为理想情况下,您需要在超平面的每个维度上分离信息。 除非您为 SVM 训练器提供偏差参数(cvSVM 中可能不提供),否则正样本和负样本的数量应该大致相同。 不能保证 HOG 是您尝试解决的问题类型的良好描述。您能否直观地确认您尝试检测的对象在所有样本中都具有独特的形状和相似的方向?例如,单一类型的花可能具有独特的形状,但是许多类型的花一起不具有相同的独特形状。竹子具有独特的形状,但可能难以与其他物体区分开来,或者在所有示例图像中的方向可能不同。 cvSVM 通常不是用于为 OpenCV HOG 训练 SVM 的工具。使用二进制形式的 SVMLight(非免费用于商业目的)或 libSVM(可以用于商业目的)。使用您的 C++/OpenCV 代码计算所有样本的 HOG,并将其以 SVMLight/libSVM 的正确输入格式写入文本文件。使用任一程序使用具有最佳C 的线性内核训练模型。通过在循环中更改C 时搜索最佳精度来找到最佳C。计算检测器向量(N+1 维度向量,其中 N 是描述符的维度),方法是查找所有支持向量,将 alpha 值乘以每个相应的支持向量,然后为每个维度添加所有生成的 alpha * 值以找到ND 向量。作为最后一个元素添加-b,其中b 是超平面偏差(您可以在来自 SVMLight/libSVM 训练的模型文件中找到它)。将此N+1 维度检测器输入HOGDescriptor::setSVMDetector() 并使用HOGDescriptor::detect()HOGDescriptor::detectMultiScale() 进行检测。

【讨论】:

感谢您的回答。你能详细说明为什么 cvSVM 不是正确的工具吗?我很好奇。 cvSVM 作为 SVM 工具没什么问题,但是如果你打算使用HOGDescriptor::detectMultiScale(),你需要一个 cvSVM 不提供的检测向量。如果您使用 cvSVM,则必须进行训练,然后对于每个测试图像,您必须手动提取滑动窗口的 HOG 特征,将其提供给 cvSVM,得到结果,重新缩放,再做一次。 HOGDescriptor 会预先计算一些 HOG,因此滑动窗口的效率更高。 似乎有人想出了如何将其从 cvSVM 中取出。你可以看到这个***.com/questions/15339657/…的答案我认为我的问题很可能是你答案中的第3点。我没有始终如一地在正面图像中对齐我的对象。在继续使用 SVMLight 之前,我将首先使用 cvSVM 尝试一组适当的正图像。感谢您的帮助【参考方案2】:

我在从 OpenCV 训练时使用 SVMLight 学习 SVM 模型有成功的结果,但没有使用过cvSVM,所以无法比较。

http://vision.ucsd.edu/~pdollar/toolbox/doc/index.html 中的 hogDraw 函数将可视化您的描述符。

【讨论】:

感谢分享。如何为 SVM 可视化超平面(经过编辑以使自己更清楚)?我想检查一下我的数据集更适合哪种内核类型。

以上是关于cvSVM 训练对 HOGDescriptor 产生较差的结果的主要内容,如果未能解决你的问题,请参考以下文章

OpenCV:如何将 HOGDescriptor::detectMultiScale() 与自定义 SVM 一起使用?

将提取的 HoG 特征输入到 CvSVM 的训练函数中

CvSVM 回归只预测整数

CvSVM 问题

如何从 CvSVM 计算置信度分数

Opencv 3 SVM 训练