3

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

您是否在批量进行预测?不幸的是,SVC.predict 方法会产生大量开销,因为它必须重建与训练算法产生的相似的 LibSVM 数据结构,浅拷贝支持向量,并将测试样本转换为 LibSVM 格式可能与 NumPy/SciPy 格式不同。因此,对单个样本的预测必然会很慢。– 拉尔斯曼斯

我已经将 SVC 模型作为 Flask Web 应用程序提供服务,因此一部分开销已经消失(unpickling),但单个文档的预测时间仍然偏高(0.25 秒)。我查看了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))
4

2 回答 2

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 的标度,但它仍然是可能的。

于 2014-01-29T17:39:22.213 回答
1

不能提前构造 LibSVM 数据结构。当对文档进行分类的请求到达时,您会获取文档的文本,从 if 中制作一个向量,然后才转换为 LibSVM 格式,以便您做出决定。

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

于 2014-01-29T10:39:05.723 回答