我正在编写一个使用SVM对某些图像(特别是这些)进行分类的应用程序。我的Matlab实现效果很好。使用SIFT词袋方法,我能够在线性核下获得接近100%的准确率。
出于速度和可移植性的原因,我需要在C++中实现这个功能,因此我尝试使用了libsvm和dlib。我尝试了多种SVM类型(c_svm, nu_svm, one_class)和多种核函数(线性、多项式、rbf)。我能达到的最佳准确率约为50% – 即使是在我训练过的相同样本上。我已经确认我的特征生成器是正常工作的,因为当我将C++生成的特征导出到Matlab并在这些特征上进行训练时,我再次能够获得接近完美的结果。
Matlab的SVM实现有什么神奇之处吗?有没有常见的陷阱或我可以调查的领域来解释我观察到的行为?我知道这有点模糊,但问题的一部分是我不知道该去哪里。如果有其他我可以提供的有用信息,请在评论中告诉我。
回答:
Matlab版本的库并没有什么神奇之处,只是它在Matlab中运行,这使得你更难犯错。
检查清单:
- 你是否对数据进行了归一化,使所有值在0到1之间(或-1到1之间),无论是线性归一化还是使用均值和标准差?
- 你是否在寻找一个好的C值(或者在RBF核的情况下是C和gamma)?是否进行了交叉验证或在保留集上进行?
- 你确定你处理了NaN和其他浮点数问题吗?Matlab在这方面隐藏得很好,C++则不然。
- 是否可能是你加载数据的方式不正确,比如将”%s”读入double中,从而给输入数据增加了噪声?
- 是否可能是libsvm/dlib期望数据以行主序排列而你发送的是列主序(或反之亦然)?Matlab几乎不可能犯这种错误,C++则不然。
- 32位和64位的兼容性问题,库的一个版本与另一个版本编译的可执行文件不匹配?
其他一些事情:
- 在Matlab中,你是否在不知不觉中将类别(y)泄露到预处理中?没人会故意这样做,但我见过这种情况发生。如果你将几乎任何f(y)作为特征,你每次都会得到几乎100%的准确率。
- 有时候,通过在C++和Matlab中训练前将数据打印到文件中来验证一切在数值上是否完全相同会有所帮助。