【问题标题】:How to cache data during the first epoch correctly (Tensorflow, dataset)?如何在第一个时期正确缓存数据(Tensorflow,数据集)?
【发布时间】:2018-11-04 06:30:57
【问题描述】:

我正在尝试将cache 转换用于dataset。这是我当前的代码(简化):

dataset = tf.data.TFRecordDataset(filenames, num_parallel_reads=1)
dataset = dataset.apply(tf.contrib.data.shuffle_and_repeat(buffer_size=5000, count=1))
dataset = dataset.map(_parser_a, num_parallel_calls=12)
dataset = dataset.padded_batch(
    20, 
    padded_shapes=padded_shapes,
    padding_values=padding_values
)
dataset = dataset.prefetch(buffer_size=1)
dataset = dataset.cache()

在第一个 epoch 之后,我收到以下错误消息:

调用迭代器没有完全读取我们正在尝试的数据集 缓存。为了避免序列的意外截断, 当前的 [部分缓存] 序列将被删除。如果发生这种情况 你有一个类似于dataset.cache().take(k).repeat() 的序列。 相反,交换订单(即dataset.take(k).cache().repeat()

然后,代码继续执行,仍然从硬盘驱动器而不是缓存中读取数据。那么,我应该在哪里放置 dataset.cache() 以避免错误? 谢谢。

【问题讨论】:

  • 如何使用来自dataset 的数据?特别是,您如何确定要采取多少步骤?如果您将dataset 读到最后(即当相关的迭代器引发tf.errors.OutOfRangeError),那么它应该会成功缓存。
  • 谢谢,@mrry。我将尝试使用tf.errors.OutOfRangeError 来确定我的dataset 的结尾。目前,我通过num_batches_per_epochs=math.ceil(num_Training_examples / batch_size) 计算一个时期内的批次数。一旦批次计数达到num_batches_per_epochs,我认为一个时期已经完成并开始下一个时期(从sess.run(iterator.initializer)开始)。
  • 使用tf.errors.OutOfRangeError 确定dataset 的结束后,不再出现错误消息(在几个epoch 后恢复训练时也可以正常工作)。再次感谢@mrry。
  • 如果我们使用tf.errors.OutOfRangeError来判断一个dataset的结束,那么repeat转换的count应该是1,否则永远不会抛出tf.errors.OutOfRangeError

标签: tensorflow tensorflow-datasets


【解决方案1】:

Dataset.cache() 转换的实现相当简单:当您第一次迭代完全它时,它会构建一个通过它的元素列表,并从中返回元素列出后续尝试对其进行迭代的尝试。如果第一遍只对数据执行部分遍,那么列表是不完整的,TensorFlow 不会尝试使用缓存的数据,因为它不知道是否需要剩余的元素,通常它可能需要重新处理所有前面的元素来计算剩余的元素。

通过修改您的程序以使用整个数据集并对其进行迭代直到出现tf.errors.OutOfRangeError,缓存将拥有数据集中元素的完整列表,并将用于所有后续迭代。

【讨论】:

  • 嗨@mrry。如果我的map() 涉及随机行为(如随机裁剪和随机旋转),我应该将cache() 相对于map() 放在哪里?我的猜测是放在cache() 之前,因为您不想在相同的图像作物上训练后续时期。
  • 没错:如果您将cache() 放在 随机map() 之后,那么它将缓存第一组随机决策。将 cache() before 放在随机的 map() 应该可以按预期工作。 (请注意,这意味着您可能希望将 map() 分成两部分,确定性部分在 cache() 之前,随机部分在 cache() 之后。)
  • shuffle 方法呢?如果缓存方法是在之后放置的,那么它将使洗牌变得无用,并且总是以相同的顺序返回数据。如果是这样,我认为应该在文档中更清楚地说明这一点
  • @SamueleCornell 是的,现在在文档中说明了这一点。检查此link。它说“缓存将在数据集的每次迭代期间产生完全相同的元素。如果您希望随机化迭代顺序,请确保在调用缓存之后调用 shuffle。”
  • 太棒了! tf.data.Dataset 文档现在好多了。我记得当时它相当稀缺(因为 API 有点新)。
猜你喜欢
  • 2018-06-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-10-15
  • 2021-07-06
  • 2020-12-27
  • 2022-01-04
  • 2021-04-04
相关资源
最近更新 更多