tf.constant 和 tf.placeholder 的行为不同



我想将tf.metrics包装在一个十四行诗模块周围,以测量每个批次的性能,以下是我所做的工作:

import tensorflow as tf
import sonnet as snt
class Metrics(snt.AbstractModule):
def __init__(self, indicator, summaries = None, name = "metrics"):
super(Metrics, self).__init__(name = name)
self._indicator = indicator
self._summaries = summaries
def _build(self, labels, logits):
if self._indicator == "accuracy":
metric, metric_update = tf.metrics.accuracy(labels, logits)
with tf.control_dependencies([metric_update]):
outputs = tf.identity(metric)
elif self._indicator == "precision":
metric, metric_update = tf.metrics.precision(labels, logits)
with tf.control_dependencies([metric_update]):
outputs = tf.identity(metric)
elif self._indicator == "recall":
metric, metric_update = tf.metrics.recall(labels, logits)
with tf.control_dependencies([metric_update]):
outputs = tf.identity(metric)
elif self._indicator == "f1_score":
metric_recall, metric_update_recall = tf.metrics.recall(labels, logits)
metric_precision, metric_update_precision = tf.metrics.precision(labels, logits)
with tf.control_dependencies([metric_update_recall, metric_update_precision]):
outputs = 2.0 / (1.0 / metric_recall + 1.0 / metric_precision)
else:
raise ValueError("unsupported metrics")
if type(self._summaries) == list:
self._summaries.append(tf.summary.scalar(self._indicator, outputs))
return outputs

但是,当我想测试模块时,以下代码有效:

def test3():
import numpy as np
labels = tf.constant([1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0], tf.int32)
logits = tf.constant([1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0], tf.int32)
metrics = Metrics("accuracy")
accuracy = metrics(labels, logits)
metrics2 = Metrics("f1_score")
f1_score = metrics2(labels, logits)
writer = tf.summary.FileWriter("utils-const", tf.get_default_graph())
with tf.Session() as sess:
sess.run([tf.global_variables_initializer(), tf.local_variables_initializer()])
accu, f1 = sess.run([accuracy, f1_score])
print(accu)
print(f1)
writer.close()

但是,以下代码不起作用:

def test4():
from tensorflow.python import debug as tf_debug
import numpy as np
tf_labels = tf.placeholder(dtype=tf.int32, shape=[None])
tf_logits = tf.placeholder(dtype=tf.int32, shape=[None])
labels = np.array([1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0], np.int32)
logits = np.array([1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0], np.int32)
metrics = Metrics("accuracy")
accuracy = metrics(tf_labels, tf_logits)
metrics2 = Metrics("f1_score")
f1_score = metrics2(tf_labels, tf_logits)
writer = tf.summary.FileWriter("utils-feed", tf.get_default_graph())
with tf.Session() as sess:
sess.run([tf.global_variables_initializer(), tf.local_variables_initializer()])
sess = tf_debug.LocalCLIDebugWrapperSession(sess)
accu, f1 = sess.run([accuracy, f1_score], feed_dict = {tf_labels: labels, tf_logits: logits})
print(accu)
print(f1)
writer.close()

test3(( 的输出是正确的,0.88。test4(( 的输出是错误的,0.0。但是,它们应该是等效的。

有人知道吗?

你确定失败的不是tf.constant版本吗?我发现tf.metrics结合tf.constant有一种奇怪的行为:

import tensorflow as tf
a = tf.constant(1.)
mean_a, mean_a_uop = tf.metrics.mean(a)
with tf.control_dependencies([mean_a_uop]):
mean_a = tf.identity(mean_a)
sess = tf.InteractiveSession()
tf.global_variables_initializer().run()
tf.local_variables_initializer().run()
for _ in range(10):
print(sess.run(mean_a))

在 GPU 上运行时返回,

0.0
2.0
1.5
1.3333334
1.25
1.2
1.1666666
1.1428572
1.125
1.1111112

而不是1S。看起来计数好像滞后了一。(我假设第一个值是inf但由于count的某些条件而为零(。另一方面,此代码的占位符版本按预期运行。

在 CPU 上,由于输出是不确定的,因此行为更加奇怪。输出示例:

0.0
1.0
1.0
0.75
1.0
1.0
0.85714287
0.875
1.0
0.9

看起来像一个错误,你可以登录tensorflow的github存储库。(请注意,对常量使用运行指标没有多大用处 - 但它仍然是一个错误(。

编辑现在我还偶然发现了一个奇怪的tf.placeholder例子,似乎tf.metrics有一个错误,不幸的是,它不仅限于与tf.constants 一起使用。

最新更新