提高单个样本的SVC预测性能

时间:2014-01-29 10:16:46

标签: python svm scikit-learn svc

我有大型SVC模型(~50Mb cPickles)用于文本分类,我正在尝试各种方法在生产环境中使用它们。对批量文档进行分类非常有效(使用predictpredict_proba每分钟大约1k个文档)。 但是,对单个文档的预测是另一个故事,正如对this question的评论中所解释的那样:

  

您是否分批进行预测?遗憾的是,SVC.predict方法会产生大量开销,因为它必须重建类似于训练算法生成的LibSVM数据结构,支持向量中的浅拷贝,并将测试样本转换为LibSVM格式可能与NumPy / SciPy格式不同。因此,对单个样本的预测必然是缓慢的。 - larsmans

我已经将SVC模型作为Flask Web应用程序提供服务,因此开销的一部分已经消失(unpickling),但单个文档的预测时间仍然偏高(0.25s)。 我查看了predict方法中的代码,但无法弄清楚是否有办法预热"预热"他们,在服务器启动时提前重建LibSVM数据结构......任何想法?

def predict(self, X):
    """Perform classification on samples in X.

    For an one-class model, +1 or -1 is returned.

    Parameters
    ----------
    X : {array-like, sparse matrix}, shape = [n_samples, n_features]

    Returns
    -------
    y_pred : array, shape = [n_samples]
        Class labels for samples in X.
    """
    y = super(BaseSVC, self).predict(X)
    return self.classes_.take(y.astype(np.int))

2 个答案:

答案 0 :(得分:3)

我可以看到三种可能的解决方案。

自定义服务器

这不是“升温”任何事情的问题。简单地说 - libSVM是C库,您需要将数据打包/解包为正确的格式。这个过程在整个矩阵上比在每一行上分别更有效。解决这个问题的唯一方法是在生产环境和libSVM之间编写更高效的包装器(你可以编写一个基于libsvm的服务器,它会在你的服务中使用某种共享内存)。不幸的是,这是现有实现可以解决的自定义问题。

批次

像缓冲查询这样的天真方法是一个选项(如果它是具有数千个查询的“高性能”系统,您可以简单地将它们存储在N元素批处理中,并将它们发送到这些包中的libSVM)。

自己的分类

最后 - 使用SVM进行分类实际上是简单任务。您不需要libSVM来执行分类。只有培训才是一个复杂的问题。获得所有支持向量(SV_i),内核(K),拉格利安乘数(alpha_i)和截距项(b)后,使用以下方法进行分类:

cl(x) = sgn( SUM_i y_i alpha_i K(SV_i, x) + b)

您可以在应用中直接编码 操作,而无需实际打包/解压缩/发送任何到libsvm。这可以加快数量级。显然 - 概率检索更复杂,因为它需要Platt的scaliing,但它仍然是可能的。

答案 1 :(得分:1)

您无法提前构建LibSVM数据结构。当一个文档分类请求到达时,你得到文档的文本,用if做一个向量,然后转换为LibSVM格式,这样你才能做出决定。

LinearSVC应该比使用SVC的线性内核的liblinear快得多。如果不会降低性能,可以尝试使用其他分类器。