在Tensorflow估算器中创建自定义指标

时间:2019-04-12 18:56:50

标签: tensorflow tensorflow-estimator

我正在使用张量流估计器训练分类问题。

我想计算每批数据的f1分数以及精度和召回率。

我使用下面的代码计算精度并进行召回,并将其记录下来以进行评估和培训。

我也使用公式计算fscore,但是在记录fscore时出现错误。

pre = tf.metrics.precision(labels=labels,predictions=pred,name="precision")

rec = tf.metrics.recall(labels=labels,predictions=pred,name="recall")

fscore_val = tf.reduce_mean((2*pre[0]*rec[0]) / (pre[0] + rec[0] + 1e-5))
fscore_update = tf.group(pre[1], rec[1])

fscore = (fscore_val, fscore_update)

# logging metric at evaluation time
metrics['precision'] = pre                    
metrics['recall'] = rec
metrics['fscore'] = fscore 

# logging metric at training time                   
tf.summary.scalar('precision', pre[1])
tf.summary.scalar('recall', rec[1])
tf.summary.scalar('fscore', fscore)


这是我得到的错误。

TypeError: Expected float32, got <tf.Operation 'metrics_Left_Lane_Type/group_deps' type=NoOp> of type 'Operation' instead.

我了解为什么会收到此错误。 这是因为fscore应该是两个值,类似于Precision和Recall。

有人可以在张量估计中帮助我吗?

1 个答案:

答案 0 :(得分:1)

首先,TensorFlow拥有自己的f1得分tf.contrib.metrics.f1_score,使用起来非常简单。唯一可能的缺点是,它会向用户隐藏阈值,从指定数量的可能阈值中选择最佳阈值。

predictions = tf.sigmoid(logits)
tf.contrib.metrics.f1_score(labels, predictions, num_thresholds=20)

如果出于任何原因想要自定义实现,则需要将update_ops分组。每个TensorFlow指标都有可增加其值的操作。您可以在定义预测时手动设置阈值

predictions = tf.greater(tf.sigmoid(logits), 0.5)
def f1_score(labels, predictions):
    precision, update_op_precision = tf.metrics.precision(labels, predictions)
    recall, update_op_recall = tf.metrics.recall(labels, predictions)
    eps = 1e-5 #small constant for numerical stability
    f1 = 2 * precision * recall / (precision + recall + eps)
    f1_upd = 2 * update_op_precision * update_op_recall / (update_op_precision + update_op_recall + eps)
    return f1, f1_upd

f1_score = f1_score(labels, predictions)

然后您可以将其添加到eval_metric_ops字典或传递给summary.scalar

eval_metric_ops = {'f1': f1_score}
tf.summary.scalar('f1', f1_score[1])

使用contrib模块的指标,它实际上给出了非常接近的结果