tf.metrics.mean_iou输入tf.constant时返回异常值求助
问题原因分析
你遇到的问题核心在于 tf.metrics.mean_iou 是带状态的流式指标——它内部会维护一个累加状态(比如各类别的真阳性、假阳性、假阴性计数),用来持续计算累计的平均IOU。
你的代码里每次循环调用 sess.run(miou) 时,其实同时做了两件事:
- 基于当前累计的状态计算出一个mean_iou值
- 执行内部的
update_op,把当前批次的标签和预测结果加到累计状态里
所以第一次循环用的是初始状态,得到的是单批次IOU;第二次循环时状态已经累计了第一次的数据,得到的是两次的平均IOU;以此类推,每次循环都会累加状态,自然输出值会不断变化。而你预期的0.061是单批次的IOU结果,和累计后的结果自然不符。
解决方案
要让每次循环都输出相同的单批次IOU,需要在每次循环前重置指标的内部状态,同时明确拆分指标的更新和取值步骤。修改后的代码如下:
import numpy as np import tensorflow as tf """ iou=TP/(TP + FP + FN) """ num_iteration = 10 num_classes = 3 l = np.array([[0, 1, 2, 0], [1, 0, 1, 0], [0, 1, 1, 1], [0, 2, 2, 0]]) tf_label = tf.constant(l, dtype=tf.int32) p0 = np.array([[0.0, 0.1, 0.7, 0.3], [0.6, 0.3, 0.4, 0.9], [0.3, 0.6, 0.3, 0.1], [0.1, 0.2, 0.3, 0.4]]) p1 = np.array([[0.6, 0.1, 0.1, 0.3], [0.6, 0.3, 0.4, 0.9], [0.3, 0.6, 0.3, 0.1], [0.1, 0.5, 0.5, 0.4]]) p2 = 1 - p0 - p1 p = np.stack((p0, p1, p2), axis=2) tf_logit = tf.constant(p, dtype=tf.float32) tf_prediction = tf.argmax(tf_logit, axis=2) # 拆分mean_iou的取值操作和状态更新操作 mean_iou, update_op = tf.metrics.mean_iou(labels=tf_label, predictions=tf_prediction, num_classes=num_classes) # 获取mean_iou相关的所有局部状态变量 metric_vars = tf.get_collection(tf.GraphKeys.LOCAL_VARIABLES, scope="mean_iou") # 定义重置状态的操作 reset_metric = tf.variables_initializer(metric_vars) sv = tf.train.Supervisor(logdir=None, summary_op=None) with sv.managed_session() as sess: for i in range(num_iteration): # 每次循环前重置指标状态,回到初始值 sess.run(reset_metric) # 先更新当前批次的状态 sess.run(update_op) # 再获取当前批次的mean_iou结果 current_miou = sess.run(mean_iou) print(f"第{i+1}次循环: {current_miou:.3f}")
代码说明
- 拆分操作:把
tf.metrics.mean_iou返回的结果拆成mean_iou(取值操作)和update_op(状态更新操作),明确两者的职责。 - 重置状态:通过
tf.get_collection拿到指标的状态变量,定义重置操作,确保每次循环都从零开始计算当前批次的IOU。 - 先更新再取值:先执行
update_op把当前批次的标签和预测计入状态,再获取mean_iou,这样得到的就是单批次的IOU结果。
运行这段代码后,每次循环都会输出你预期的0.061。
内容的提问来源于stack exchange,提问作者Troy
相关产品推荐
相关产品推荐

