tf.data.Dataset.interleave()与map()和flat_map()究竟有何不同?
我目前的理解是:
不同map_func:两个 interleave和flat_map期望“的函数映射数据集元素的数据集”。相反,map期望“将数据集元素映射到另一个数据集元素的函数”。
参数:两个interleave和map报价参数num_parallel_calls,而flat_map不会。此外,interleave 提供了这些神奇的参数 block_length 和 cycle_length。对于 cycle_length=1,文档说明 interleave 和 flat_map 的输出是相等的。
最后,我已经看到了数据加载管道没有交错以及与交错的人。任何建议何时使用interleavevs.map或flat_map将不胜感激
//编辑:如果我们从不同的数据集开始,我确实看到了 interleave 的值,例如在下面的代码中
files = tf.data.Dataset.list_files("/path/to/dataset/train-*.tfrecord")
dataset = files.interleave(tf.data.TFRecordDataset)
但是,在如下场景中使用interleaveover有什么好处map吗?
files = tf.data.Dataset.list_files("/path/to/dataset/train-*.png")
dataset = files.map(load_img, num_parallel_calls=tf.data.AUTOTUNE)
回答
编辑:
映射不能也用于并行化 I/O 吗?
实际上,您可以从具有map功能的目录中读取图像和标签。假设这种情况:
list_ds = tf.data.Dataset.list_files(my_path)
def process_path(path):
### get label here etc. Images need to be decoded
return tf.io.read_file(path), label
new_ds = list_ds.map(process_path,num_parallel_calls=tf.data.experimental.AUTOTUNE)
请注意,现在它num_parallel_calls已设置为多线程。
interlave()功能优势:
- 假设你有一个数据集
- 有了
cycle_length你可以从数据集中取出那么多元素,即 5,那么从数据集中取出 5 个元素,map_func可以应用 a。 - 之后,从新生成的对象中获取数据集对象,
block_length每次都是数据块。
换句话说,interleave()函数 c在应用a 的同时遍历您的数据集map_func()。此外,它可以同时处理多个数据集或数据文件。例如,来自文档:
dataset = dataset.interleave(lambda x:
tf.data.TextLineDataset(x).map(parse_fn, num_parallel_calls=1),
cycle_length=4, block_length=16)
但是,在如下场景中使用交错映射是否有任何好处?
两者interleave()和map()似乎有点相似,但它们的用例并不相同。如果你想在应用一些映射的同时读取数据集interleave()是你的超级英雄。您的图像可能需要在读取时进行解码。首先阅读所有内容,在处理大型数据集时解码可能效率低下。在您提供的代码片段中,AFAIKtf.data.TFRecordDataset应该更快。
TL;DR 通过交错读取文件的 I/O 操作来interleave()并行化数据加载步骤。
map() 将数据预处理应用于数据集的内容。
因此,您可以执行以下操作:
ds = train_file.interleave(lambda x: tf.data.Dataset.list_files(directory_here).map(func,
num_parallel_calls=tf.data.experimental.AUTOTUNE)
tf.data.experimental.AUTOTUNE将决定缓冲区大小、CPU 能力以及 I/O 操作的并行级别。换句话说,AUTOTUNE将在运行时动态处理关卡。
num_parallel_calls参数产生多个线程以利用多个内核来并行化任务。有了这个,您可以并行加载多个数据集,减少等待打开文件的时间;asinterleave也可以带参数num_parallel_calls。图片取自docs。
在图像中,有 4 个重叠的数据集,这是由参数 确定的cycle_length,所以在这种情况下cycle_length = 4。
FLAT_MAP:在整个数据集中映射一个函数并展平结果。如果您想确保订单保持不变,您可以使用它。它不num_parallel_calls作为一个论点。请参阅文档了解更多信息。
MAP:
该map函数将分别在数据集的每个元素上执行选定的函数。显然,随着您应用越来越多的操作,大型数据集上的数据转换可能会很昂贵。关键是,如果 CPU 没有得到充分利用,可能会更耗时。但我们可以使用parallelism APIs:
num_of_cores = multiprocessing.cpu_count() # num of available cpu cores
mapped_data = data.map(function, num_parallel_calls = num_of_cores)
对于 cycle_length=1,文档说明 interleave 和 flat_map 的输出相等
cycle_length--> 将被并发处理的输入元素的数量。设置为 时1,将一一处理。
INTERLEAVE:像map这样的转换操作可以并行化。
借助映射的并行性,在顶部 CPU 试图在转换中实现并行化,但是从磁盘中提取数据会导致开销。
此外,一旦将原始字节读入内存,可能还需要将函数映射到数据,这当然需要额外的计算。像解密数据等。各种数据提取开销的影响需要并行化,以便通过交错每个数据集的内容来减轻这种影响。
因此,在读取数据集时,您希望最大化:
图片来源:deeplearning.ai
- I edited the answer, see if it is clear now. I took the image from a video actually, that is available on coursera.