tfrecords文件是否有最佳数量的元素?

时间:2018-12-25 19:49:54

标签: tensorflow tfrecord

这是这些SO问题的后续行动

What is the need to do sharding of TFRecords files?

optimal size of a tfrecord file

以及本教程的这段内容

  

对于这个小的数据集,我们将仅创建一个TFRecords文件,用于   训练集,另一个为测试集。但是如果您的数据集非常   然后将其拆分成几个TFRecords文件   碎片。这也将改善随机改组,因为   数据集API仅从较小的缓冲区(例如1024个元素   加载到RAM中。所以如果你有100个TFRecords文件,然后   随机化比单个TFRecords文件要好得多。

https://github.com/Hvass-Labs/TensorFlow-Tutorials/blob/master/18_TFRecords_Dataset_API.ipynb

因此有一个最佳文件大小,但是我想知道是否有一个最佳数目的元素?既然是元素本身正在分发到GPU内核?

1 个答案:

答案 0 :(得分:2)

您是否要优化:

1个初始数据随机化? 2在训练批次和/或时期之间的数据随机化? 3个训练/验证吞吐量(即GPU利用率)?

当最初将数据保存到分片文件时,应处理初始数据随机化。假设您无法将数据读取到内存中,这将是一个挑战。一种方法是将所有唯一数据ID读取到内存中,将它们洗牌,进行训练/验证/测试拆分,然后以随机顺序将实际数据写入文件分片。现在,您的数据最初会被随机/拆分/分片。

初始数据随机化将使训练过程中更易于保持随机化。但是,我仍然会说,重新整理文件名并重新整理数据存储缓冲区作为训练/验证数据流的一部分是“最佳实践”。通常,您将使用多个线程/进程来设置输入流。第一步是通过重新组合文件名来随机化文件输入流。可以这样完成:

train_files = tf.data.Dataset.list_files('{}/d*.tfr'.format(train_dir),
                                            shuffle=True)

现在,如果您的初始数据写入已经是随机的,那么您可以“从”一个文件中读取整个数据,然后再转到下一个文件,但这仍然会影响整个训练过程中的重新随机化,因此通常情况下,您需要对文件进行交织从每个文件读取并读取一定数量的记录。假设您正在使用多个文件读取过程(这应该做以最大化gpu吞吐量),这也可以提高吞吐量。

blocksize  = 1000     # samples read from one file before switching files
train_data  = train_files.interleave(interleaveFiles,
              block_length=blocksize,
              num_parallel_calls=tf.data.experimental.AUTOTUNE)

在这里,我们从每个文件读取1000个样本,然后再继续下一个。再次,要在每个时期重新混合训练数据(这可能很关键或可能不是很关键),我们会重新混合内存中的数据,根据机器上可用的数据和数据项的大小设置内存缓冲区(注意-在为gpu格式化数据之前。)

buffersize = 1000000  # samples read before shuffling in memory
train_data  = train_data.shuffle(buffersize,
                                 reshuffle_each_iteration=True)
train_data  = train_data.repeat()

repeat()调用只是为了在训练过程中允许数据集“环绕”。这可能重要,也可能不重要,具体取决于您如何设置培训过程。

要优化吞吐量,您可以做两件事:

1更改数据输入流中的操作顺序。通常,如果您将随机运算放在较早的位置,则它们可以对“低权重”实体(如文件名)进行操作,而不是对张量进行操作。 2使用预取功能让您的CPU在GPU计算期间处理流数据

train_data  = train_data.map(mapData,
                  num_parallel_calls=tf.data.experimental.AUTOTUNE)
train_data  = train_data.padded_batch(batchsize)
train_data  = train_data.prefetch(10)

因此,映射和批处理最后发生(通常是最大化gpu吞吐量的首选方法,但它可能取决于其他因素,例如数据大小(预张紧和后张紧)以及映射函数的计算成本如何)。 / p>

最后,您可以调整预取大小以最大化gpu吞吐量,但受系统内存和内存速度的限制。

那么,这如何影响每个分片文件中数据项的“最佳”数量?

很显然,如果您的数据/文件大小为>块大小,则块大小变得无关紧要,您最好完全读取每个文件。通常,如果要使用此范例,则将块大小<<数据/文件。我用10倍;因此,如果我的块大小为1000,则文件中大约有10,000个数据项。这可能不是最佳选择,但是到目前为止,我可以在我的特定硬件上使用这种方法将gpu使用率保持在90%以上。如果您想调整硬件,则可以根据特定的优化条件,从〜10倍左右开始调整。

如果文件数量非常大,可能会在维护良好的文件读取流时遇到问题,但是在现代系统上,您应该可以获取100,000个或更多文件,并且仍然可以。移动大量文件可能很困难,但是通常比拥有非常少量的非常大的文件容易,因此文件大小受到一些(广泛)限制,这些限制可能影响最终获得多少数据项/文件。一般来说,对于大型数据集,拥有大约100个文件的文件将是理想的选择。这样,您可以轻松高效地在网络上流式传输文件(同样,这取决于您的网络)。如果数据集很小,那么您将拥有10到50 s的文件,这适合流传输,具体取决于文件大小(我通常尝试达到100-300MB /文件,这非常适合在LAN或WAN上移动内容)。

因此,我认为文件大小和文件数比数据项/文件数对流程的约束要强得多,只要给定文件读取的块大小,只要您有适当数量的数据项/文件即可。同样,您可以对文件进行超分片处理(1个数据项/文件?),并将整个文件读入内存,而无需使用文件阻止功能。那可能行得通,而且改组文件名而不是数据项肯定很轻巧。但是您最终可能还会拥有数百万个文件!

要真正进行优化,您需要在特定计算机上设置端到端培训系统,然后对其进行调整,以了解最适合您的特定数据,网络和硬件的系统。只要您的数据有效地随机化并且数据文件易于存储/使用/共享,您就只想优化GPU吞吐量。如果对数据输入流进行重新排序和预取不能使您满意,我会感到惊讶。