[英]Custom metric based on tensorflow's streaming metrics returns NaN
我正在尝试将 F1 分数定义为 TensorFlow 中DNNClassifier
的自定义指标。 为此,我编写了一个函数
def metric_fn(predictions=[], labels=[], weights=[]):
P, _ = tf.contrib.metrics.streaming_precision(predictions, labels)
R, _ = tf.contrib.metrics.streaming_recall(predictions, labels)
if P + R == 0:
return 0
return 2*(P*R)/(P+R)
使用 TensorFlow 中的streaming_precision
和streaming_recall
来计算 F1 分数。 之后,我在validation_metrics 中创建了一个新条目:
validation_metrics = {
"accuracy":
tf.contrib.learn.MetricSpec(
metric_fn=tf.contrib.metrics.streaming_accuracy,
prediction_key=tf.contrib.learn.PredictionKey.CLASSES),
"precision":
tf.contrib.learn.MetricSpec(
metric_fn=tf.contrib.metrics.streaming_precision,
prediction_key=tf.contrib.learn.PredictionKey.CLASSES),
"recall":
tf.contrib.learn.MetricSpec(
metric_fn=tf.contrib.metrics.streaming_recall,
prediction_key=tf.contrib.learn.PredictionKey.CLASSES),
"f1score":
tf.contrib.learn.MetricSpec(
metric_fn=metric_fn,
prediction_key=tf.contrib.learn.PredictionKey.CLASSES)
}
然而,虽然我得到了正确的精度和召回值,但f1score
总是nan
:
INFO:tensorflow:Saving dict for global step 151: accuracy = 0.982456, accuracy/baseline_label_mean = 0.397661, accuracy/threshold_0.500000_mean = 0.982456, auc = 0.982867, f1score = nan, global_step = 151, labels/actual_label_mean = 0.397661, labels/prediction_mean = 0.406118, loss = 0.310612, precision = 0.971014, precision/positive_threshold_0.500000_mean = 0.971014, recall = 0.985294, recall/positive_threshold_0.500000_mean = 0.985294
我的metric_fn
,但我想不通。 metric_fn
获得的值P
和R
的形式为Tensor("precision/value:0", shape=(), dtype=float32)
。 我觉得这有点奇怪。 我期待一个标量张量。
任何帮助表示赞赏。
我认为问题可能来自这样一个事实,即您在metric_fn
使用的流媒体指标没有得到任何更新。
尝试以下操作(我还对我的口味稍作修改):
def metric_fn(predictions=None, labels=None, weights=None):
P, update_op1 = tf.contrib.metrics.streaming_precision(predictions, labels)
R, update_op2 = tf.contrib.metrics.streaming_recall(predictions, labels)
eps = 1e-5;
return (2*(P*R)/(P+R+eps), tf.group(update_op1, update_op2))
tf.learn.MetricSpec
__init__
第一个参数是metric_fn
。
文档说:
metric_fn:用作度量的函数。 有关如何将预测、标签和权重传递给此函数的规则,请参阅 _adapt_metric_fn。 这必须返回一个单独的张量,它被解释为这个度量的值,或者一对 (value_op, update_op),其中 value_op 是调用以获取度量值的操作,并且应该为每个批次运行 update_op更新内部状态。
由于您想在metric_fn
使用流操作,因此不能返回单个 Tensor,但您必须考虑到流操作具有必须更新的内部状态。
因此,您的metric_fn
的第一部分应该是:
def metric_fn(predictions=[], labels=[], weights=[]):
P, update_precision = tf.contrib.metrics.streaming_precision(predictions, labels)
R, update_recall = tf.contrib.metrics.streaming_recall(predictions, labels)
然后,如果您想在满足条件时返回0
,则不能使用 python if
语句(不是在张量流图中计算的),但必须使用tf.cond
(图中的计算)。
此外,您只想在更新操作后检查P
和R
的值(否则第一个值是 undefined 或nan
)。
要在P
和R
更新后强制评估tf.cond
,可以使用tf.control_dependencies
def metric_fn(predictions=[], labels=[], weights=[]):
P, update_precision = tf.contrib.metrics.streaming_precision(predictions, labels)
R, update_recall = tf.contrib.metrics.streaming_recall(predictions, labels)
with tf.control_dependencies([P, update_precision, R, update_recall]):
score = tf.cond(tf.equal(P + R, 0.), lambda: 0, lambda: 2*(P*R)/(P+R))
return score, tf.group(update_precision, update_recall)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.