2014-04-13 11 views
17

Ich wollte wissen, ob es eine bessere integrierte Möglichkeit gibt, Grid-Suche zu machen und mehrere Modelle in einer einzigen Pipeline zu testen. Natürlich würden die Parameter der Modelle anders sein, was für mich kompliziert ist, dies herauszufinden. Hier ist, was ich getan habe:scikit Grid Suche über mehrere Klassifikatoren python

from sklearn.pipeline import Pipeline 
from sklearn.ensemble import RandomForestClassifier 
from sklearn.neighbors import KNeighborsClassifier 
from sklearn.svm import SVC 
from sklearn.naive_bayes import MultinomialNB 
from sklearn.grid_search import GridSearchCV 


def grid_search(): 
    pipeline1 = Pipeline((
    ('clf', RandomForestClassifier()), 
    ('vec2', TfidfTransformer()) 
    )) 

    pipeline2 = Pipeline((
    ('clf', KNeighborsClassifier()), 
    )) 

    pipeline3 = Pipeline((
    ('clf', SVC()), 
    )) 

    pipeline4 = Pipeline((
    ('clf', MultinomialNB()), 
    )) 

    parameters1 = { 
    'clf__n_estimators': [10, 20, 30], 
    'clf__criterion': ['gini', 'entropy'], 
    'clf__max_features': [5, 10, 15], 
    'clf__max_depth': ['auto', 'log2', 'sqrt', None] 
    } 

    parameters2 = { 
    'clf__n_neighbors': [3, 7, 10], 
    'clf__weights': ['uniform', 'distance'] 
    } 

    parameters3 = { 
    'clf__C': [0.01, 0.1, 1.0], 
    'clf__kernel': ['rbf', 'poly'], 
    'clf__gamma': [0.01, 0.1, 1.0], 

    } 
    parameters4 = { 
    'clf__alpha': [0.01, 0.1, 1.0] 
    } 

    pars = [parameters1, parameters2, parameters3, parameters4] 
    pips = [pipeline1, pipeline2, pipeline3, pipeline4] 

    print "starting Gridsearch" 
    for i in range(len(pars)): 
     gs = GridSearchCV(pips[i], pars[i], verbose=2, refit=False, n_jobs=-1) 
     gs = gs.fit(X_train, y_train) 
     print "finished Gridsearch" 
     print gs.best_score_ 

Doch dieser Ansatz nach wie vor das beste Modell in jedem Klassifikator geben und nicht zu vergleichen zwischen Klassifizierer.

+1

Es gibt keine automatische Möglichkeit, dies zu tun. –

+1

noch;) [Das Problem ist, dass wir nicht die "Schritte" der Pipeline setzen können, oder?] –

+0

@AndreasMueller; Entschuldigung hat das früher nicht angesprochen. Können Sie näher erläutern, was Sie dort gemeint haben? – Anuj

Antwort

3

Obwohl das Thema ein bisschen alt ist, posten ich die Antwort für den Fall, dass es in der Zukunft hilft.

Anstatt die Grid-Suche für die Auswahl von Hyperparametern zu verwenden, können Sie die 'hyperopt' library verwenden.

Schauen Sie sich bitte Abschnitt 2.2 von this page an. Im obigen Fall können Sie einen Ausdruck "hp.choice" verwenden, um zwischen den verschiedenen Pipelines zu wählen und dann die Parameterausdrücke für jeden separat zu definieren.

In Ihrer Zielfunktion müssen Sie abhängig von der ausgewählten Pipeline eine Überprüfung durchführen und die CV-Bewertung für die ausgewählte Pipeline und die Parameter (möglicherweise über cross_cal_score) zurückgeben.

Das Versuchsobjekt am Ende der Ausführung zeigt die beste Pipeline und die Parameter insgesamt an.

9

Der Beitrag Hyperparameter Grid Search across multiple models in scikit-learn bietet eine Implementierung eines EstimatorSelectionHelper Schätzers, der verschiedene Schätzer mit jeweils einem eigenen Raster von Parametern ausführen kann.

+0

Diese Lösung funktionierte am besten für mich, ich musste nur einige kleine Änderungen vornehmen, um auf Python3 zu laufen und mit den neuesten Versionen von scikit-learn 0.19, Code ist hier verfügbar: http://davidsbatista.net/blog/2018/02/ 23/modell_optimierung / –

0

Obwohl die Lösung von Dubek einfacher ist, hilft sie nicht bei Interaktionen zwischen Parametern von Pipeline-Elementen, die vor dem Classfier kommen. Daher habe ich eine helper class geschrieben, um damit umzugehen, und kann in der Standard-Pipeline-Einstellung von scikit enthalten sein. Ein minimales Beispiel:

from sklearn.pipeline import Pipeline 
from sklearn.model_selection import GridSearchCV 
from sklearn.preprocessing import StandardScaler, MaxAbsScaler 
from sklearn.svm import LinearSVC 
from sklearn.ensemble import RandomForestClassifier 
from sklearn import datasets 
from pipelinehelper import PipelineHelper 

iris = datasets.load_iris() 
X_iris = iris.data 
y_iris = iris.target 
pipe = Pipeline([ 
    ('scaler', PipelineHelper([ 
     ('std', StandardScaler()), 
     ('max', MaxAbsScaler()), 
    ])), 
    ('classifier', PipelineHelper([ 
     ('svm', LinearSVC()), 
     ('rf', RandomForestClassifier()), 
    ])), 
]) 

params = { 
    'scaler__selected_model': pipe.named_steps['scaler'].generate({ 
     'std__with_mean': [True, False], 
     'std__with_std': [True, False], 
     'max__copy': [True], # just for displaying 
    }), 
    'classifier__selected_model': pipe.named_steps['classifier'].generate({ 
     'svm__C': [0.1, 1.0], 
     'rf__n_estimators': [100, 20], 
    }) 
} 
grid = GridSearchCV(pipe, params, scoring='accuracy', verbose=1) 
grid.fit(X_iris, y_iris) 
print(grid.best_params_) 
print(grid.best_score_) 

Es kann auch für andere Elemente der Pipeline verwendet werden, nicht nur für den Klassifikator. Code ist auf github wenn jemand es auschecken möchte.

Verwandte Themen