2014-04-13 22 views
17

Volevo sapere se esiste un modo migliore più integrato per eseguire la ricerca in rete e testare più modelli in una singola pipeline. Ovviamente i parametri dei modelli sarebbero diversi, il che ha reso complicato per me capirlo. Ecco quello che ho fatto:ricerca di griglia di scikit su più classificatori 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_ 

Tuttavia, questo approccio è ancora dando il miglior modello all'interno di ogni categoria di classificazione, e non il confronto tra i classificatori.

+1

Non c'è un modo automatico per farlo. –

+1

ancora;) [il problema è che non possiamo impostare i "passi" della pipeline, giusto?] –

+0

@AndreasMueller; scusa non ho affrontato questo prima. Puoi elaborare cosa intendevi lì? – Anuj

risposta

3

Anche se l'argomento è un po 'vecchio, sto postando la risposta nel caso in cui aiuti chiunque in futuro.

Invece di utilizzare la ricerca griglia per la selezione dell'iperparametro, è possibile utilizzare 'hyperopt' library.

Si prega di dare un'occhiata alla sezione 2.2 di this page. Nel caso precedente, è possibile utilizzare un'espressione 'hp.choice' per selezionare tra le varie pipeline e quindi definire separatamente le espressioni dei parametri per ciascuna di esse.

Nella funzione obiettivo, è necessario eseguire un controllo in base alla pipeline scelta e restituire il punteggio CV per la pipeline e i parametri selezionati (possibilmente tramite cross_cal_score).

L'oggetto di prova alla fine dell'esecuzione, indicherà la pipeline e i parametri migliori in generale.

9

Il post Hyperparameter Grid Search across multiple models in scikit-learn offre un'implementazione di uno stimatore EstimatorSelectionHelper che può eseguire diversi stimatori, ciascuno con la propria griglia di parametri.

+0

questa soluzione ha funzionato meglio per il mio, ho solo dovuto fare alcune piccole modifiche per funzionare su Python3 e con le ultime versioni di scikit-learn 0.19, il codice è disponibile qui: http://davidsbatista.net/blog/2018/02/ 23/model_optimization / –

0

Sebbene la soluzione di dubek sia più diretta, non aiuta le interazioni tra i parametri degli elementi della pipeline che precedono il classfier. Pertanto, ho scritto un helper class per gestirlo, e posso essere incluso nell'impostazione predefinita della pipeline di scikit. Un esempio minimo:

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_) 

Può essere utilizzato anche per altri elementi della tubazione, non solo il classificatore. Il codice è github se qualcuno vuole verificarlo.

Problemi correlati