2

我开始使用新的数据集 API,我想做的一件事没有在文档中描述(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")

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

笔记:

一种解决方案是使用方法定义 epoch 的数量,dataset.repeat() 但使用它我们有点松散地跟踪我们在训练中的位置。

我想在每个时期(一次遍历所有数据)之后检查损失的演变。

4

2 回答 2

2

首先,我建议量化馈送XY每次初始化迭代器的性能开销。tf.int32对于像和这样的原始类型,tf.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)

  # ...
于 2017-10-09T20:18:16.517 回答
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)

请注意,由于重复已打开,您需要计算在每个 epoch 中循环一次数据所需的确切迭代次数,并将其设置在您的内部循环中。

于 2018-10-01T07:51:06.277 回答