使用scikit Learn的SVM无限运行,永远无法完成执行


76

我正在尝试在具有595605行和5列(功能)的训练数据集和具有397070行的测试数据集上使用scikit Learn(python)运行SVR。数据已经过预处理和规范化。

我能够成功运行测试示例,但是使用我的数据集执行并使其运行了一个多小时后,我仍然看不到任何输出或程序终止。我尝试使用不同的IDE甚至从终端执行,但这似乎不是问题。我也尝试将'C'参数值从1更改为1e3。

使用scikit的所有svm实现都面临类似的问题。

我还没有等到它完成?此执行需要多少时间?

根据我的经验,它不需要几分钟。

这是我的系统配置:Ubuntu 14.04、8GB RAM,大量可用内存,第四代i7处理器


您能提供代码吗?此外,培训或测试是否需要花费大量时间?较小的训练/测试数据集怎么样?
ffriend

我只是将数据从csv文件读取到pandas数据框中,然后将其传递给scikit学习功能。就这样!在这里提供代码并没有真正的帮助
tejaskhot 2014年

6
sklearn的SVM实现包含至少3个步骤:1)创建SVR对象,2)拟合模型,3)预测值。第一步介绍正在使用的内核,这有助于更好地了解内部进程。第二步和第三步有很大的不同,我们至少需要知道其中哪一个花费了这么长时间。如果是训练,那可能没问题,因为有时学习很慢。如果正在测试,则可能存在错误,因为在SVM中进行测试确实非常快。另外,可能是CSV读取花费了很长时间,而根本没有SVM。因此,所有这些细节可能都很重要。
ffriend

我也通过svm面临同样的问题,但是有人可以告诉我规范化后需要多少时间吗?
kashyap kitchlu

Answers:


69

内核化SVM需要计算数据集中每个点之间的距离函数,这是的主要成本。距离的存储是内存的负担,因此它们是在运行中重新计算的。值得庆幸的是,大多数时候只需要最靠近决策边界的点即可。经常计算的距离存储在缓存中。如果缓存被颠簸,则运行时间将达到。On个特征 × n 3个观测值O(nfeatures×nobservations2)O(nfeatures×nobservations3)

您可以通过以下方式调用SVR来增加此缓存:

model = SVR(cache_size=7000)

通常,这是行不通的。但是,一切并没有丢失。您可以对数据进行二次采样,然后将其余数据用作验证集,也可以选择其他模型。超过200,000个观察范围,选择线性学习者是明智的。

通过近似内核矩阵并将其馈送到线性SVM,可以近似内核SVM。这使您可以在线性时间内在准确性和性能之间进行权衡。

实现此目标的一种流行方法是使用kmeans / kmeans ++找到的100个左右的群集中心作为内核功能的基础。然后将新的导出特征输入到线性模型中。这在实践中效果很好。诸如sophia-mlvowpal wabbit之类的工具就是Google,Yahoo和Microsoft的工作方式。输入/输出成为简单线性学习者的主要成本。

在大量数据中,非参数模型对大多数问题的表现大致相同。例外是结构化输入,例如文本,图像,时间序列,音频。

进一步阅读


16

SVM解决了二次优化问题。

我没有要补充的,这里没有说。我只想在Sklearn页面上发布有关SVC的链接,以阐明发生了什么事情:

该实现基于libsvm。拟合时间复杂度是样本数量的两倍以上,这使得很难扩展到具有多个10000个样本的数据集。

如果您不想使用内核,而线性SVM就足够了,那就是LinearSVR,它速度更快,因为它使用了优化方法和线性回归。不过,如果还没有进行标准化,则必须将数据标准化,因为它会将正则化应用于拦截系数,而这可能并不是您想要的。这意味着,如果您的数据平均值远非零,将无法令人满意地解决它。

您还可以使用随机梯度下降法来解决优化问题。Sklearn具有SGDRegressor功能。您必须使用loss='epsilon_insensitive'与线性SVM相似的结果。请参阅文档。我将只使用梯度下降作为最后的手段,因为这意味着需要对超参数进行大量调整,以避免陷入局部最小值。LinearSVR如果可以的话使用。


我有一个包含很多行的数据集。SVC开始占用我大约15万行数据太久了。我将您的建议与LinearSVR结合使用,一百万行只需几分钟。PS还发现LogisticRegression分类器产生的结果与LinearSVR相似(就我而言),并且速度更快。
jeffery_the_wind '17

8

您是否在预处理步骤中包括了缩放比例?运行SVM时出现此问题。我的数据集是约780,000个样本(行),具有20个特征(col)。我的训练集是〜235,000个样本。原来,我只是忘了扩展数据!如果是这种情况,请尝试将此位添加到您的代码中:

将数据缩放到[-1,1];提高SVM速度:

从sklearn.preprocessing导入MinMaxScaler
缩放比例= MinMaxScaler(feature_range =(-1,1))。fit(X_train)
X_train =缩放比例.transform(X_train)
X_test =缩放比例.transform(X_test)


2
谁能解释为什么这可以加快SVM的安装速度?
lppier

1
为什么选择MinMaxScaler而不是其他任何原因?例如StandardScaler?
raspi

@Ippier:本质上,您在减少每个选项的可能边界空间,从而使机器的工作量大大减少。
IKE

7

有了如此庞大的数据集,我认为您最好使用神经网络,深度学习,随机森林(它们出奇的好)等。

如先前的答复所述,所花费的时间与训练样本数量的三次方成正比。就测试向量的数量而言,甚至预测时间也是多项式。

如果您确实必须使用SVM,那么我建议您使用GPU来加快或减少训练数据集的大小。首先尝试数据样本(可能有10,000行),以查看数据格式或分布是否有问题。

如其他答复所述,线性内核速度更快。


3

我最近遇到了类似的问题,因为忘记了缩放数据集中的要素,而该数据集先前曾用于训练集成模型类型。谢尔比·马特洛克(Shelby Matlock)指出,无法扩展数据可能是罪魁祸首。您可以尝试sklearn中可用的其他缩放器,例如RobustScaler

from sklearn.preprocessing import RobustScaler scaler = RobustScaler() X = scaler.fit_transfrom(X)

X现在已被变换/缩放并准备好输入您想要的模型。


2

这很有道理。对于IIUC,支持向量运算的执行速度受样本数量而不是维数的约束。换句话说,它受CPU时间而不是RAM的限制。我不确定这应该花多少时间,但是我正在运行一些基准测试来找出答案。


1

让它运行一整夜或更长时间运行24小时。您的CPU使用率是多少?如果没有任何一个内核以100%的速度运行,则您有问题。可能有记忆。您是否检查过数据集是否完全适合8GB?您是否尝试过SGDClassifier?它是那里最快的之一。值得尝试一下,希望它能在一个小时左右完成。


SGDClassifier不支持内核。如果OP需要线性SVM,则建议先尝试LinearSVR。它比SVR使用线性回归库解决问题的速度快得多,并且可以保证全局最小值(与梯度下降不同)。
里卡多·克鲁兹

感谢您的评论。您能否详细说明为什么内核支持是一个问题?
迭戈

文档来看,The loss function to be used. Defaults to ‘hinge’, which gives a linear SVM.相同SGDRegressorSGDRegressor等同于使用SVR(kernel='linear')。如果这是OP想要的,那就太好了。我印象中他想将SVM与内核一起使用。如果不是这种情况,我建议他先尝试一下LinearSVR
里卡多·克鲁兹

1

尝试将数据标准化为[-1,1]。我遇到了类似的问题,归一化后一切正常。您可以使用以下方法轻松标准化数据:

from sklearn import preprocessing X_train = preprocessing.scale(X_train) X_test = preprocessing.scale(X_test)


@Archie这是对问题的答案,而不是问题。
timleathart '17

1

我遇到了这个问题,cache_size正如其他人建议的那样,这根本没有帮助。您可以看到这篇文章,并且是主要贡献者,建议您手动更改代码。

如你所知,SVC并且SVR是最优化的问题,他们停止时,误差是如此之少,其中进一步优化是徒劳的。因此,这些参数中还有另一个参数max_iter,您可以在其中设置应执行的迭代次数。

sklearn在python和e1071R和R中使用过,在不设置的情况下获得结果的速度要快得多,max_iter并且sklearn需要2-4倍的时间。我可以减少python计算时间的唯一方法是使用max_iter。它是相对于你的模型,功能,内核和超参数数量的复杂性,但对于小数据集我用4000左右的数据点,并max_iter10000结果差异不显着不惜一切,这是可以接受的。


0

我只遇到了一个数据集类似的问题,该数据集仅包含115个元素并且仅包含一个要素(国际航空公司数据)。解决方案是扩展数据。到目前为止,我错过的答案是管道的用法:

from sklearn.svm import SVR
from sklearn.preprocessing import StandardScaler, MinMaxScaler

model = Pipeline([('scaler', StandardScaler()),
                  ('svr', SVR(kernel='linear'))])

您可以model像通常的分类/回归模型一样进行训练,并以相同的方式对其进行评估。什么都没有改变,只有模型的定义。


什么Pipeline啊 您没有导入它。
Bram Vanroy

0

您需要扩展数据。缩放会将您的数据点标准化到-1到1范围,这将有助于更快地收敛。

尝试使用以下代码:

# X is your numpy data array.

from sklearn import preprocessing

X = preprocessing.scale(X)

欢迎来到Data Science SE!您能否解释一下您的建议将如何帮助OP?您建议的是对数组进行缩放。尚不清楚这如何影响或不影响scikit学习中的SVR算法。
立体声
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.