如何将多个tfrecords文件合并成一个文件?

9
我的问题是,如果我想为我的数据创建一个tfrecords文件,那么完成它需要大约15天的时间,其中包含500000对模板,每个模板有32帧(图像)。为了节省时间,我有3个GPU,所以我想可以在每个GPU上创建一个tfrocords文件,然后我可以在5天内完成创建tfrecords。但是我搜索了一种将这三个文件合并成一个文件的方法,但找不到适当的解决方案。
那么,有没有办法将这三个文件合并成一个文件,或者有没有办法通过从这三个tfrecords文件中提取示例批次来训练我的网络,知道我正在使用Dataset API。
4个回答

16

由于问题是两个月前提出的,我认为你已经找到了解决方案。对于接下来的问题,答案是否定的,你不需要创建一个巨大的tfrecord文件。只需使用新的DataSet API:

dataset = tf.data.TFRecordDataset(filenames_to_read,
    compression_type=None,    # or 'GZIP', 'ZLIB' if compress you data.
    buffer_size=10240,        # any buffer size you want or 0 means no buffering
    num_parallel_reads=os.cpu_count()  # or 0 means sequentially reading
)

# Maybe you want to prefetch some data first.
dataset = dataset.prefetch(buffer_size=batch_size)

# Decode the example
dataset = dataset.map(single_example_parser, num_parallel_calls=os.cpu_count())

dataset = dataset.shuffle(buffer_size=number_larger_than_batch_size)
dataset = dataset.batch(batch_size).repeat(num_epochs)
...

有关详细信息,请查看文档


2
实际上,是的,你是对的。我发现解决方案只需通过tf.data.TFRecordDataset()传递一个文件名列表即可。我忘了提及答案。但是对于另一个较小的数据集,我注意到如果你传递单个tfrecord文件比传递多个tfrecord文件更准确,我不知道为什么。我认为两种方式之间唯一的区别是洗牌方式不同。那么,你认为只有一个tfrecords文件比使用多个tfrecords文件好吗? - W. Sam
在TFRecordDataset的num_parallel_reads文档中,他们说它代表并行读取文件的数量,但是在你的示例中将其设置为CPU核心数。所以如果我有12个CPU核心和3个tfrecord文件,我应该将其设置为12还是3?对于dataset.map中的num_parallel_calls也是同样的问题。 - W. Sam
@W.Sam 如果文件不是太大,比如小于10GB,我更喜欢使用单个文件。事实上,我在这里更改了num_parallel_calls。有些参考资料称此应该等于批量大小。我认为这应该被视为超参数,以找出哪个更好。 - Holmes Conan
我的训练数据是330 G,验证数据是179,测试数据是424,我认为针对这种情况,我需要一个多文件列表。 - W. Sam
@holmescn 感谢您的回答,有没有办法在时期之间洗牌文件名而不是实际数据? - Elbek

10

针对任何想合并多个.tfrecord文件的人,直接回答问题标题:

最方便的方法是使用tf.Data API: (根据文档中的示例进行修改)

# Create dataset from multiple .tfrecord files
list_of_tfrecord_files = [dir1, dir2, dir3, dir4]
dataset = tf.data.TFRecordDataset(list_of_tfrecord_files)

# Save dataset to .tfrecord file
filename = 'test.tfrecord'
writer = tf.data.experimental.TFRecordWriter(filename)
writer.write(dataset)

然而,正如holmescn所指出的那样,最好将.tfrecord文件保留为单独的文件,并将它们作为一个单独的TensorFlow数据集读取。

您还可以参考Data Science Stackexchange上有关多个.tfrecord文件的更长讨论。


2

MoltenMuffins的答案适用于更高版本的tensorflow。然而,如果您使用较低版本,则必须遍历三个tfrecords并将它们保存到新的记录文件中,如下所示。这适用于tf版本1.0及以上。

def comb_tfrecord(tfrecords_path, save_path, batch_size=128):
        with tf.Graph().as_default(), tf.Session() as sess:
            ds = tf.data.TFRecordDataset(tfrecords_path).batch(batch_size)
            batch = ds.make_one_shot_iterator().get_next()
            writer = tf.python_io.TFRecordWriter(save_path)
            while True:
                try:
                    records = sess.run(batch)
                    for record in records:
                        writer.write(record)
                except tf.errors.OutOfRangeError:
                    break

仅提供代码的答案是不被鼓励的。请添加一些解释,说明如何解决问题,或者这与现有答案有何不同。来自审核 - Nick

1
定制上述脚本以更好地列出tfrecords。
import os
import glob
import tensorflow as tf
save_path = 'data/tf_serving_warmup_requests'
tfrecords_path = glob.glob('data/*.tfrecords')
dataset = tf.data.TFRecordDataset(tfrecords_path)
writer = tf.data.experimental.TFRecordWriter(save_path)
writer.write(dataset)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接