使用tf.estimator.train_and_evaluate时如何有效地改组大型tf.data.Dataset?

时间:2018-01-17 11:06:09

标签: tensorflow tensorflow-datasets tensorflow-estimator

tf.estimator.train_and_evaluate文档清楚地表明输入数据集必须正确洗牌才能进行培训以查看所有示例:

  

过度拟合:为了避免过度拟合,建议设置训练input_fn以正确地改变训练数据。在进行评估之前,还建议将模型训练一段时间,比如多个时期,因为输入管道从头开始进行每次训练。这对当地的培训和评估尤为重要。

在我的应用程序中,我想从具有任意评估频率和tf.data.Dataset缓冲区大小的完整shuffle()中统一采样示例。否则,培训最多可以看到第一个:

(steps_per_second * eval_delay * batch_size) + buffer_size

元素,有效地丢弃其余元素。有没有一种有效的方法可以解决这个问题,而无需在系统内存中加载完整的数据集?

我根据缓冲区大小考虑了sharding数据集,但如果评估不经常发生,它将在同一个分片上多次迭代(repeat()关闭管道)。理想情况下,我想在对数据集进行完整迭代后转移到另一个分片,这可能吗?

感谢您的任何指示!

1 个答案:

答案 0 :(得分:0)

可以使用此数据集转换实现数据集的随机分片:

def random_shard(shard_size, dataset_size):
  num_shards = -(-dataset_size // shard_size)  # Ceil division.
  offsets = np.linspace(
      0, dataset_size, num=num_shards, endpoint=False, dtype=np.int64)

  def _random_shard(dataset):
    sharded_dataset = tf.data.Dataset.from_tensor_slices(offsets)
    sharded_dataset = sharded_dataset.shuffle(num_shards)
    sharded_dataset = sharded_dataset.flat_map(
        lambda offset: dataset.skip(offset).take(shard_size))
    return sharded_dataset

  return _random_shard

这需要提前知道总数据集大小。但是,如果实现基于文件的分片方法,则还要对整个数据集进行一次迭代,这不是主要问题。

关于效率,请注意skip(offset)实际上会迭代offset示例,因此如果offset很大,则会出现延迟。仔细预取应该有助于此。