web-dev-qa-db-fra.com

Comment calculer F1 Macro dans Keras?

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

18
Aryo Pradipta Gema

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é. 

36
Paddy

Je suggère aussi cette solution de contournement

  • installer keras_metrics package de ybubnov
  • appelez 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 époque

Quelque 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)

2
arcticriki

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

2
Dieshe

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.

0