2016-06-25 3 views
13

Ich habe ein Dataset mit ~ 300 Punkten und 32 verschiedenen Labels und ich möchte ein LinearSVR-Modell auswerten, indem ich seine Lernkurve mit Hilfe der Gridsuche und LabelKFold-Validierung aufzeichne.Wie kann LabelKFold verschachtelt werden?

Der Code Ich habe sieht wie folgt aus:

import numpy as np 
from sklearn import preprocessing 
from sklearn.svm import LinearSVR 
from sklearn.pipeline import Pipeline 
from sklearn.cross_validation import LabelKFold 
from sklearn.grid_search import GridSearchCV 
from sklearn.learning_curve import learning_curve 
    ... 
#get data (x, y, labels) 
    ... 
C_space = np.logspace(-3, 3, 10) 
epsilon_space = np.logspace(-3, 3, 10) 

svr_estimator = Pipeline([ 
    ("scale", preprocessing.StandardScaler()), 
    ("svr", LinearSVR), 
]) 

search_params = dict(
    svr__C = C_space, 
    svr__epsilon = epsilon_space 
) 

kfold = LabelKFold(labels, 5) 

svr_search = GridSearchCV(svr_estimator, param_grid = search_params, cv = ???) 

train_space = np.linspace(.5, 1, 10) 
train_sizes, train_scores, valid_scores = learning_curve(svr_search, x, y, train_sizes = train_space, cv = ???, n_jobs = 4) 
    ... 
#plot learning curve 

Meine Frage ist, wie das cv Attribut Setup für die Rastersuche und Lernkurve, so dass es meine ursprünglichen Satz in Trainings- und Testsätze brechen wird, dass Don teile keine Beschriftungen für die Berechnung der Lernkurve. Und dann von diesen Trainingssätzen weiter in Trainings- und Testsets aufteilen, ohne die Labels für die Rastersuche zu teilen?

Im Wesentlichen, wie führe ich ein geschachteltes LabelKFold?


I, der Benutzer, der die Prämie für diese Frage erstellt, schrieb die folgenden reproduzierbaren Beispieldaten zur Verfügung unter Verwendung von sklearn.

import numpy as np 
from sklearn.datasets import load_digits 
from sklearn.ensemble import RandomForestClassifier 
from sklearn.metrics import make_scorer, roc_auc_score 
from sklearn.grid_search import GridSearchCV 
from sklearn.cross_validation import cross_val_score, LabelKFold 

digits = load_digits() 
X = digits['data'] 
Y = digits['target'] 
Z = np.zeros_like(Y) ## this is just to make a 2-class problem, purely for the sake of an example 
Z[np.where(Y>4)]=1 

strata = [x % 13 for x in xrange(Y.size)] # define the strata for use in 

## define stuff for nested cv... 
mtry = [5, 10] 
tuned_par = {'max_features': mtry} 
toy_rf = RandomForestClassifier(n_estimators=10, max_depth=10, random_state=10, 
           class_weight="balanced") 
roc_auc_scorer = make_scorer(roc_auc_score, needs_threshold=True) 

## define outer k-fold label-aware cv 
outer_cv = LabelKFold(labels=strata, n_folds=5) 

############################################################################# 
## this works: using regular randomly-allocated 10-fold CV in the inner folds 
############################################################################# 
vanilla_clf = GridSearchCV(estimator=toy_rf, param_grid=tuned_par, scoring=roc_auc_scorer, 
         cv=5, n_jobs=1) 
vanilla_results = cross_val_score(vanilla_clf, X=X, y=Z, cv=outer_cv, n_jobs=1) 

########################################################################## 
## this does not work: attempting to use label-aware CV in the inner loop 
########################################################################## 
inner_cv = LabelKFold(labels=strata, n_folds=5) 
nested_kfold_clf = GridSearchCV(estimator=toy_rf, param_grid=tuned_par, scoring=roc_auc_scorer, 
           cv=inner_cv, n_jobs=1) 
nested_kfold_results = cross_val_score(nested_kfold_clf, X=X, y=Y, cv=outer_cv, n_jobs=1) 

Antwort

3

Aus Ihrer Frage, Sie suchen die LabelKFold Punktzahl auf Ihre Daten, während die Parameter Ihrer Pipeline in jeder der Iterationen dieses äußeren LabelKFold raster Suche, eine LabelKFold mit wieder. Obwohl ich nicht in der Lage war, das zu erreichen out-of-the-Box dauert es nur eine Schleife:

outer_cv = LabelKFold(labels=strata, n_folds=3) 
strata = np.array(strata) 
scores = [] 
for outer_train, outer_test in outer_cv: 
    print "Outer set. Train:", set(strata[outer_train]), "\tTest:", set(strata[outer_test]) 
    inner_cv = LabelKFold(labels=strata[outer_train], n_folds=3) 
    print "\tInner:" 
    for inner_train, inner_test in inner_cv: 
     print "\t\tTrain:", set(strata[outer_train][inner_train]), "\tTest:", set(strata[outer_train][inner_test]) 
    clf = GridSearchCV(estimator=toy_rf, param_grid=tuned_par, scoring=roc_auc_scorer, cv= inner_cv, n_jobs=1) 
    clf.fit(X[outer_train],Z[outer_train]) 
    scores.append(clf.score(X[outer_test], Z[outer_test])) 

Ausführen des Codes, die ersten Iteration ergibt:

Outer set. Train: set([0, 1, 4, 5, 7, 8, 10, 11]) Test: set([9, 2, 3, 12, 6]) 
Inner: 
    Train: set([0, 10, 11, 5, 7]) Test: set([8, 1, 4]) 
    Train: set([1, 4, 5, 8, 10, 11]) Test: set([0, 7]) 
    Train: set([0, 1, 4, 8, 7])  Test: set([10, 11, 5]) 

Daher ist es leicht zu vergewissern Sie sich, dass es wie beabsichtigt ausgeführt wird. Ihre Ergebnisse für die Kreuzvalidierung finden Sie in der Liste scores und Sie können sie problemlos verarbeiten. Ich habe die Variablen verwendet, z. B. strata, die Sie in Ihrem letzten Codeabschnitt definiert haben.

+0

Das ist ungefähr so, wie ich es machen musste, die kfold-Schleife alleine zu machen und die Gittersuche nach einzelnen Falten zu machen. Ich bin der ursprüngliche Fragesteller, aber ich bin nicht derjenige, der diese Frage mit Kopfgeld beantwortet hat. Ich bin mir nicht sicher, wie das funktioniert, aber ich werde diese Antwort verbessern, weil es die beste Lösung ist, die ich kenne. Ich werde jedoch auf die Antwort des Kopfgeldinhabers warten, bevor ich die Antwort akzeptiere. – Alex

+0

Das sieht sehr brauchbar aus - ich werde das hier ausprobieren. Es scheint, dass dies der richtige Weg ist. Vielen Dank. FWIW, @Alex, ich glaube, dass nur ich das Kopfgeld vergeben kann, damit sich Geompalik in den nächsten 24 Stunden darauf freuen kann. – Sycorax

Verwandte Themen