2015-11-27 7 views
5

Sto usando scikit-learn con un CV stratificato per confrontare alcuni classificatori. Sto calcolando: precisione, richiamo, auc.Random Forest sta sovralimentando

Ho usato per l'ottimizzazione dei parametri GridSearchCV con un 5 CV.

RandomForestClassifier(warm_start= True, min_samples_leaf= 1, n_estimators= 800, min_samples_split= 5,max_features= 'log2', max_depth= 400, class_weight=None) 

sono i migliori_parami di GridSearchCV.

Il mio problema, penso di essere davvero troppo sexy. Per esempio:

a caso Foresta con deviazione standard (+/-)

  • precisione: 0.99 (+/- 0,06)
  • sensibilità: 0.94 (+/- 0,06)
  • specificità : 0.94 (+/- 0,06)
  • B_accuracy: 0.94 (+/- 0,06)
  • AUC: 0.94 (+/- 0,11)

regressione logistica con deviazione standard (+/-)

  • precisione: 0.88 (+/- 0,06)
  • sensibilità: 0,79 (+/- 0,06)
  • specificità: 0.68 (+/- 0,06)
  • B_accuracy: 0.73 (+/- 0,06)
  • AUC: 0.73 (+/- 0,041)

E anche gli altri sembrano una regressione logistica (quindi non sembrano sovradimensionati).

Il mio codice per la CV è:

for i,j in enumerate(data): 
    X.append(data[i][0]) 
    y.append(float(data[i][1])) 
x=np.array(X) 
y=np.array(y) 

def SD(values): 

    mean=sum(values)/len(values) 
    a=[] 
    for i in range(len(values)): 
     a.append((values[i]-mean)**2) 
    erg=sum(a)/len(values) 
    SD=math.sqrt(erg) 
    return SD,mean 

    for name, clf in zip(titles,classifiers): 
    # go through all classifiers, compute 10 folds 
    # the next for loop should be 1 tab indent more, coudlnt realy format it here, sorry 
    pre,sen,spe,ba,area=[],[],[],[],[] 
    for train_index, test_index in skf: 
     #print train_index, test_index 
     #get the index from all train_index and test_index 
     #change them to list due to some errors 
     train=train_index.tolist() 
     test=test_index.tolist() 
     X_train=[] 
     X_test=[] 
     y_train=[] 
     y_test=[] 
     for i in train: 
      X_train.append(x[i]) 

     for i in test: 
      X_test.append(x[i]) 

     for i in train: 
      y_train.append(y[i]) 

     for i in test: 
      y_test.append(y[i]) 


     #clf=clf.fit(X_train,y_train) 
     #predicted=clf.predict_proba(X_test) 
     #... other code, calculating metrics and so on... 
    print name 
    print("precision: %0.2f \t(+/- %0.2f)" % (SD(pre)[1], SD(pre)[0])) 
    print("sensitivity: %0.2f \t(+/- %0.2f)" % (SD(sen)[1], SD(pre)[0])) 
    print("specificity: %0.2f \t(+/- %0.2f)" % (SD(spe)[1], SD(pre)[0])) 
    print("B_accuracy: %0.2f \t(+/- %0.2f)" % (SD(ba)[1], SD(pre)[0])) 
    print("AUC: %0.2f \t(+/- %0.2f)" % (SD(area)[1], SD(area)[0])) 
    print "\n" 

Se sto usando il metodo scores = cross_validation.cross_val_score(clf, X, y, cv=10, scoring='accuracy'), non ottengo questi valori "sovradattamento". Quindi forse c'è qualcosa di sbagliato nel metodo CV che sto usando? Ma è solo per RF ...

Ho fatto il mio grazie al ritardo della funzione di punteggio di specificità nella funzione cross_val_.

+0

E la domanda è ...? –

+2

Non * crossizza * una foresta casuale. Piuttosto, la foresta viene convalidata in croce mentre viene costruita. –

+0

Ma come devo confrontare i modelli? So che sta per essere convalidato, ma in qualche modo dovrei confrontarlo con altri metodi come SVM, regressione logistica e così via ... La mia ricerca è anche: perché sto sovraffaticando? è la parte con "per train_index, test_index in skf:" l'intero ciclo potrebbe essere sbagliato? perché come ho già detto, la funzione scorer_val fornisce valori "normali" – auronsen

risposta

11

Herbert,

se il vostro scopo è quello di confrontare diversi algoritmi di apprendimento, che consigliamo di utilizzare nidificato convalida incrociata. (Mi riferisco all'algoritmo di apprendimento come algoritmi diversi come regressione logistica, alberi decisionali e altri modelli discriminanti che apprendono l'ipotesi o il modello - il classificatore finale - dai dati di allenamento).

La convalida incrociata "regolare" va bene se si desidera regolare gli iperparametri di un singolo algoritmo. Tuttavia, non appena inizi a eseguire l'ottimizzazione dell'iperparametro con gli stessi parametri/pieghe di convalida incrociata, la stima delle prestazioni sarà probabilmente eccessivamente ottimistica. Il motivo per cui si esegue la convalida incrociata più e più volte, i dati di test diventeranno "dati di addestramento" in qualche misura.

La gente mi ha chiesto questa domanda abbastanza frequentemente, in realtà, e mi prenderò alcuni estratti da una sezione FAQ che ho postato qui: http://sebastianraschka.com/faq/docs/evaluate-a-model.html

In nested convalida incrociata, abbiamo un cross k-fold esterna ciclo di convalida per dividere i dati in pieghe di addestramento e test, e un ciclo interno viene utilizzato per selezionare il modello tramite cross-validazione k-fold sulla piega di allenamento. Dopo la selezione del modello, la piega di prova viene quindi utilizzata per valutare le prestazioni del modello. Dopo aver identificato il nostro algoritmo "preferito", possiamo seguire un approccio "regolare" di validazione incrociata della k-fold (sul set completo di allenamento) per trovare i suoi iparparametri "ottimali" e valutarlo sul set di test indipendente. Consideriamo un modello di regressione logistica per renderlo più chiaro: utilizzando la validazione incrociata annidata formerai m diversi modelli di regressione logistica, 1 per ciascuna delle m pieghe esterne, e le pieghe interne vengono utilizzate per ottimizzare gli iperparametri di ciascun modello (ad es. utilizzando gridsearch in combinazione con la convalida incrociata k-fold Se il modello è stabile, questi modelli m dovrebbero avere tutti gli stessi valori di iperparametro e riportare le prestazioni medie di questo modello in base alle pieghe di prova esterne. l'algoritmo successiva, ad esempio, uno SVM ecc

enter image description here

posso solo consiglio vivamente questo eccellente documento che illustra questo problema in modo più dettagliato:

PS: in genere, non è necessario/voler impostare i iperparametri di una foresta a caso (in modo così esteso). L'idea alla base di Random Forests (una forma di insaccamento) è in realtà di non potare gli alberi decisionali - in realtà, uno dei motivi per cui Breiman ha elaborato l'algoritmo di Random Forest è stato quello di affrontare il problema della potatura/sovradattamento dei singoli alberi decisionali. Quindi, l'unico parametro che devi veramente "preoccupare" è il numero di alberi (e forse il numero di caratteristiche casuali per albero). Tuttavia, in genere, è meglio fare campionamenti di bootstrap di allenamento di dimensione n (dove n è il numero originale di funzionalità nel set di allenamento) e le caratteristiche di squareroot (m) (dove m è la dimensionalità del set di allenamento).

Spero che questo sia stato utile!

Edit:

qualche esempio di codice per fare CV annidati via scikit-learn:

pipe_svc = Pipeline([('scl', StandardScaler()), 
        ('clf', SVC(random_state=1))]) 

param_range = [0.0001, 0.001, 0.01, 0.1, 1.0, 10.0, 100.0, 1000.0] 

param_grid = [{'clf__C': param_range, 
       'clf__kernel': ['linear']}, 
      {'clf__C': param_range, 
       'clf__gamma': param_range, 
       'clf__kernel': ['rbf']}] 


# Nested Cross-validation (here: 5 x 2 cross validation) 
# ===================================== 
gs = GridSearchCV(estimator=pipe_svc, 
          param_grid=param_grid, 
          scoring='accuracy', 
          cv=5) 
scores = cross_val_score(gs, X_train, y_train, scoring='accuracy', cv=2) 
print('CV accuracy: %.3f +/- %.3f' % (np.mean(scores), np.std(scores))) 
+0

grid = GridSearchCV (algo, paramsE, cv = 5, scoring = 'accuratezza'). fit (x_data, y_data) e quindi: scores = cross_validation.cross_val_score (griglia, x_data, y_data), sarebbe il CV annidato o no? da questo posso ottenere grid.best_score_ e best params/estimator? – auronsen

+0

@auronsen Non proprio. Questo non sarebbe "CV annidato" perché dovresti installare lo stimatore di ricerca della griglia sul set di allenamento e non sulla sottocartella del ciclo esterno. Ho aggiunto un esempio in fondo alla mia risposta precedente; Spero possa aiutare! – Sebastian