将 tfrecord 文件拆分为分片有什么好处?

数据挖掘 Python 张量流
2021-10-10 22:19:09

我正在使用 Tensorflow 进行语音识别,并计划使用海量波数据集训练 LSTM NN。由于性能提升,我计划使用 tfrecords。互联网上有几个示例(例如 Inception),其中 tfrecords 文件被拆分为碎片。我的问题是:将 tfrecords 文件放入分片有什么好处?此拆分是否有任何额外的性能提升?

4个回答

将 TFRecord 文件拆分为分片可帮助您对不适合内存的大型数据集进行混洗。

想象一下,您在磁盘上保存了数百万个训练示例,并且您希望通过训练过程重复运行它们。此外,假设对于训练数据的每次重复(即每个时期),您希望以完全随机的顺序加载数据。

一种方法是每个训练示例有一个文件并生成所有文件名的列表。然后在每个 epoch 开始时,你打乱文件名列表并加载单个文件。这种方法的问题是您从磁盘上的随机位置加载数百万个文件。这可能会很慢,尤其是在硬盘驱动器上。如果您从随机位置加载数百万个小文件,即使是 RAID 0 阵列也无助于提高速度。如果您通过网络连接访问文件,问题会变得更糟。

另一种方法是从一个大的 TFRecord 文件中按顺序读取训练示例,并使用 shuffle 缓冲区对内存中的示例进行随机播放。但是,shuffle 缓冲区通常不能大于 CPU 可用的 DDR 内存。如果洗牌缓冲区明显小于您的数据集,那么它可能无法充分洗牌数据。数据可以“本地”打乱,但不能“全局”打乱。也就是说,数据集开头的示例可能不会与数据集末尾的示例混在一起。

一个好的解决方案是通过将数据集拆分为多个 TFRecord 文件(称为分片)来平衡使用上述两种方法的组合。在每个 epoch 期间,您可以打乱分片文件名以获得全局打乱,并使用打乱缓冲区来获得本地打乱。良好的平衡将使分片足够大以防止磁盘速度问题,但会使分片足够小以允许通过洗牌缓冲区进行充分洗牌。

以下是具体步骤:

  1. 将所有训练示例随机放入多个 TFRecord 文件(分片)中。
  2. 在每个 epoch 开始时,打乱分片文件名列表。
  3. 从分片中读取训练示例并将示例通过随机缓冲区传递。通常,混洗缓冲区应大于分片大小,以确保在分片之间进行良好的混洗。
  4. 将打乱的示例传递到您的训练过程中。

在研究拆分为多个文件的好处时,唯一合理的答案来自一位 Google 人员。

他们说性能提升可以忽略不计,但我同意拆分文件会有所帮助,特别是如果您想将数据集传输到另一个位置。

请记住,现在您不需要在保存之前进行随机播放,因为(当前)推荐的读取 TFRecords 的方法使用tf.data.TFRecordDataset实现了非常有用的.shuffle()方法。

对于那些仍然想知道的人:这样您就可以对数据进行洗牌。将您的 TFrecords 放在一个文件中,您无法重新排序。这通常是 SGD 所必需的。

但是,使用分片,您可以打乱分片的顺序,这使您可以近似地打乱数据,就好像您可以访问单个 TFRecords。这显然总比没有好,显然你拥有的分片越多,这个近似值就越好。

另一种方法是通过复制来预洗您的数据,或者根本不使用 TFRecords。

将 TFRecords 文件拆分为多个分片基本上具有 3 个优点:

  1. 更容易洗牌正如其他人所指出的,它可以很容易地在粗略的水平上对数据进行洗牌(在使用洗牌缓冲区之前)。
  2. 下载速度更快如果文件分布在多个服务器上,从不同服务器并行下载多个文件将优化带宽使用(而不是从单个服务器下载一个文件)。与从单个服务器下载数据相比,这可以显着提高性能。
  3. 操作更简单处理 10,000 个 100MB 的文件比处理一个 1TB 的文件更容易。处理大文件可能会很痛苦:尤其是传输更容易失败。当数据全部在一个文件中时,操作数据子集也更加困难。