2016-02-06 26 views
8

Sto usando Python sklearn (versione 0.17) per selezionare il modello ideale su un set di dati. Per fare questo, ho seguito questi passi:python sklearn: qual è la differenza tra il punteggio accuracy_score e learning_curve?

  1. dividere il set di dati utilizzando cross_validation.train_test_split con test_size = 0.2.
  2. Utilizzare GridSearchCV per selezionare il classificatore ideale k-closest-neighbors sul set di allenamento.
  3. Passare il classificatore restituito da GridSearchCV a plot_learning_curve. plot_learning_curve ha dato la trama mostrata di seguito.
  4. Eseguire il classificatore restituito da GridSearchCV sul set di prova ottenuto.

Dalla trama, possiamo vedere che il punteggio per il max. la dimensione dell'allenamento è di circa 0,43. Questo punteggio è il punteggio restituito dalla funzione sklearn.learning_curve.learning_curve.

Ma quando ho eseguito il meglio classificatore sul set di test ottengo un punteggio di accuratezza di 0,61, come restituito da sklearn.metrics.accuracy_score (previsto correttamente le etichette/numero di etichette)

Link a immagine: graph plot for KNN classifier

Questo è il codice che sto usando. Non ho incluso la funzione plot_learning_curve in quanto richiederebbe molto spazio. Ho preso il plot_learning_curve da here

import pandas as pd 
import numpy as np 
from sklearn.neighbors import KNeighborsClassifier 
from sklearn.metrics import accuracy_score 
from sklearn.metrics import classification_report 
from matplotlib import pyplot as plt 
import sys 
from sklearn import cross_validation 
from sklearn.learning_curve import learning_curve 
from sklearn.grid_search import GridSearchCV 
from sklearn.cross_validation import train_test_split 


filename = sys.argv[1] 
data = np.loadtxt(fname = filename, delimiter = ',') 
X = data[:, 0:-1] 
y = data[:, -1] # last column is the label column 


X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=2) 

params = {'n_neighbors': [2, 3, 5, 7, 10, 20, 30, 40, 50], 
      'weights': ['uniform', 'distance']} 

clf = GridSearchCV(KNeighborsClassifier(), param_grid=params) 
clf.fit(X_train, y_train) 
y_true, y_pred = y_test, clf.predict(X_test) 
acc = accuracy_score(y_pred, y_test) 
print 'accuracy on test set =', acc 

print clf.best_params_ 
for params, mean_score, scores in clf.grid_scores_: 
    print "%0.3f (+/-%0.03f) for %r" % (
     mean_score, scores.std()/2, params) 

y_true, y_pred = y_test, clf.predict(X_test) 
#pred = clf.predict(np.array(features_test)) 
acc = accuracy_score(y_pred, y_test) 
print classification_report(y_true, y_pred) 
print 'accuracy last =', acc 
print 

plot_learning_curve(clf, "KNeighborsClassifier", 
       X, y, 
       train_sizes=np.linspace(.05, 1.0, 5)) 

è normale? Posso capire che potrebbe esserci qualche differenza nei punteggi, ma questa è una differenza di 0,18, che quando convertita in percentuali è del 43% contro il 61%. Anche il rapporto_del_registrazione fornisce un richiamo medio di 0,61.

Sto facendo qualcosa di sbagliato? C'è una differenza nel modo in cui learning_curve calcola i punteggi? Ho anche provato a passare la funzione scoring='accuracy' a learning_curve per vedere se corrisponde al punteggio di precisione, ma non ha fatto alcuna differenza.

Qualsiasi consiglio sarebbe di grande aiuto.

Sto utilizzando la qualità del vino (bianco) data set from UCI e ho rimosso anche l'intestazione prima di eseguire il codice.

+1

Dov'è il tuo codice per plot_learning_curve()? Sembra che sia qui che l'incoerenza è. I punteggi di accuratezza della convalida incrociata di GridSearchCV sono ragionevolmente vicini all'accuratezza calcolata sul set di test. – SPKoder

+0

@SPKoder Immagino che abbia usato la funzione dal sito web di sklearn: http://scikit-learn.org/stable/auto_examples/model_selection/plot_learning_curve.html#example-model-selection-plot-learning-curve-py. A proposito, ho fatto diversi test e sono abbastanza sicuro di aver trovato una spiegazione, puoi verificarlo e ricontrollare la mia ipotesi –

risposta

8

Quando si chiama la funzione learning_curve, esegue una convalida incrociata su tutti i dati. Quando si lascia vuoto il parametro cv, si tratta di una strategia di suddivisione incrociata di 3 volte incrociata. E qui arriva la parte difficile perché, come indicato nella documentazione "Se lo stimatore è un classificatore o se y non è né binario né multiclasse, viene utilizzato KFold". E il tuo estimatore è un classificatore.

Quindi, qual è la differenza tra KFold e StratifiedKFold?

KFold = insieme di dati in Split k pieghe consecutive (senza mischiare predefinita)

StratifiedKFold = "Le pieghe sono realizzati conservando la percentuale dei campioni per ogni classe."

Facciamo un semplice esempio:

  • le etichette dei dati sono [4.0, 4.0, 4.0, 5.0, 5.0, 5.0, 6.0, 6.0, 6.0]
  • dal non stratificato 3 volte dividi in sottoinsiemi: [4.0, 4.0, 4.0], [5.0, 5.0, 5.0], [6.0, 6.0, 6.0]
  • ogni piega viene quindi utilizzato un set di convalida una volta mentre il k - 1 (3-2) la rimanente piega forma il set di allenamento, quindi, ad esempio, si allenerà su [5.0, 5.0, 6.0, 6.0, 6.0] e convalida su [4.0, 4.0, 4.0]

Questo spiega la bassa accuratezza della curva di apprendimento (~ 0,43%). Ovviamente questo è un esempio estremo per illustrare la situazione, ma i dati sono in qualche modo strutturati e devi mescolarli.

Ma quando si ottiene l'accuratezza del ~ 61%, i dati sono stati suddivisi con il metodo train_test_split che per impostazione predefinita esegue una riproduzione casuale dei dati e mantiene le proporzioni.

Basta guardare questa, ho eseguito un semplice test per sostenere la mia ipotesi:

X_train2, X_test2, y_train2, y_test2 = train_test_split(X, y, test_size=0., random_state=2) 

Nel tuo esempio si pascolava il learning_curve con tutti i tuoi dati di X,y. Sto facendo un piccolo trucco qui che è quello di dividere i dati che dicono test_size=0. che significa che tutti i dati sono in train variabili. In questo modo sto ancora conservando tutti i dati, ma ora viene mescolato mentre passava attraverso la funzione train_test_split.

Poi ho chiamato la funzione tracciato, ma con i dati mescolate:

plot_learning_curve(clf, "KNeighborsClassifier",X_train2, y_train2, train_sizes=np.linspace(.05, 1.0, 5)) 

Ora l'uscita con i campioni max formazione num invece di 0.43 è 0.59 che rende molto più senso con i risultati GridSearch.

Osservazione: Credo che il punto di tracciare la curva di apprendimento è quello di determinare wether aggiungendo più campioni alla formazione impostare il nostro stimatore è in grado di svolgere meglio o no (in modo da poter decidere per esempio, quando c'è non c'è bisogno di aggiungere altri esempi). Come nel numero train_sizes, i valori sono appena np.linspace(.05, 1.0, 5) --> [ 0.05 , 0.2875, 0.525 , 0.7625, 1. ] Non sono del tutto sicuro che questo sia l'utilizzo che stai perseguendo in questo tipo di test.

Problemi correlati