为什么 scikit-learn SVM.SVC() 非常慢?
Why is scikit-learn SVM.SVC() extremely slow?
我尝试使用SVM分类器训练一个大约100k样本的数据,但我发现它非常慢,甚至两个小时后没有任何反应。当数据集有大约 1k 个样本时,我可以立即得到结果。我还尝试了 SGDClassifier 和朴素贝叶斯,它们速度非常快,我在几分钟内就得到了结果。你能解释一下这个现象吗?
关于 SVM 学习的一般评论
使用非线性核的 SVM 训练,这是 sklearn 的 SVC 中的默认设置,在复杂性方面大约是:O(n_samples^2 * n_features)
link to some question with this approximation given by one of sklearn's devs. This applies to the SMO-algorithm used within libsvm,这是 sklearn 中针对此类问题的核心求解器.
当不使用内核而使用 sklearn.svm.LinearSVC (based on liblinear) or sklearn.linear_model.SGDClassifier 时,这会发生很大变化。
所以我们可以做一些数学运算来近似计算 1k 和 100k 样本之间的时间差:
1k = 1000^2 = 1.000.000 steps = Time X
100k = 100.000^2 = 10.000.000.000 steps = Time X * 10000 !!!
这只是一个近似值,可能更差或更差(例如,设置缓存大小;牺牲内存以提高速度)!
Scikit-learn具体备注
情况也可能更加复杂,因为 scikit-learn 在监狱里为我们做了很多好事。以上对classic 2-class SVM有效。如果您有机会尝试学习一些多 class 数据; scikit-learn 将自动使用 OneVsRest 或 OneVsAll 方法来执行此操作(因为核心 SVM 算法不支持此操作)。阅读 scikit-learns 文档以了解这部分内容。
同样的警告适用于生成概率:SVM 不会自然地生成最终预测的概率。因此,为了使用这些(由参数激活),scikit-learn 使用了一个名为 Platt scaling 的繁重的交叉验证过程,这也会花费很多时间!
Scikit-learn 文档
因为 sklearn 拥有最好的文档之一,这些文档中通常有很好的部分来解释类似的内容 (link):
如果您使用的是英特尔CPU,那么英特尔已经提供了解决方案。
面向 Scikit-learn 的英特尔扩展为您提供了一种加速现有 scikit-learn 代码的方法。加速是通过打补丁实现的:用扩展提供的优化版本替换现有的 scikit-learn 算法。
您应该按照以下步骤操作:
首先安装 sklearn 的 intelex 包
pip install scikit-learn-intelex
现在只需在程序顶部添加以下行
from sklearnex import patch_sklearn
patch_sklearn()
现在运行程序会比以前快很多。
您可以从以下link阅读更多相关信息:
https://intel.github.io/scikit-learn-intelex/
我尝试使用SVM分类器训练一个大约100k样本的数据,但我发现它非常慢,甚至两个小时后没有任何反应。当数据集有大约 1k 个样本时,我可以立即得到结果。我还尝试了 SGDClassifier 和朴素贝叶斯,它们速度非常快,我在几分钟内就得到了结果。你能解释一下这个现象吗?
关于 SVM 学习的一般评论
使用非线性核的 SVM 训练,这是 sklearn 的 SVC 中的默认设置,在复杂性方面大约是:O(n_samples^2 * n_features)
link to some question with this approximation given by one of sklearn's devs. This applies to the SMO-algorithm used within libsvm,这是 sklearn 中针对此类问题的核心求解器.
当不使用内核而使用 sklearn.svm.LinearSVC (based on liblinear) or sklearn.linear_model.SGDClassifier 时,这会发生很大变化。
所以我们可以做一些数学运算来近似计算 1k 和 100k 样本之间的时间差:
1k = 1000^2 = 1.000.000 steps = Time X
100k = 100.000^2 = 10.000.000.000 steps = Time X * 10000 !!!
这只是一个近似值,可能更差或更差(例如,设置缓存大小;牺牲内存以提高速度)!
Scikit-learn具体备注
情况也可能更加复杂,因为 scikit-learn 在监狱里为我们做了很多好事。以上对classic 2-class SVM有效。如果您有机会尝试学习一些多 class 数据; scikit-learn 将自动使用 OneVsRest 或 OneVsAll 方法来执行此操作(因为核心 SVM 算法不支持此操作)。阅读 scikit-learns 文档以了解这部分内容。
同样的警告适用于生成概率:SVM 不会自然地生成最终预测的概率。因此,为了使用这些(由参数激活),scikit-learn 使用了一个名为 Platt scaling 的繁重的交叉验证过程,这也会花费很多时间!
Scikit-learn 文档
因为 sklearn 拥有最好的文档之一,这些文档中通常有很好的部分来解释类似的内容 (link):
如果您使用的是英特尔CPU,那么英特尔已经提供了解决方案。 面向 Scikit-learn 的英特尔扩展为您提供了一种加速现有 scikit-learn 代码的方法。加速是通过打补丁实现的:用扩展提供的优化版本替换现有的 scikit-learn 算法。 您应该按照以下步骤操作:
首先安装 sklearn 的 intelex 包
pip install scikit-learn-intelex
现在只需在程序顶部添加以下行
from sklearnex import patch_sklearn
patch_sklearn()
现在运行程序会比以前快很多。
您可以从以下link阅读更多相关信息: https://intel.github.io/scikit-learn-intelex/