2011-12-02 18 views
8

我已经在Python中使用scikits.learn训练了一堆RBF SVM,然后对结果进行了Pickled。这些是用于图像处理任务的,我想做的一件事是测试每个分类器在一些测试图像的每个像素上运行。也就是说,从以像素(i,j)为中心的窗口中提取特征向量,运行该特征向量上的每个分类器,然后移动到下一个像素并重复。这对于Python来说太慢了。如何从scikits.learn分类器中提取信息然后在C代码中使用

澄清:当我说“这太慢了......”我的意思是即使是scikits.learn使用的Libsvm底层代码太慢了。实际上,我正在为GPU编写一个手动决策函数,以便在每个像素处进行并行分类。

是否可以使用Pickle加载分类器,然后获取某种属性,描述如何从特征向量计算出决策,然后将该信息传递给我自己的C代码?在线性支持向量机的情况下,我可以提取权向量和偏向量,并将它们作为输入添加到C函数中。但是对于RBF分类器来说,等同的事情是什么?我如何从scikits.learn对象中获取这些信息?

加:首次尝试解决方案。

看起来分类器对象的属性为support_vectors_,它包含作为数组的每一行的支持向量。还有属性dual_coef_,这是一个由len(support_vectors_)系数组成的数组。从非线性SVM的标准教程看来,应该执行以下操作:

  • 从您的测试数据点计算特征向量v。这将是一个与support_vectors_的行长度相同的向量。
  • 对于i中的每一行support_vectors_,计算该支持向量与v之间的平方欧几里得距离d[i]
  • 计算t[i]作为gamma * exp{-d[i]}其中gamma是RBF参数。
  • 总结dual_coef_[i] * t[i]全部i。将scikits.learn分类器的intercept_属性的值添加到该总和中。
  • 如果总和为正,归类为1,否则归为0。

补充:编号为第9页,在此documentation link它提到,的确分类的intercept_属性包含偏项。我已经更新了上述步骤以反映这一点。

+0

文档链接中断 – ademar111190

回答

9

是的,你的解决方案看起来没问题。要将numpy数组的原始内存直接传递给C程序,您可以使用ctypes helpers from numpy或将您的C程序与cython打包在一起,并通过传递numpy数组来直接调用它(有关更多详细信息,请参阅文档http://cython.org)。然而,我不确定试图加速GPU上的预测是最简单的方法:内核支持向量机已知在预测时间较慢,因为它们的复杂性直接取决于支持向量的数量高度非线性(多模式)问题。

在预测时间更快的替代方法包括神经网络(可能比SVM只有2个超参数C和gamma更复杂或更慢)或者使用基于距离的非线性变换来转换数据原型+阈值+图像区域上的最大池(仅用于图像分类)。

最后,您还可以尝试使用NuSVC模型,其正则化参数nu直接影响拟合模型中支持向量的数量:较少的支持向量意味着更快的预测时间(检查准确性,但这将是预测速度和最终准确性之间的折衷)。

+0

感谢您的深思熟虑的答复。这个建议在后面会非常有用,但是对于当前的项目,由于其他限制,我不幸陷入了使用SVM的困境。 – ely

+0

然后,你应该看看'sklearn.svm.NuSVC'并尝试首先权衡SV的数量。 – ogrisel

+0

从我所看到的,sklearn 0.9 NuSVC()中的nu参数只给出了支持向量数的下限。当我训练时,我不断获得我的数据支持向量,除非我做的太大以至于我实际上获得更多。我看不出如何使它提供更少的支持向量。 – ely