在 python 中使 SVM 运行 更快
Making SVM run faster in python
使用下面的 代码 用于 python 中的 svm:
from sklearn import datasets
from sklearn.multiclass import OneVsRestClassifier
from sklearn.svm import SVC
iris = datasets.load_iris()
X, y = iris.data, iris.target
clf = OneVsRestClassifier(SVC(kernel='linear', probability=True, class_weight='auto'))
clf.fit(X, y)
proba = clf.predict_proba(X)
但这需要花费大量时间。
实际数据维度:
train-set (1422392,29)
test-set (233081,29)
我怎样才能加快速度(并行或其他方式)?请帮忙。
我已经尝试过 PCA 和下采样。
我有 6 个类。
编辑:
找到 http://scikit-learn.org/stable/modules/generated/sklearn.linear_model.SGDClassifier.html
但我希望进行概率估计,而 svm 似乎并非如此。
编辑:
from sklearn import datasets
from sklearn.multiclass import OneVsRestClassifier
from sklearn.svm import SVC,LinearSVC
from sklearn.linear_model import SGDClassifier
import joblib
import numpy as np
from sklearn import grid_search
import multiprocessing
import numpy as np
import math
def new_func(a): #converts array(x) elements to (1/(1 + e(-x)))
a=1/(1 + math.exp(-a))
return a
if __name__ == '__main__':
iris = datasets.load_iris()
cores=multiprocessing.cpu_count()-2
X, y = iris.data, iris.target #loading dataset
C_range = 10.0 ** np.arange(-4, 4); #c value range
param_grid = dict(estimator__C=C_range.tolist())
svr = OneVsRestClassifier(LinearSVC(class_weight='auto'),n_jobs=cores) ################LinearSVC Code faster
#svr = OneVsRestClassifier(SVC(kernel='linear', probability=True, ##################SVC code slow
# class_weight='auto'),n_jobs=cores)
clf = grid_search.GridSearchCV(svr, param_grid,n_jobs=cores,verbose=2) #grid search
clf.fit(X, y) #training svm model
decisions=clf.decision_function(X) #outputs decision functions
#prob=clf.predict_proba(X) #only for SVC outputs probablilites
print decisions[:5,:]
vecfunc = np.vectorize(new_func)
prob=vecfunc(decisions) #converts deicision to (1/(1 + e(-x)))
print prob[:5,:]
编辑 2:
user3914041 的回答产生了非常差的概率估计。
SVM 分类器不那么容易扩展。从文档中,关于 sklearn.svm.SVC
.
的复杂性
The fit time complexity is more than quadratic with the number of
samples which makes it hard to scale to dataset with more than a
couple of 10000 samples.
在 scikit-learn 中,您有 svm.linearSVC
可以更好地扩展。
显然它可以处理您的数据。
或者,您可以使用另一个分类器。如果您想要概率估计,我建议您使用逻辑回归。
逻辑回归还有一个优点是不需要 probability calibration 输出 'proper' 概率。
编辑:
我不知道linearSVC
复杂度,最后我在user guide:
找到了资料
Also note that for the linear case, the algorithm used in LinearSVC by
the liblinear implementation is much more efficient than its
libsvm-based SVC counterpart and can scale almost linearly to millions
of samples and/or features.
要从 linearSVC
中获取概率,请查看 this link。它与我在上面 link 编辑的概率校准指南仅几 link 秒,并且包含一种估计概率的方法。
即:
prob_pos = clf.decision_function(X_test)
prob_pos = (prob_pos - prob_pos.min()) / (prob_pos.max() - prob_pos.min())
请注意,如 link 中所示,如果不进行校准,估计值可能会很差。
如果您想尽可能坚持使用 SVC 并在整个数据集上进行训练,您可以使用在数据子集上训练的 SVC 集合来减少每个 classifier 的记录数(这显然对复杂性有二次影响)。 Scikit 支持使用 BaggingClassifier
包装器。与单个 classifier 相比,这应该会给你类似(如果不是更好的话)的准确性,而且训练时间要少得多。也可以使用 n_jobs
参数将单个 classifier 的训练设置为并行 运行。
或者,我也会考虑使用随机森林 classifier - 它本身支持 multi-class classification,它速度很快,并且在 min_samples_leaf
设置得当。
我用 10 个 SVC 的集合对 iris 数据集进行了 100 次快速测试,每个 SVC 都训练了 10% 的数据。它比单个 classifier 快 10 倍以上。这些是我在笔记本电脑上得到的数字:
单次SVC:45s
集成 SVC:3 秒
随机森林分类器:0.5s
请参阅下面我用来生成数字的代码:
import time
import numpy as np
from sklearn.ensemble import BaggingClassifier, RandomForestClassifier
from sklearn import datasets
from sklearn.multiclass import OneVsRestClassifier
from sklearn.svm import SVC
iris = datasets.load_iris()
X, y = iris.data, iris.target
X = np.repeat(X, 100, axis=0)
y = np.repeat(y, 100, axis=0)
start = time.time()
clf = OneVsRestClassifier(SVC(kernel='linear', probability=True, class_weight='auto'))
clf.fit(X, y)
end = time.time()
print "Single SVC", end - start, clf.score(X,y)
proba = clf.predict_proba(X)
n_estimators = 10
start = time.time()
clf = OneVsRestClassifier(BaggingClassifier(SVC(kernel='linear', probability=True, class_weight='auto'), max_samples=1.0 / n_estimators, n_estimators=n_estimators))
clf.fit(X, y)
end = time.time()
print "Bagging SVC", end - start, clf.score(X,y)
proba = clf.predict_proba(X)
start = time.time()
clf = RandomForestClassifier(min_samples_leaf=20)
clf.fit(X, y)
end = time.time()
print "Random Forest", end - start, clf.score(X,y)
proba = clf.predict_proba(X)
如果要确保在BaggingClassifier
中每条记录只用于训练一次,可以将bootstrap
参数设置为False。
置顶回答中简单提及;这是代码:最快的方法是通过 the n_jobs
parameter:替换行
clf = OneVsRestClassifier(SVC(kernel='linear', probability=True, class_weight='auto'))
与
clf = OneVsRestClassifier(SVC(kernel='linear', probability=True, class_weight='auto'), n_jobs=-1)
这将使用您计算机上所有可用的 CPU,同时仍执行与以前相同的计算。
您可以使用 the kernel_approximation
module 将 SVM 扩展到像这样的大量样本。
对于大型数据集,考虑改用 LinearSVC 或 SGDClassifier,可能在 Nystroem 转换器之后。
https://scikit-learn.org/stable/modules/generated/sklearn.svm.SVC.html
使用下面的 代码 用于 python 中的 svm:
from sklearn import datasets
from sklearn.multiclass import OneVsRestClassifier
from sklearn.svm import SVC
iris = datasets.load_iris()
X, y = iris.data, iris.target
clf = OneVsRestClassifier(SVC(kernel='linear', probability=True, class_weight='auto'))
clf.fit(X, y)
proba = clf.predict_proba(X)
但这需要花费大量时间。
实际数据维度:
train-set (1422392,29)
test-set (233081,29)
我怎样才能加快速度(并行或其他方式)?请帮忙。 我已经尝试过 PCA 和下采样。
我有 6 个类。 编辑: 找到 http://scikit-learn.org/stable/modules/generated/sklearn.linear_model.SGDClassifier.html 但我希望进行概率估计,而 svm 似乎并非如此。
编辑:
from sklearn import datasets
from sklearn.multiclass import OneVsRestClassifier
from sklearn.svm import SVC,LinearSVC
from sklearn.linear_model import SGDClassifier
import joblib
import numpy as np
from sklearn import grid_search
import multiprocessing
import numpy as np
import math
def new_func(a): #converts array(x) elements to (1/(1 + e(-x)))
a=1/(1 + math.exp(-a))
return a
if __name__ == '__main__':
iris = datasets.load_iris()
cores=multiprocessing.cpu_count()-2
X, y = iris.data, iris.target #loading dataset
C_range = 10.0 ** np.arange(-4, 4); #c value range
param_grid = dict(estimator__C=C_range.tolist())
svr = OneVsRestClassifier(LinearSVC(class_weight='auto'),n_jobs=cores) ################LinearSVC Code faster
#svr = OneVsRestClassifier(SVC(kernel='linear', probability=True, ##################SVC code slow
# class_weight='auto'),n_jobs=cores)
clf = grid_search.GridSearchCV(svr, param_grid,n_jobs=cores,verbose=2) #grid search
clf.fit(X, y) #training svm model
decisions=clf.decision_function(X) #outputs decision functions
#prob=clf.predict_proba(X) #only for SVC outputs probablilites
print decisions[:5,:]
vecfunc = np.vectorize(new_func)
prob=vecfunc(decisions) #converts deicision to (1/(1 + e(-x)))
print prob[:5,:]
编辑 2: user3914041 的回答产生了非常差的概率估计。
SVM 分类器不那么容易扩展。从文档中,关于 sklearn.svm.SVC
.
The fit time complexity is more than quadratic with the number of samples which makes it hard to scale to dataset with more than a couple of 10000 samples.
在 scikit-learn 中,您有 svm.linearSVC
可以更好地扩展。
显然它可以处理您的数据。
或者,您可以使用另一个分类器。如果您想要概率估计,我建议您使用逻辑回归。 逻辑回归还有一个优点是不需要 probability calibration 输出 'proper' 概率。
编辑:
我不知道linearSVC
复杂度,最后我在user guide:
Also note that for the linear case, the algorithm used in LinearSVC by the liblinear implementation is much more efficient than its libsvm-based SVC counterpart and can scale almost linearly to millions of samples and/or features.
要从 linearSVC
中获取概率,请查看 this link。它与我在上面 link 编辑的概率校准指南仅几 link 秒,并且包含一种估计概率的方法。
即:
prob_pos = clf.decision_function(X_test)
prob_pos = (prob_pos - prob_pos.min()) / (prob_pos.max() - prob_pos.min())
请注意,如 link 中所示,如果不进行校准,估计值可能会很差。
如果您想尽可能坚持使用 SVC 并在整个数据集上进行训练,您可以使用在数据子集上训练的 SVC 集合来减少每个 classifier 的记录数(这显然对复杂性有二次影响)。 Scikit 支持使用 BaggingClassifier
包装器。与单个 classifier 相比,这应该会给你类似(如果不是更好的话)的准确性,而且训练时间要少得多。也可以使用 n_jobs
参数将单个 classifier 的训练设置为并行 运行。
或者,我也会考虑使用随机森林 classifier - 它本身支持 multi-class classification,它速度很快,并且在 min_samples_leaf
设置得当。
我用 10 个 SVC 的集合对 iris 数据集进行了 100 次快速测试,每个 SVC 都训练了 10% 的数据。它比单个 classifier 快 10 倍以上。这些是我在笔记本电脑上得到的数字:
单次SVC:45s
集成 SVC:3 秒
随机森林分类器:0.5s
请参阅下面我用来生成数字的代码:
import time
import numpy as np
from sklearn.ensemble import BaggingClassifier, RandomForestClassifier
from sklearn import datasets
from sklearn.multiclass import OneVsRestClassifier
from sklearn.svm import SVC
iris = datasets.load_iris()
X, y = iris.data, iris.target
X = np.repeat(X, 100, axis=0)
y = np.repeat(y, 100, axis=0)
start = time.time()
clf = OneVsRestClassifier(SVC(kernel='linear', probability=True, class_weight='auto'))
clf.fit(X, y)
end = time.time()
print "Single SVC", end - start, clf.score(X,y)
proba = clf.predict_proba(X)
n_estimators = 10
start = time.time()
clf = OneVsRestClassifier(BaggingClassifier(SVC(kernel='linear', probability=True, class_weight='auto'), max_samples=1.0 / n_estimators, n_estimators=n_estimators))
clf.fit(X, y)
end = time.time()
print "Bagging SVC", end - start, clf.score(X,y)
proba = clf.predict_proba(X)
start = time.time()
clf = RandomForestClassifier(min_samples_leaf=20)
clf.fit(X, y)
end = time.time()
print "Random Forest", end - start, clf.score(X,y)
proba = clf.predict_proba(X)
如果要确保在BaggingClassifier
中每条记录只用于训练一次,可以将bootstrap
参数设置为False。
置顶回答中简单提及;这是代码:最快的方法是通过 the n_jobs
parameter:替换行
clf = OneVsRestClassifier(SVC(kernel='linear', probability=True, class_weight='auto'))
与
clf = OneVsRestClassifier(SVC(kernel='linear', probability=True, class_weight='auto'), n_jobs=-1)
这将使用您计算机上所有可用的 CPU,同时仍执行与以前相同的计算。
您可以使用 the kernel_approximation
module 将 SVM 扩展到像这样的大量样本。
对于大型数据集,考虑改用 LinearSVC 或 SGDClassifier,可能在 Nystroem 转换器之后。
https://scikit-learn.org/stable/modules/generated/sklearn.svm.SVC.html