j'ai essayé d'utiliser les codes donnés par Keras avant qu'ils ne soient supprimés. Voici le code:
def precision(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 recall(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 fbeta_score(y_true, y_pred, beta=1):
if beta < 0:
raise ValueError('The lowest choosable beta is zero (only precision).')
# If there are no true positives, fix the F score at 0 like sklearn.
if K.sum(K.round(K.clip(y_true, 0, 1))) == 0:
return 0
p = precision(y_true, y_pred)
r = recall(y_true, y_pred)
bb = beta ** 2
fbeta_score = (1 + bb) * (p * r) / (bb * p + r + K.epsilon())
return fbeta_score
def fmeasure(y_true, y_pred):
return fbeta_score(y_true, y_pred, beta=1)
D'après ce que j'ai vu (je suis un amateur dans ce domaine), il semble qu'ils utilisent la bonne formule. Mais, lorsque j'ai essayé de l'utiliser comme métrique dans le processus de formation, j'ai obtenu des résultats identiques pour val_accuracy, val_precision, val_recall et val_fmeasure. Je pense que cela peut arriver même si la formule est correcte, mais j'estime que c'est peu probable. Une explication à ce problème? Je vous remercie
depuis Keras 2.0, les mesures f1, la précision et le rappel ont été supprimées. La solution consiste à utiliser une fonction de métrique personnalisée:
from keras import backend as K
def f1(y_true, y_pred):
def recall(y_true, y_pred):
"""Recall metric.
Only computes a batch-wise average of recall.
Computes the recall, a metric for multi-label classification of
how many relevant items are selected.
"""
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(y_true, y_pred):
"""Precision metric.
Only computes a batch-wise average of precision.
Computes the precision, a metric for multi-label classification of
how many selected items are relevant.
"""
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
precision = precision(y_true, y_pred)
recall = recall(y_true, y_pred)
return 2*((precision*recall)/(precision+recall+K.epsilon()))
model.compile(loss='binary_crossentropy',
optimizer= "adam",
metrics=[f1])
La ligne de retour de cette fonction
return 2*((precision*recall)/(precision+recall+K.epsilon()))
a été modifié en ajoutant la constante epsilon, afin d'éviter la division par 0. Ainsi, NaN ne sera pas calculé.
Je suggère aussi cette solution de contournement
model.fit(nb_Epoch=1, ...)
dans une boucle for en tirant parti des mesures de précision/rappel générées après chaque époqueQuelque chose comme ça:
for mini_batch in range(epochs):
model_hist = model.fit(X_train, Y_train, batch_size=batch_size, epochs=1,
verbose=2, validation_data=(X_val, Y_val))
precision = model_hist.history['val_precision'][0]
recall = model_hist.history['val_recall'][0]
f_score = (2.0 * precision * recall) / (precision + recall)
print 'F1-SCORE {}'.format(f_score)
L'utilisation d'une fonction métrique de Keras n'est pas la bonne façon de calculer F1 ou AUC ou quelque chose comme ça.
La raison en est que la fonction de métrique est appelée à chaque étape du lot lors de la validation. De cette façon, le système Keras calcule une moyenne sur les résultats du lot. Et ce n’est pas le bon score en F1.
C'est la raison pour laquelle le score de F1 a été supprimé des fonctions métriques dans keras. Vois ici:
Pour ce faire, utilisez une fonction de rappel personnalisée de la manière suivante: https://medium.com/@thongonary/how-to-compute-f1-score-for-each-Epoch -in-keras-a1acd17715a2
Comme le dit @Pedia dans son commentaire ci-dessus, on_Epoch_end
, comme indiqué dans le fichier github.com/fchollet/keras/issues/5400 est la meilleure approche.