2016-06-25 11 views
13

Mam zestaw danych z ~ 300 punktami i 32 różnymi etykietami i chcę ocenić model LinearSVR, wykreślając jego krzywą uczenia za pomocą wyszukiwania w sieci i sprawdzania poprawności LabelKFold.Jak zagnieździć LabelKFold?

Kod mam wygląda następująco:

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 

Moje pytanie brzmi: jak ustawić atrybut cv na poszukiwaniu siatki i krzywej uczenia się tak, że będzie złamać mój oryginalny zestaw do zestawów treningowych i testowych, które don nie udostępnia żadnych etykiet do obliczania krzywej uczenia się. A następnie z tych zestawów szkoleniowych, rozdzielaj je dalej na zestawy szkoleniowe i testowe bez udostępniania etykiet do wyszukiwania w sieci?

Zasadniczo, w jaki sposób uruchomić zagnieżdżone LabelKFold?


I, użytkownik, który utworzył bounty na to pytanie, napisał następujące powtarzalne przykład wykorzystując dane dostępne od 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) 

Odpowiedz

3

Od swoje pytanie, szukasz wyniku LabelKFold na danych, natomiast siatki szukają parametry swojej rurociągu w każdej iteracji tej zewnętrznej LabelKFold, używając znowu LabelKFold. Mimo, że nie był w stanie osiągnąć out-of-the-box to tylko jedna pętla:

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

Uruchamianie kodu, pierwsze plony iteracji:

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

Stąd łatwo jest sprawdź, czy działa zgodnie z przeznaczeniem. Twoje wyniki walidacji krzyżowej znajdują się na liście scores i można je łatwo przetworzyć. Użyłem zmiennych, np. strata, które zdefiniowałeś w swoim ostatnim fragmencie kodu.

+0

Tak właśnie musiałem to zrobić, wykonując pętlę kfold na własną rękę i uruchamiając wyszukiwanie siatki na poszczególnych fałdach. Jestem oryginalnym pytającym, ale nie jestem tym, który włożył nagrodę za to pytanie. Nie jestem pewien, jak to działa, ale zamierzam przegłosować tę odpowiedź, ponieważ jest to najlepsze rozwiązanie, które znam. Zanim jednak przyjmuję odpowiedź, czekam na odpowiedź właściciela nagrody. – Alex

+0

To wygląda bardzo żywotnie - dam temu wir. Wygląda na to, że jest to właściwy sposób. Dziękuję Ci bardzo. FWIW, @Alex, uważam, że tylko ja mogę nagrodzić nagrodę, więc geompalik może na to czekać w ciągu najbliższych 24 godzin. – Sycorax

Powiązane problemy