如何使用新的数据集API在tensorflow中使用占位符循环数据一次

时间:2017-10-06 07:50:09

标签: python tensorflow tensorflow-datasets

我开始使用新的数据集API,我想要做的一件事没有在doc(https://www.tensorflow.org/programmers_guide/datasets#training_workflows)上描述

我的数据适合内存,所以我想在tensorflow中加载它以使训练有效,为此我现在看到2种方法:

一个是直接在图表中加载数据:

dataset = tf.contrib.data.Dataset.from_tensor_slices((X, Y))
iterator = dataset.make_initializable_iterator()
next_element = iterator.get_next()

# loop on epochs
for _ in range(5):
    # Initialize an iterator over the training dataset.
    sess.run(iterator.initializer)
    # loop over all the batch
    for _ in range(1000):
        s = time.time()
        try:
            sess.run(next_element)
        except tf.errors.OutOfRangeError:
            print("Finish epoch")

另一个是在占位符中加载数据,因此数据不会保存在图表中:

features_placeholder = tf.placeholder(features.dtype, features.shape)
labels_placeholder = tf.placeholder(labels.dtype, labels.shape)

dataset = tf.contrib.data.Dataset.from_tensor_slices((features_placeholder, labels_placeholder))
iterator = dataset.make_initializable_iterator()
next_element = iterator.get_next()

# loop on epochs
for _ in range(5):
    # Initialize an iterator over the training dataset.
    sess.run(iterator.initializer, feed_dict={features_placeholder: X, labels_placeholder: Y})
    # loop over all the batch
    for _ in range(1000):
        s = time.time()
        try:
            sess.run(next_element)
        except tf.errors.OutOfRangeError:
            print("Finish epoch")

第二个是我认为最好的节省内存,但我不想在每个时代提供数据。它实际上是对性能的损失。

有没有办法用占位符初始化迭代器一次?

类似的东西:

sess.run(iterator.initializer, feed_dict={features_placeholder: X, labels_placeholder: Y})

# loop on epochs
for _ in range(5):
    # Initialize an iterator over the training dataset.
    sess.run(iterator.initializer)
    # loop over all the batch
    for _ in range(1000):
        s = time.time()
        try:
            sess.run(next_element)
        except tf.errors.OutOfRangeError:
            print("Finish epoch")

这样我们可以保持第一个解决方案的性能,并像第二个解决方案一样节省内存。

  

注意:

     

一个解决方案是使用dataset.repeat()定义纪元数   方法,但有了它我们松散的轨道我们在哪里   训练。

     

我想在每个纪元后检查(一次通过所有数据)   损失的演变。

2 个答案:

答案 0 :(得分:2)

首先,我建议在每次初始化迭代器时量化提供XY的性能开销。对于像tf.int32tf.float32这样的原始类型,通常可以在不复制任何数据的情况下提供值,在这种情况下,开销可以忽略不计。即使需要副本,也需要一个memcpy(),这可能会非常快。 (另一方面,提供tf.string张量可能更昂贵,因为它需要多个小副本才能在Python和C ++字符串表示之间进行转换。)

假设这是一个重要的开销,您可以通过将输入数据存储在tf.Variable中来使其成为一次性成本。例如:

placeholder_X = tf.placeholder(X.dtype, X.shape)
var_X = tf.Variable(placeholder_X)
placeholder_Y = tf.placeholder(Y.dtype, Y.shape)
var_Y = tf.Variable(placeholder_Y)

dataset = tf.contrib.data.Dataset.from_tensor_slices((var_X, var_Y))
iterator = dataset.make_initializable_iterator()

# ...

# The contents of `X` and `Y` will be copied once, in this call.
sess.run(tf.global_variables_initializer(), feed_dict={
    placeholder_X: X, placeholder_Y = Y})

for _ in range(5):
  # The iterator will be initialized from the variables with no copy.
  sess.run(iterator.initializer)

  # ...

答案 1 :(得分:0)

我认为您不需要在每个时代都进行初始化。您可以在训练循环之前执行一次。但是在定义数据集时,您还需要告诉数据集在每次迭代时都要重复和重新排列:

features_placeholder = tf.placeholder(features.dtype, features.shape)
labels_placeholder = tf.placeholder(labels.dtype, labels.shape)

dataset = tf.data.Dataset.from_tensor_slices((features_placeholder, labels_placeholder)).shuffle(buffer_value,reshuffle_each_iteration=True).repeat().batch(batch_num)
iterator = dataset.make_initializable_iterator()
next_element = iterator.get_next()

#Initialize an iterator over the training dataset.
sess.run(iterator.initializer, feed_dict={features_placeholder: X, labels_placeholder: Y})
    # loop on epochs
for _ in range(5):
    # loop over all the batch
    for _ in range(1000):
        s = time.time()
        sess.run(next_element)

请注意,由于重复功能已启用,因此您需要计算需要在每个时期循环一次数据并在内部循环中进行设置的确切迭代次数。