我正在使用tf.estimator.train_and_evaluate
和tf.data.Dataset
将数据提供给估算工具:
输入数据功能:
def data_fn(data_dict, batch_size, mode, num_epochs=10):
dataset = {}
if mode == tf.estimator.ModeKeys.TRAIN:
dataset = tf.data.Dataset.from_tensor_slices(data_dict['train_data'].astype(np.float32))
dataset = dataset.cache()
dataset = dataset.shuffle(buffer_size= batch_size * 10).repeat(num_epochs).batch(batch_size)
else:
dataset = tf.data.Dataset.from_tensor_slices(data_dict['valid_data'].astype(np.float32))
dataset = dataset.cache()
dataset = dataset.batch(batch_size)
iterator = dataset.make_one_shot_iterator()
next_element = iterator.get_next()
return next_element
训练功能:
def train_model(data):
tf.logging.set_verbosity(tf.logging.INFO)
config = tf.ConfigProto(allow_soft_placement=True,
log_device_placement=False)
config.gpu_options.allow_growth = True
run_config = tf.contrib.learn.RunConfig(
save_checkpoints_steps=10,
keep_checkpoint_max=10,
session_config=config
)
train_input = lambda: data_fn(data, 100, tf.estimator.ModeKeys.TRAIN, num_epochs=1)
eval_input = lambda: data_fn(data, 1000, tf.estimator.ModeKeys.EVAL)
estimator = tf.estimator.Estimator(model_fn=model_fn, params=hps, config=run_config)
train_spec = tf.estimator.TrainSpec(train_input, max_steps=100)
eval_spec = tf.estimator.EvalSpec(eval_input,
steps=None,
throttle_secs = 30)
tf.estimator.train_and_evaluate(estimator, train_spec, eval_spec)
培训很顺利,但在评估方面我得到了这个错误:
OutOfRangeError (see above for traceback): End of sequence
如果我不在评估数据集上使用Dataset.batch
(通过省略dataset[name] = dataset[name].batch(batch_size)
中的行data_fn
),我会得到相同的错误但是经过更长的时间后。
如果我不批量处理数据并使用steps=1
进行评估,我只能避免此错误,但这会对整个数据集执行评估吗?
我不明白导致此错误的原因,因为文档显示我也应该能够对批次进行评估。
注意:在数据批次上使用tf.estimator.evaluate
时会出现相同的错误。
答案 0 :(得分:0)
我将此问题发布为github问题,以下是Tensorflow团队的回复:
https://github.com/tensorflow/tensorflow/issues/19541
从“xiejw”复制以获得完整性:
如果我理解正确,这个问题是“一旦给估算器一个带有数据集的input_fn,评估过程就会出现OutOfRangeError错误。”
Estimator实际上可以正确处理这个问题。但是,已知的常见根本原因是model_fn中定义的度量标准有bug。我们需要首先排除这一部分。
@mrezak如果可能的话,你能展示一下关于model_fn的代码吗?或者,如果您有一个可重现性最小的脚本,那将非常有用。 - 提前致谢。
常见问题是:tensorflow中的metric应返回两个Ops:update_op和value_op。 Estimator为输入源中的每批数据调用update_op,一旦耗尽,就调用value_op来获取度量值。这里的value_op应该依赖于只读变量的依赖。
许多model_fn将value_op的依赖项与输入管道放在一起,因此,estimator.evaluate将再次触发输入管道,这会导致OutOfRangeError错误
问题确实是我如何定义eval_metric
中的model_fn
。在我的实际代码中,我要优化的总损失由多个损失(重建+ L2 + KL)组成,在评估部分我想得到重建损失(在验证数据上),这取决于输入数据管道。我的实际重建成本比MSE更复杂(也没有其他的tf.metric函数),使用tf.metric基本函数不能直接实现。
这是解决问题的“xiejw”的建议:
my_total_loss = ... # the loss you care. Pay attention to how you reduce the loss.
eval_metric_ops = {'total_loss: tf.metrics.mean(my_total_loss)}