在tf.Estimator设置中使用tf.metrics.precision/recall计算F1分数



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

我见过这个SO问题,但无法从中提取出有效的解决方案。

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的解决方案

我是这样做的:

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

1(为什么要执行tf.metrics.mean?召回率和精度是的标量值

2( 你试过打印f1_scoref1_update_op吗?

3( 从召回文件中,他们提到

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

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

f1值张量可以根据精度值和调用值计算。度量必须是(value,update_op(元组。我们可以通过tf.identity获得f1。这对我有效:

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

TensorFlow插件已经有了正式的解决方案

https://www.tensorflow.org/addons/api_docs/python/tfa/metrics/F1Score

最新更新