繁体   English   中英

使 SVM 在 Python 中运行得更快

[英]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 的答案产生的概率估计非常差。

如果您想尽可能坚持使用 SVC 并在完整数据集上进行训练,您可以使用在数据子集上训练的 SVC 集合来减少每个分类器的记录数(这显然对复杂性具有二次影响)。 Scikit 通过BaggingClassifier包装器支持这BaggingClassifier 与单个分类器相比,这应该可以为您提供相似(如果不是更好)的准确度,并且训练时间要少得多。 还可以使用n_jobs参数将各个分类器的训练设置为并行运行。

或者,我也会考虑使用随机森林分类器 - 它本身支持多类分类,速度很快,并且在适当设置min_samples_leaf时提供了非常好的概率估计。

我对 iris 数据集进行了快速测试,该数据集由 10 个 SVC 组成,每个 SVC 都使用了 10% 的数据进行了训练。 它比单个分类器快 10 倍以上。 这些是我在笔记本电脑上得到的数字:

单个 SVC:45 秒

合奏 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。

SVM 分类器不那么容易扩展。 从文档中,关于sklearn.svm.SVC的复杂性。

拟合时间复杂度超过样本数量的二次方,这使得很难扩展到具有超过 10000 个样本的数据集。

在 scikit-learn 中,你有svm.linearSVC可以更好地扩展。 显然它可以处理您的数据。

或者,您可以使用另一个分类器。 如果您想要概率估计,我建议您使用逻辑回归。 Logistic 回归还具有不需要概率校准来输出“正确”概率的优点。

编辑:

我不知道linearSVC复杂度,最后我在用户指南中找到了信息:

另请注意,对于线性情况,liblinear 实现在 LinearSVC 中使用的算法比基于 libsvm 的 SVC 对应物更有效,并且几乎可以线性扩展到数百万个样本和/或特征。

要从linearSVC获得概率,请查看此链接 它与我上面链接的概率校准指南只有几个链接,并且包含一种估计概率的方法。 即:

    prob_pos = clf.decision_function(X_test)
    prob_pos = (prob_pos - prob_pos.min()) / (prob_pos.max() - prob_pos.min())

请注意,如链接中所示,如果没有校准,估计值可能会很差。

上面的回答中简要提到了这一点; 这是代码: 最快的方法是通过n_jobs参数:替换该行

clf = OneVsRestClassifier(SVC(kernel='linear', probability=True, class_weight='auto'))

clf = OneVsRestClassifier(SVC(kernel='linear', probability=True, class_weight='auto'), n_jobs=-1)

这将使用您计算机上所有可用的 CPU,同时仍执行与以前相同的计算。

您可以使用kernel_approximation模块将 SVM 扩展到像这样的大量样本。

对于大型数据集,请考虑使用 LinearSVC 或 SGDClassifier,可能在 Nystroem 转换器之后。

https://scikit-learn.org/stable/modules/generated/sklearn.svm.SVC.html

使用class_weight == 'auto'提到的一些答案。 对于高于0.17的sklearn版本,请使用class_weight == 'balanced'代替: httpsclass_weight == 'balanced'

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM