不能使用估算器+数据集并训练少于一个纪元

时间:2017-11-07 09:06:07

标签: tensorflow tensorflow-datasets tensorflow-estimator

TensorFlow 1.4将TF数据集移动到核心(tf.data.Dataset),doc / tutorial建议使用tf.estimator来训练模型。

但是,正如this page末尾所建议的那样,必须在input_fn函数内实例化数据集对象及其迭代器。这意味着每次调用estimator.train(input_fn, steps)时,数据集的迭代都将重新开始。因此,呼叫是步骤<在epoch中的样本数量将导致在数据集的子集上训练模型。

因此我的问题。是否可以使用Estimator + Dataset实现类似的功能:

for i in range(num_epochs):
    # Train for some steps
    estimator.train(input_fn=train_input_fn, steps=valid_freq)

    validation_iterator.
    # Evaluate on the validation set (steps=None, we evaluate on the full validation set)
    estimator.evaluate(input_fn=valid_input_fn)

没有在每次调用estimator.train(input_fn=train_input_fn, steps=valid_freq)时从头开始训练样本迭代?

例如,与here不同,在input_fn之外实例化数据集及其迭代器?我尝试了但它不起作用,因为输入(来自数据集迭代器)和模型(来自估算器model_fn)不属于同一个图形。

由于

相关GitHub issue

2 个答案:

答案 0 :(得分:1)

我不知道如何在estimator.train()的运行中使培训保持一致。

但是,您可以做的是确保构建train_input_fn,使其足够随机以获得相同的效果。

例如,假设您有一个值为[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]的数据集,并且每次调用estimator.train时只能训练一半数据集。
如果你没有足够好地洗牌,你将继续培训价值观[0, 1, 2, 3, 4]

train_size = 10
dataset = tf.data.Dataset.range(train_size)
x = dataset.make_one_shot_iterator().get_next()

sess = tf.Session()
for i in range(train_size // 2):
    print(sess.run(x))

但是,如果您使用buffer_size至少与数据集一样大的地方致电tf.data.Dataset.shuffle(),您将获得随机值。用这个多次调用estimator.train相当于用多个纪元调用它一次。

train_size = 10
dataset = tf.data.Dataset.range(train_size)
dataset = dataset.shuffle(buffer_size=train_size)
x = dataset.make_one_shot_iterator().get_next()

sess = tf.Session()
for i in range(train_size // 2):
    print(sess.run(x))

我写了另一个答案来解释buffer_size here的重要性。

答案 1 :(得分:0)

您可以从input_fn返回dataset。像这样:

def input_fn():
  dataset = ...
  return dataset

要在不停止培训过程的情况下进行评估,可以使用tf.contrib.estimator.InMemoryEvaluatorHook