En utilisant le code ci-dessous pour 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)
Mais cela prend énormément de temps.
Dimensions des données réelles :
train-set (1422392,29)
test-set (233081,29)
Comment puis-je l'accélérer (parallèlement ou autrement)? S'il vous plaît aider. J'ai déjà essayé la PCA et le sous-échantillonnage.
J'ai 6 cours. Edit: Trouvé http://scikit-learn.org/stable/modules/generated/sklearn.linear_model.SGDClassifier.html mais je souhaite des estimations de probabilité et il semble que ce ne soit pas le cas pour svm.
Modifier:
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 __== '__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,:]
Edit 2: La réponse de user3914041 donne des estimations de probabilité très faibles.
Si vous souhaitez vous en tenir au SVC autant que possible et vous entraîner à l'intégralité du jeu de données, vous pouvez utiliser des ensembles de SVC formés sur des sous-ensembles de données pour réduire le nombre d'enregistrements par classificateur (ce qui a apparemment une influence quadratique sur la complexité). Scikit supporte cela avec le wrapper BaggingClassifier
. Cela devrait vous donner une précision similaire (sinon meilleure) par rapport à un classificateur unique, avec beaucoup moins de temps de formation. La formation des classificateurs individuels peut également être configurée pour s'exécuter en parallèle à l'aide de la commande n_jobs
paramètre.
Alternativement, je considérerais également l’utilisation d’un classifieur Random Forest - il prend en charge la classification multi-classes de manière native, il est rapide et donne de bonnes estimations de probabilité lorsque min_samples_leaf
est réglé correctement.
J'ai fait des tests rapides sur l'ensemble de données de l'iris agrandi 100 fois avec un ensemble de 10 SVC, chacun formé sur 10% des données. Il est plus de 10 fois plus rapide qu'un classificateur unique. Voici les chiffres que j'ai sur mon ordinateur portable:
SVC simple: 45s
Ensemble SVC: 3s
Classificateur de forêt aléatoire: 0.5s
Voir ci-dessous le code que j'ai utilisé pour produire les numéros:
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 vous voulez vous assurer que chaque enregistrement n'est utilisé qu'une seule fois pour l'apprentissage du BaggingClassifier
, vous pouvez définir le paramètre bootstrap
sur False.
Les classificateurs SVM ne s'adaptent pas aussi facilement. Des docs, sur la complexité de sklearn.svm.SVC
.
La complexité temporelle de l'ajustement est plus que quadratique par rapport au nombre d'échantillons, ce qui rend difficile la mise à l'échelle d'un jeu de données comprenant plus de 10000 échantillons.
En scikit-learn, vous avez svm.linearSVC
qui peut mieux évoluer. Apparemment, il pourrait être capable de gérer vos données.
Sinon, vous pouvez simplement aller avec un autre classificateur. Si vous voulez des estimations de probabilité, je suggérerais une régression logistique. La régression logistique a également l'avantage de ne pas nécessiter étalonnage de probabilité pour générer des probabilités "correctes".
Modifier:
Je ne connaissais pas la complexité de linearSVC
, enfin j'ai trouvé des informations dans le guide de l'utilisateur :
Notez également que dans le cas linéaire, l'algorithme utilisé dans LinearSVC par l'implémentation linéaire est beaucoup plus efficace que son équivalent SVC basé sur libsvm et qu'il peut évoluer presque linéairement vers des millions d'échantillons et/ou d'entités.
Pour obtenir la probabilité d'un linearSVC
, consultez ce lien . Il ne s’agit que de quelques liens par rapport au guide de calibration de probabilité que j’ai lié ci-dessus et qui contient un moyen d’estimer les probabilités. À savoir:
prob_pos = clf.decision_function(X_test)
prob_pos = (prob_pos - prob_pos.min()) / (prob_pos.max() - prob_pos.min())
Notez que les estimations seront probablement médiocres sans calibration, comme illustré dans le lien.
Cela a été brièvement mentionné dans la réponse du haut. voici le code: Le moyen le plus rapide de le faire est via le n_jobs
paramètre : remplace la ligne
clf = OneVsRestClassifier(SVC(kernel='linear', probability=True, class_weight='auto'))
avec
clf = OneVsRestClassifier(SVC(kernel='linear', probability=True, class_weight='auto'), n_jobs=-1)
Cela utilisera tous les processeurs disponibles sur votre ordinateur, tout en effectuant le même calcul qu'auparavant.
Vous pouvez utiliser le kernel_approximation
module pour adapter les SVM à un grand nombre d’échantillons comme celui-ci.
Quelques réponses mentionnées en utilisant class_weight == 'auto'
. Pour les versions supérieures à 0.17, utilisez class_weight == 'balanced'
à la place: https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.LogisticRegression.html