tensorflow mean_iou - 如何获得一致的结果

kmh*_*kmh 5 python image-segmentation keras tensorflow

我被 tensorflow 指标 mean_iou() 难住了。我尝试使用会导致对相同数据的结果不一致,而且我在任何地方都找不到有用的示例。

这篇博客文章讨论了这个问题......但我无法用这里的想法解决我的问题。 http://ronny.rest/blog/post_2017_09_11_tf_metrics/

最终目标是将validation_func(y_true, y_pred)arg 'metric' 作为参数传递给 Keras Model.compile() 方法。

最终目标

就像是...

def my_iou(y_true, y_pred):
  num_classes = 2
  score, update_op = tf.metrics.mean_iou(tf.argmax(y_true, axis=3), tf.argmax(y_pred, axis=3), num_classes)
  K.get_session().run(tf.local_variables_initializer())
  # K.get_session().run(tf.global_variables_initializer())
  with tf.control_dependencies([update_op]):
    final_score = tf.identity(score)
  return final_score
Run Code Online (Sandbox Code Playgroud)

虚拟数据

  • 尺寸将是:(批次,高度,宽度,num_classes)
  • 第 1 类 - 前景对象;我想分割的东西
  • 0级 - 背景

我真正关心的是 1 类的 IOU。在这种情况下,它应该是 7/9=0.778。我希望这会吐出的是每个班级的平均欠条......

  • 借条 0 类:0/2=0
  • 借条 1 级:7/9=0.778
  • 总体:平均(iou_0,iou_1)=0.3889

数据

from keras import backend as K
import tensorflow as tf
import numpy as np

y_true = np.zeros(18, dtype='int32').reshape((1,3,3,2))
y_true[:,:,:,1] = 1
y_true[:,0,0,1] = 0
y_true[:,0,0,0] = 1

y_pred = np.zeros(18, dtype='float32').reshape((1,3,3,2))
y_pred[:,:,:,1] = 1.0
y_pred[:,-1,-1,1] = 0.1
y_pred[:,-1,-1,0] = 0.9
Run Code Online (Sandbox Code Playgroud)

如果我用类似下面的东西进行模拟,我大部分时间都会得到预期的 0.3889……但我偶尔也会得到 3.5 或 0.0,我不知道为什么?

results = []
for i in range(20):
  with tf.Session() as sess:
    y_t = tf.convert_to_tensor(y_true)
    y_p = tf.convert_to_tensor(y_pred)
    results.append(my_iou(y_t, y_p).eval())
Run Code Online (Sandbox Code Playgroud)

最近的一次跑步

[0.3888889,
 0.3888889,
 0.3888889,
 0.3888889,
 3.5,
 0.3888889,
 0.3888889,
 0.3888889,
 0.3888889,
 0.3888889,
 0.3888889,
 0.3888889,
 0.3888889,
 3.5,
 0.3888889,
 0.3888889,
 0.3888889,
 3.5,
 0.3888889,
 0.3888889]
Run Code Online (Sandbox Code Playgroud)

有什么帮助吗?

编辑

现在我正在使用专门用于二进制分类的硬编码,但我不喜欢它。不可概括,可能太简单了,而且可能完全错误。(同样值得注意的是……在这段代码中,类 0 是前景,不像我的示例设置,类 1 是前景)

def my_iou_binary(self, y_true, y_pred):
  yt0 = y_true[:,:,:,0]
  yp0 = K.cast(y_pred[:,:,:,0] > 0.5, 'float32')

  inter = tf.count_nonzero(tf.logical_and(tf.equal(yt0, 1), tf.equal(yp0, 1)))
  union = tf.count_nonzero(tf.add(yt0, yp0))
  iou = tf.where(tf.equal(union, 0), 1., tf.cast(inter/union, 'float32'))

  return iou
Run Code Online (Sandbox Code Playgroud)