Come ottenere precisione, F1, precisione e richiamo, per un modello di keras?


21

Voglio calcolare la precisione, il richiamo e il punteggio F1 per il mio modello binario KerasClassifier, ma non trovo alcuna soluzione.

Ecco il mio codice attuale:

# Split dataset in train and test data 
X_train, X_test, Y_train, Y_test = train_test_split(normalized_X, Y, test_size=0.3, random_state=seed)

# Build the model
model = Sequential()
model.add(Dense(23, input_dim=45, kernel_initializer='normal', activation='relu'))
model.add(Dense(1, kernel_initializer='normal', activation='sigmoid'))

# Compile model
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])


tensorboard = TensorBoard(log_dir="logs/{}".format(time.time()))

time_callback = TimeHistory()

# Fit the model
history = model.fit(X_train, Y_train, validation_split=0.3, epochs=200, batch_size=5, verbose=1, callbacks=[tensorboard, time_callback]) 

E quindi prevedo nuovi dati di test e ottengo la matrice di confusione in questo modo:

y_pred = model.predict(X_test)
y_pred =(y_pred>0.5)
list(y_pred)

cm = confusion_matrix(Y_test, y_pred)
print(cm)

Ma c'è qualche soluzione per ottenere il punteggio di precisione, il punteggio di F1, la precisione e il richiamo? (Se non complicato, anche il punteggio di convalida incrociata, ma non necessario per questa risposta)

Grazie per tutto l'aiuto!

Risposte:


20

Le metriche sono state rimosse dal core di Keras. Devi calcolarli manualmente. Li hanno rimossi sulla versione 2.0 . Queste metriche sono tutte metriche globali, ma Keras funziona in batch. Di conseguenza, potrebbe essere più fuorviante che utile.

Tuttavia, se ne hai davvero bisogno, puoi farlo in questo modo

from keras import backend as K

def recall_m(y_true, y_pred):
    true_positives = K.sum(K.round(K.clip(y_true * y_pred, 0, 1)))
    possible_positives = K.sum(K.round(K.clip(y_true, 0, 1)))
    recall = true_positives / (possible_positives + K.epsilon())
    return recall

def precision_m(y_true, y_pred):
    true_positives = K.sum(K.round(K.clip(y_true * y_pred, 0, 1)))
    predicted_positives = K.sum(K.round(K.clip(y_pred, 0, 1)))
    precision = true_positives / (predicted_positives + K.epsilon())
    return precision

def f1_m(y_true, y_pred):
    precision = precision_m(y_true, y_pred)
    recall = recall_m(y_true, y_pred)
    return 2*((precision*recall)/(precision+recall+K.epsilon()))

# compile the model
model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['acc',f1_m,precision_m, recall_m])

# fit the model
history = model.fit(Xtrain, ytrain, validation_split=0.3, epochs=10, verbose=0)

# evaluate the model
loss, accuracy, f1_score, precision, recall = model.evaluate(Xtest, ytest, verbose=0)

se possono essere fuorvianti, come valutare un modello di Keras?
ZelelB,

1
Poiché Keras calcola queste metriche alla fine di ogni batch, potresti ottenere risultati diversi dalle metriche "reali". Un modo alternativo sarebbe quello di dividere il set di dati in training e test e utilizzare la parte test per prevedere i risultati. Quindi, poiché conosci le etichette reali, calcola la precisione e richiama manualmente.
Tasos,

Taso, posso suggerire gentilmente di ripubblicare la risposta in questa domanda SO: come devo implementare la precisione e richiamare le metriche nel mio modello di rete neurale in keras? Saluti, Iraklis
desertnaut,

Spiacenti, ho appena visto che era chiuso :(
desertnaut

Qualche idea sul perché questo non funzioni sulla convalida per me? funziona bene per l'allenamento.
Rodrigo Ruiz, il

13

È possibile utilizzare il rapporto di classificazione scikit-learn . Per convertire le etichette in un formato numerico o binario dai un'occhiata al codificatore di etichette scikit-learn .

from sklearn.metrics import classification_report

y_pred = model.predict(x_test, batch_size=64, verbose=1)
y_pred_bool = np.argmax(y_pred, axis=1)

print(classification_report(y_test, y_pred_bool))

che ti dà (output copiato dall'esempio di scikit-learn):

             precision  recall   f1-score    support

 class 0       0.50      1.00      0.67         1
 class 1       0.00      0.00      0.00         1
 class 2       1.00      0.67      0.80         3

2
Questo è quello che uso, semplice ed efficace.
Matteo,

2

Puoi anche provare come indicato di seguito.

from sklearn.metrics import f1_score, precision_score, recall_score, confusion_matrix
y_pred1 = model.predict(X_test)
y_pred = np.argmax(y_pred1, axis=1)

# Print f1, precision, and recall scores
print(precision_score(y_test, y_pred , average="macro"))
print(recall_score(y_test, y_pred , average="macro"))
print(f1_score(y_test, y_pred , average="macro"))

0

Ho provato questo: model.recision_recall_fscore_support (Y_test, y_pred, average = 'micro') e ottengo questo errore nell'esecuzione: AttributeError: l'oggetto 'Sequential' non ha alcun attributo 'recision_recall_fscore_support'
ZelelB

Non è necessario specificare model.recision_recall_fscore_support (), piuttosto solo recision_recall_fscore_support (Y_test, y_pred, average = 'micro') (senza "modello") e assicurarsi di avere l'importazione corretta: da sklearn.metrics import precision_recall_fscore_support)
Viacheslav Komisarenko,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.