Haciendo SVM correr más rápido en python

Usando el siguiente código para svm en python:

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) 

Pero está tomando una gran cantidad de tiempo.

Dimensiones de datos reales :

 train-set (1422392,29) test-set (233081,29) 

¿Cómo puedo acelerarlo (paralelo o de alguna otra manera)? Por favor ayuda. Ya he intentado PCA y downsampling.

Tengo 6 clases. Edit: Found http://scikit-learn.org/stable/modules/generated/sklearn.linear_model.SGDClassifier.html pero deseo estimaciones de probabilidad y parece que no es así para svm.

Editar:

 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,:] 

Edición 2: La respuesta del usuario 3914041 produce estimaciones de probabilidad muy bajas.

Si desea seguir con el SVC tanto como sea posible y entrenar en el conjunto de datos completo, puede usar conjuntos de SVC entrenados en subconjuntos de los datos para reducir el número de registros por clasificador (que aparentemente tiene una influencia cuadrática en la complejidad). Scikit soporta eso con el envoltorio BaggingClassifier . Eso debería darle una precisión similar (si no mejor) en comparación con un solo clasificador, con mucho menos tiempo de entrenamiento. El entrenamiento de los clasificadores individuales también se puede configurar para ejecutarse en paralelo utilizando el parámetro n_jobs .

Alternativamente, también consideraría usar un clasificador de bosque aleatorio: es compatible con la clasificación de múltiples clases de forma nativa, es rápido y ofrece estimaciones de probabilidad bastante buenas cuando min_samples_leaf se establece correctamente.

Hice unas pruebas rápidas en el conjunto de datos del iris que se hizo estallar 100 veces con un conjunto de 10 SVC, cada una entrenada en el 10% de los datos. Es más de 10 veces más rápido que un solo clasificador. Estos son los números que tengo en mi computadora portátil:

Solo SVC: 45s

Ensemble SVC: 3s

Clasificador de bosque aleatorio: 0.5s

Vea a continuación el código que usé para producir los números:

 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) 

Si desea asegurarse de que cada registro se use solo una vez para el entrenamiento en el BaggingClassifier , puede establecer el parámetro de bootstrap en Falso.

Los clasificadores SVM no escalan tan fácilmente. De los documentos, sobre la complejidad de sklearn.svm.SVC .

La complejidad del tiempo de ajuste es más que cuadrática con el número de muestras, lo que dificulta la escala al conjunto de datos con más de un par de 10000 muestras.

En scikit-learn tienes svm.linearSVC que puede escalar mejor. Aparentemente podría ser capaz de manejar sus datos.

Alternativamente, puedes ir con otro clasificador. Si quieres estimaciones de probabilidad te sugiero regresión logística. La regresión logística también tiene la ventaja de no necesitar una calibración de probabilidad para generar probabilidades “adecuadas”.

Editar:

No sabía sobre la complejidad de linearSVC , finalmente encontré información en la guía del usuario :

También tenga en cuenta que para el caso lineal, el algoritmo utilizado en LinearSVC por la implementación liblinear es mucho más eficiente que su contraparte SVC basada en libsvm y puede escalar casi linealmente a millones de muestras y / o características.

Para obtener la probabilidad de un linearSVC echa un vistazo a este enlace . Está a solo un par de enlaces de la guía de calibración de probabilidad que he enlazado anteriormente y contiene una manera de estimar las probabilidades. A saber:

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

Tenga en cuenta que las estimaciones probablemente serán malas sin calibración, como se ilustra en el enlace.

Fue mencionado brevemente en la respuesta superior; Aquí está el código: la forma más rápida de hacerlo es a través del parámetro n_jobs : reemplazar la línea

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

con

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

Esto utilizará todas las CPU disponibles en su computadora, mientras sigue haciendo el mismo cálculo que antes.

Puede usar el módulo kernel_approximation para escalar SVM a un gran número de muestras como esta.