为啥使用 SVM 线性内核的代码不能使用 RBF

Posted

技术标签:

【中文标题】为啥使用 SVM 线性内核的代码不能使用 RBF【英文标题】:Why working code with SVM Linear Kernel not working with RBF为什么使用 SVM 线性内核的代码不能使用 RBF 【发布时间】:2019-12-19 10:05:18 【问题描述】:

当我使用 SVM 的 trainAuto 方法时,我得到 getKernelType() 的值 2,但是当我在代码中使用 RBF 时,它会训练我的文件并输出 XML 文件。

svm = cv2.ml.SVM_create()
svm.setType(cv2.ml.SVM_C_SVC)
svm.setKernel(cv2.ml.SVM_RBF)
svm.setGamma(0.0025)
svm.setC(0.5)
svm.train(samples, cv2.ml.ROW_SAMPLE, labels)
svm.save('svm_data.xml')

以上代码对我有用。但是当我用下面的代码移动到预测部分时

hog = cv2.HOGDescriptor((100,200), (16,16), (8,8), (8,8), 9)
svm = cv2.ml.SVM_load('svm_data.xml')
sv = svm.getSupportVectors()
rho, alpha, svidx = svm.getDecisionFunction(0)
svm_new = np.append(sv, -rho)
hog.setSVMDetector(svm_new)

显示低于错误

error: (-215:Assertion failed) checkDetectorSize() in function 'cv::HOGDescriptor::setSVMDetector'

但是当我用 LINEAR 更改 RBF 时它在预测部分对我有用。

当我检查时

print (hog.checkDetectorSize())
print (hog.getDescriptorSize())

它返回 True 用于 DetectorSize 和 26676 用于 DescriptorSize

【问题讨论】:

【参考方案1】:

OpenCV 无法接受线性内核以外的 SVM。

首先,official documentation 说:

setSVMDetector()

virtual void cv::HOGDescriptor::setSVMDetector (InputArray _svmdetector)

参数

线性 SVM 分类器的

_svmdetector 系数。

很明显,您只将 SVM 的系数(作为单个数组)传递给 HOGDescriptor,而不是 种类(最常见的是线性、RBF 和多项式)和/或特定于它的参数(多项式的次数或 RBF 的伽马)。所以底层的 OpenCV 检测器无法确定内核的种类。而且它不必这样做,因为唯一实现的就是线性的。

此外,请阅读this 和this 问题。

【讨论】:

但是线性给出的结果并不好用 HOG 虽然它应该是 这意味着我必须将svm.setType(cv2.ml.SVM_C_SVC) 更改为Regression with Linear SVM? SVM.C_SVR_EPS ? 我不认为回归/分类模式对这里的结果有一些影响。这是结果解释的问题:在一种情况下,您与决策线保持距离,在另一种情况下,您只对它的符号感兴趣。在这两种情况下,阿尔法都是相同的。你可以尝试改变它,但我怀疑它会改变什么。至于性能低下,请确保您在 HOG 描述符上进行训练,而不是在原始图像上进行训练 see example This 是我使用 HOG 进行训练的方式,这是最***的代码

以上是关于为啥使用 SVM 线性内核的代码不能使用 RBF的主要内容,如果未能解决你的问题,请参考以下文章

在 python scikit-learn 中,RBF 内核的性能比 SVM 中的线性差得多

SVM的类型和核函数选择

OpenCV 线性 SVM 未训练

SVM 自定义 RBF 内核 IndexError

具有不平衡数据的 SKlearn SVM RBF

在 SVM 中使用带有卡方距离度量的 RBF 内核