web-dev-qa-db-fra.com

Comment calculer la précision et le rappel en keras

Je construis un classificateur multi-classes avec Keras 2.02 (avec backend Tensorflow) , et je ne sais pas comment calculer la précision et le rappel dans Keras. Aidez-moi, s'il vous plaît.

38
Jimmy Du

Le paquet Python keras-metrics pourrait être utile pour cela (je suis l'auteur du paquet).

import keras
import keras_metrics

model = models.Sequential()
model.add(keras.layers.Dense(1, activation="sigmoid", input_dim=2))
model.add(keras.layers.Dense(1, activation="softmax"))

model.compile(optimizer="sgd",
              loss="binary_crossentropy",
              metrics=[keras_metrics.precision(), keras_metrics.recall()])
33
Yasha Bubnov

À partir de Keras 2.0, la précision et le rappel ont été supprimés de la branche principale. Vous devrez les mettre en œuvre vous-même. Suivez ce guide pour créer des métriques personnalisées: Ici .

On peut trouver l'équation de précision et de rappel Ici

Ou réutilisez le code de keras avant qu'il ne soit supprimé Ici .

Ces métriques ont été supprimées car elles ont été effectuées par lots, de sorte que la valeur peut être incorrecte ou non.

30
Dref360

Ma réponse est basée sur le commentaire du numéro de Keras GH . Il calcule la précision de la validation et le rappel à chaque époque pour une tâche de classification codée en onehot. Regardez aussi ceci SO SO pour voir comment cela peut être fait avec keras.backend Fonctionnalité.

import keras as keras
import numpy as np
from keras.optimizers import SGD
from sklearn.metrics import precision_score, recall_score

model = keras.models.Sequential()
# ...
sgd = SGD(lr=0.001, momentum=0.9)
model.compile(optimizer=sgd, loss='categorical_crossentropy', metrics=['accuracy'])


class Metrics(keras.callbacks.Callback):
    def on_train_begin(self, logs={}):
        self._data = []

    def on_Epoch_end(self, batch, logs={}):
        X_val, y_val = self.validation_data[0], self.validation_data[1]
        y_predict = np.asarray(model.predict(X_val))

        y_val = np.argmax(y_val, axis=1)
        y_predict = np.argmax(y_predict, axis=1)

        self._data.append({
            'val_recall': recall_score(y_val, y_predict),
            'val_precision': precision_score(y_val, y_predict),
        })
        return

    def get_data(self):
        return self._data


metrics = Metrics()
history = model.fit(X_train, y_train, epochs=100, validation_data=(X_val, y_val), callbacks=[metrics])
metrics.get_data()
4
vogdb

Ce fil est un peu fade, mais au cas où cela aiderait quelqu'un à atterrir ici. Si vous souhaitez mettre à niveau vers Keras v2.1.6, vous avez beaucoup de mal à faire en sorte que les métriques avec état fonctionnent, bien qu’il semble que davantage de travail soit en cours ( https://github.com/keras -équipe/keras/pull/9446 ).

Quoi qu'il en soit, j'ai trouvé que le meilleur moyen d'intégrer précision/rappel était d'utiliser la métrique personnalisée qui sous-classe Layer, illustrée par un exemple dans BinaryTruePositives .

Pour rappel, cela ressemblerait à:

class Recall(keras.layers.Layer):
    """Stateful Metric to count the total recall over all batches.

    Assumes predictions and targets of shape `(samples, 1)`.

    # Arguments
        name: String, name for the metric.
    """

    def __init__(self, name='recall', **kwargs):
        super(Recall, self).__init__(name=name, **kwargs)
        self.stateful = True

        self.recall = K.variable(value=0.0, dtype='float32')
        self.true_positives = K.variable(value=0, dtype='int32')
        self.false_negatives = K.variable(value=0, dtype='int32')
    def reset_states(self):
        K.set_value(self.recall, 0.0)
        K.set_value(self.true_positives, 0)
        K.set_value(self.false_negatives, 0)

    def __call__(self, y_true, y_pred):
        """Computes the number of true positives in a batch.

        # Arguments
            y_true: Tensor, batch_wise labels
            y_pred: Tensor, batch_wise predictions

        # Returns
            The total number of true positives seen this Epoch at the
                completion of the batch.
        """
        y_true = K.cast(y_true, 'int32')
        y_pred = K.cast(K.round(y_pred), 'int32')

        # False negative calculations
        y_true = K.cast(y_true, 'int32')
        y_pred = K.cast(K.round(y_pred), 'int32')
        false_neg = K.cast(K.sum(K.cast(K.greater(y_pred, y_true), 'int32')), 'int32')
        current_false_neg = self.false_negatives * 1
        self.add_update(K.update_add(self.false_negatives,
                                     false_neg),
                        inputs=[y_true, y_pred])
        # True positive  calculations
        correct_preds = K.cast(K.equal(y_pred, y_true), 'int32')
        true_pos = K.cast(K.sum(correct_preds * y_true), 'int32')
        current_true_pos = self.true_positives * 1
        self.add_update(K.update_add(self.true_positives,
                                     true_pos),
                        inputs=[y_true, y_pred])
        # Combine
        recall = (K.cast(self.true_positives, 'float32') / (K.cast(self.true_positives, 'float32') + K.cast(self.false_negatives, 'float32') + K.cast(K.epsilon(), 'float32')))
        self.add_update(K.update(self.recall,
                                     recall),
                        inputs=[y_true, y_pred])

        return recall   
1
vsocrates

Utilisez le cadre Scikit Learn pour cela.

from sklearn.metrics import classification_report

history = model.fit(x_train, y_train, batch_size=32, epochs=10, verbose=1, validation_data=(x_test, y_test), shuffle=True)
pred = model.predict(x_test, batch_size=32, verbose=1)
predicted = np.argmax(pred, axis=1)
report = classification_report(np.argmax(y_test, axis=1), predicted)
print(report)

Ce blog est très utile.

0
Jesús Utrera