提高单个样本的 SVC 预测性能
Posted
技术标签:
【中文标题】提高单个样本的 SVC 预测性能【英文标题】:Improving SVC prediction performance on single samples 【发布时间】:2014-02-21 01:44:56 【问题描述】:我有用于文本分类的大型 SVC 模型(~50Mb cPickles),我正在尝试在生产环境中使用它们的各种方法。对文档批次进行分类效果非常好(使用predict
和predict_proba
,每分钟大约可以处理1k 个文档)。
但是,对单个文档的预测是另一回事,正如this question 的评论中所解释的那样:
你是在批量做预测吗?不幸的是,SVC.predict 方法会产生大量开销,因为它必须重建类似于训练算法产生的 LibSVM 数据结构,浅拷贝支持向量,并将测试样本转换为 LibSVM 格式可能与 NumPy/SciPy 格式不同。因此,对单个样本的预测必然会很慢。 – larsmans
我已经将 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))
【问题讨论】:
不要使用SVC
进行文本分类,不值得。
嗨,我明白你的意思,但我应该指定它是一个多类情感分类(非常不同的类大小)。目前,我正在努力达到最高精度。到目前为止,带有 RBF 内核的 SVC 的性能优于其他所有分类器,尽管差距很小(例如 SVC 0.898、PassiveAggressiveClassifier 0.868、MultinomialNB 0.837)。然而,SVC 在很大程度上优于最小类别的竞争(例如 F1 SVC 0.84、PAC 0.76、MNB 0.68)。如果 SVC 对单个文档的处理速度稍微快一点,我看不出有任何理由不将它用于我当前的数据。
【参考方案1】:
不能提前构造LibSVM数据结构。当对文档进行分类的请求到达时,您会获取文档的文本,从 if 中制作一个向量,然后才转换为 LibSVM 格式,以便您做出决定。
LinearSVC
应该比带有线性内核的SVC
快得多,因为它使用liblinear
。如果不会过多降低性能,您可以尝试使用不同的分类器。
【讨论】:
当然,您无法避免处理您应要求获得的一份文件。但是,取决于样本数量的性能差异如此之大,以至于我仍然想知道是否可以提前做点什么。例如,在每个文档上同时调用predict
和 predict_proba
:100 个文档 5.6157s、10 个文档 0.9705s、2 个文档 0.4969s、1 个文档 0.4551s
更改分类器不是问题的一部分。
LinearSVC
只是SVC
的优化版本,所以你并没有真正改变分类器。 ***.com/questions/11508788/…
您知道LinearSVC
和SVC
选项之间的区别吗(阅读:非线性内核)?我再说一遍:这不是我的问题的一部分,无需建议更改分类器。【参考方案2】:
我可以看到三种可能的解决方案。
自定义服务器
这不是“加热”任何东西的问题。简单地说 - 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 标度,但它仍然是可能的。
【讨论】:
非常有帮助,谢谢。我认为分批是目前的解决方案,但我会尽快尝试分类:-)以上是关于提高单个样本的 SVC 预测性能的主要内容,如果未能解决你的问题,请参考以下文章
R语言使用线性回归模型来预测(predict)单个样本的目标值(响应值response)实战
训练准确度提高但验证准确度保持在 0.5,并且模型为每个验证样本预测几乎相同的类别
详解支持向量机-SVC真实数据案例:预测明天是否会下雨-探索标签和处理异常值菜菜的sklearn课堂笔记
R语言基于库克距离统计量识别(Cook’s distance)对于回归模型性能或者预测影响(Influential observation)很大的观测样本可视化库克距离并添加阈值线识别影响力大的样本
R语言基于库克距离统计量识别(Cook’s distance)对于回归模型性能或者预测影响(Influential observation)很大的观测样本可视化库克距离并添加阈值线识别影响力大的样本