Comment obtenir précision, F1, précision et rappel, pour un modèle à kéros?

21

Je veux calculer la précision, le rappel et le score F1 pour mon modèle binaire KerasClassifier, mais je ne trouve aucune solution.

Voici mon code actuel:

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

Et puis je prédit sur de nouvelles données de test, et j'obtiens la matrice de confusion comme ceci:

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

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

Mais existe-t-il une solution pour obtenir le score d'exactitude, le score F1, la précision et le rappel? (Si ce n'est pas compliqué, également le score de validation croisée, mais pas nécessaire pour cette réponse)

Merci pour toute aide!

ZelelB
la source

Réponses:

20

Les mesures ont été supprimées du noyau Keras. Vous devez les calculer manuellement. Ils les ont supprimés sur la version 2.0 . Ces métriques sont toutes des métriques globales, mais Keras fonctionne par lots. Par conséquent, cela pourrait être plus trompeur qu'utile.

Cependant, si vous en avez vraiment besoin, vous pouvez le faire comme ceci

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)
Tasos
la source
s'ils peuvent être trompeurs, comment alors évaluer un modèle Keras?
ZelelB
1
Puisque Keras calcule ces métriques à la fin de chaque lot, vous pouvez obtenir des résultats différents à partir des "vraies" métriques. Une autre façon serait de diviser votre ensemble de données en formation et en test et d'utiliser la partie test pour prédire les résultats. Ensuite, puisque vous connaissez les vraies étiquettes, calculez la précision et rappelez-les manuellement.
Tasos
Taso, puis-je vous suggérer de bien vouloir republier votre réponse dans cette question SO: Comment dois-je implémenter des mesures de précision et de rappel dans mon modèle de réseau neuronal en keras?
Santé
Désolé, je viens de voir qu'il était fermé :(
desertnaut
Une idée pourquoi cela ne fonctionne pas sur la validation pour moi? fonctionne très bien pour la formation.
Rodrigo Ruiz
13

Vous pouvez utiliser le rapport de classification scikit-learn . Pour convertir vos étiquettes en un format numérique ou binaire jeter un oeil à l' encodeur d'étiquettes 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))

ce qui vous donne (sortie copiée de l'exemple 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
matse
la source
2
C'est ce que j'utilise, simple et efficace.
Matthew
2

Vous pouvez également essayer comme mentionné ci-dessous.

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"))
Ashok Kumar Jayaraman
la source
0

Essayez ceci: https://scikit-learn.org/stable/modules/generated/sklearn.metrics.precision_recall_fscore_support.html avec Y_test, y_pred comme paramètres.

Viacheslav Komisarenko
la source
J'ai essayé ceci: model.recision_recall_fscore_support (Y_test, y_pred, average = 'micro') et j'obtiens cette erreur lors de l'exécution: AttributeError: l'objet 'Sequential' n'a pas d'attribut 'recision_recall_fscore_support'
ZelelB
Vous n'avez pas besoin de spécifier model.recision_recall_fscore_support (), mais simplement recision_recall_fscore_support (Y_test, y_pred, average = 'micro') (sans "model") et assurez-vous que vous avez la bonne importation: depuis sklearn.metrics import precision_recall_fscore_support)
Viacheslav Komisarenko