【问题标题】:Calculate F1 Score using tf.metrics.precision/recall in a tf.Estimator setup在 tf.Estimator 设置中使用 tf.metrics.precision/recall 计算 F1 分数
【发布时间】:2019-05-06 07:56:11
【问题描述】:

我正在尝试在 tf.Estimator 设置中计算 F1 分数。

我看过这个SO question,但无法从中提炼出可行的解决方案。

tf.Estimator 的问题是它希望我提供一个值和一个更新操作,所以现在,我的模型末尾有这段代码:

if mode == tf.estimator.ModeKeys.EVAL:
    with tf.variable_scope('eval'):
        precision, precision_update_op = tf.metrics.precision(labels=labels,
                                            predictions=predictions['class'],
                                            name='precision')

        recall, recall_update_op = tf.metrics.recall(labels=labels,
                                      predictions=predictions['class'],
                                      name='recall')

        f1_score, f1_update_op = tf.metrics.mean((2 * precision * recall) / (precision + recall), name='f1_score')

        eval_metric_ops = {
            "precision": (precision, precision_update_op),
            "recall": (recall, recall_update_op),
            "f1_score": (f1_score, f1_update_op)}

现在准确率和召回率似乎工作得很好,但在 F1 分数上,我不断得到nan

我应该如何让它发挥作用?

编辑:

使用tf.contrib.metrics.f1_score 可以实现有效的解决方案,但由于contrib 将在 TF 2.0 中被弃用,我会很感激contrib-less 解决方案

【问题讨论】:

    标签: python tensorflow tensorflow-estimator


    【解决方案1】:

    我是这样做的:

    def f1_score_class0(labels, predictions):
        """
        To calculate f1-score for the 1st class.
        """
        prec, update_op1 = tf.compat.v1.metrics.precision_at_k(labels, predictions, 1, class_id=0)
        rec,  update_op2 = tf.compat.v1.metrics.recall_at_k(labels, predictions, 1, class_id=0)
    
        return {
                "f1_Score_for_class0":
                    ( 2*(prec * rec) / (prec + rec) , tf.group(update_op1, update_op2) )
        }
    

    【讨论】:

      【解决方案2】:

      1) 你为什么要tf.metrics.mean?召回率和准确率是标量值

      2) 您是否尝试过打印f1_scoref1_update_op

      3) 从documentation of recall 他们提到如何

      为了在数据流上估计度量,该函数创建一个 update_op 来更新这些变量并返回召回率。 update_op 通过权重中的相应值对每个预测进行加权

      由于您直接从处理更新的两个操作中获得 F1 分数,因此请尝试执行 tf.identity(这实际上不会导致任何更改)

      【讨论】:

      • 你不能这样做,因为 eval_metric_ops 期望得到一个 (value, update_op) 的元组
      • 是的,所以第一个值是您计算的 f1_score,第二个操作只是身份操作?
      【解决方案3】:

      f1 值张量可以根据精度和召回值计算。指标必须是 (value, update_op) 元组。我们可以为 f1 传递 tf.identity。这对我有用:

      import tensorflow as tf
      
      def metric_fn(labels, logits):
          predictions = tf.argmax(logits, axis=-1)
          pr, pr_op = tf.metrics.precision(labels, predictions)
          re, re_op = tf.metrics.recall(labels, predictions)
          f1 = (2 * pr * re) / (pr + re)
          return {
              'precision': (pr, pr_op),
              'recall': (re, re_op),
              'f1': (f1, tf.identity(f1))
          }
      

      【讨论】:

      • 期望操作的tf.identity(f1)是什么意思?
      • 它将张量转换为虚拟操作,因为 tf.metrics 必须返回元组(值张量,更新操作)。
      • 你确定这行得通吗?据我了解,该操作用于批量计算指标的能力,因为这里的操作没有任何意义,我想知道它是否不会破坏分数
      【解决方案4】:
      猜你喜欢
      • 2017-05-07
      • 2017-09-11
      • 2019-11-25
      • 2017-12-30
      • 2021-08-29
      • 2016-01-24
      • 2020-10-02
      • 1970-01-01
      • 2015-12-10
      相关资源
      最近更新 更多