我有大型SVC模型(~50Mb cPickles)用于文本分类,我正在尝试各种方法在生产环境中使用它们。对批量文档进行分类非常有效(使用predict
和predict_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))
答案 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
快得多。如果不会降低性能,可以尝试使用其他分类器。