如何在 Keras 中计算精度和召回率

Posted

技术标签:

【中文标题】如何在 Keras 中计算精度和召回率【英文标题】:How to calculate precision and recall in Keras 【发布时间】:2017-08-21 22:38:34 【问题描述】:

我正在用 Keras 2.02(带有 Tensorflow 后端)构建一个多类分类器,但我不知道。请帮帮我。

【问题讨论】:

我从这个页面注意到:ja.ojit.com/so/tensorflow/3439045 你可以使用非标准的损失,比如对 Keras 的precision_recall_auc_loss()。我尝试过但未能重用您提供的代码 sn-p。是否可以发布更完整的示例代码? 【参考方案1】:

Python 包 keras-metrics 可能对此有用(我是包的作者)。

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

更新:从Keras 版本2.3.0 开始,库分发包中提供了精度、召回率等指标。

用法如下:

model.compile(optimizer="sgd",
              loss="binary_crossentropy",
              metrics=[keras.metrics.Precision(), keras.metrics.Recall()])

【讨论】:

提及您是此软件包的作者可能是个好主意,这既是为了充分披露您的隶属关系,也为了使您的回答更具可信度。 @Dref360 说“从 Keras 2.0 开始,精度和召回率已从主分支中删除。” -- 那么这是已删除的指标,还是您仍然可以将 keras_metric 与 Keras 2.0 一起使用? 它在 Keras 2.2.2 和 keras-metrics 0.0.5 中给出了准确率和召回率 = 0.000。我使用了与上面相同的代码。但是当我使用@Christian 发布的解决方案时,它会返回值。 @DrGeneral,能否请您提供一个模型和您使用的训练数据,以便我可以验证实施有什么问题。我记得,版本为 <1.8.0Tensorflow 后端存在计算问题。 @YashaBubnov,哦。我使用的是 tensorflow 1.5,我的模型是一个 LSTM,在最后一层有 sigmoid 激活。我很高兴为您提供帮助,但我不能分享公司的数据。对不起:)【参考方案2】:

我的回答是基于comment of Keras GH issue。它为 onehot-encoded 分类任务在每个 epoch 计算验证精度和召回率。另请查看SO answer,了解如何使用keras.backend 功能完成。

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

【讨论】:

这里需要recall_score(y_val, y_predict, average=None)precision_score(y_val, y_predict, average=None)。默认是average=binary,你会得到一个错误,因为这是多类分类。 您的代码使用对象“模型”的外部引用。【参考方案3】:

这个帖子有点陈旧,但以防万一它会帮助有人登陆这里。如果您愿意升级到 Keras v2.1.6,尽管似乎还有更多工作要做(https://github.com/keras-team/keras/pull/9446)。

无论如何,我发现集成精度/召回率的最佳方法是使用子类 Layer 的自定义指标,如 BinaryTruePositives 中的示例所示。

回想一下,这看起来像:

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   

【讨论】:

【参考方案4】:

为此使用 Scikit Learn 框架。

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)

This blog 很有用。

【讨论】:

这是你最后要做的事情。但是要获得每个时代的这些值并查看它们如何演变?【参考方案5】:

从 Keras 2.0 开始,精度和召回率已从主分支中删除。您必须自己实施它们。按照本指南创建自定义指标:Here。

精确度和召回率方程可以找到Here

或者在删除之前重用 keras 中的代码Here。

删除了一些指标,因为它们是分批的,因此值可能正确也可能不正确。

【讨论】:

感谢您的回答。但是,当我在删除之前重用 keras 中的代码时,精度和召回值都为 0。为什么? 为什么他们被删除了? 即使链接断开,请确保您的回答有用。 可以在此处找到删除说明,以及使用回调实现计算它的解决方案:github.com/keras-team/keras/issues/5794 是否可以调整代码并计算整个数据集的相应指标,即训练和测试?我看到 github 线程中提供了一些解决方案,但我无法确定它们是分批还是跨整个数据集

以上是关于如何在 Keras 中计算精度和召回率的主要内容,如果未能解决你的问题,请参考以下文章

如何计算精度和召回率

计算精度和召回率

python实现计算精度召回率和F1值

如何计算两个嵌套数组的精度和召回率 [关闭]

如何在 python 中使用 libSVM 计算精度、召回率和 F 分数

在 Keras 分类神经网络中进行精度交易以获得更好的召回率