Python tf.data.Dataset.map()和tf.data.Dataset.apply()之间的差异

Python tf.data.Dataset.map()和tf.data.Dataset.apply()之间的差异,python,tensorflow,tensorflow-datasets,Python,Tensorflow,Tensorflow Datasets,随着最近升级到1.4版,Tensorflow在库核心中包含了tf.data。 is中描述的一个“主要新特性”,即“用于 应用自定义转换函数”。这与现有的有何不同?区别在于map将分别对数据集的每个元素执行一个函数,而apply将一次性对整个数据集执行一个函数(如文档中的示例所示) apply的参数是一个函数,当map的参数是一个函数,它接受一个Dataset并返回一个Dataset,而map的参数是一个接受一个元素并返回一个转换后的元素。是绝对正确的。你可能还想知道我们为什么要介绍,我想我会提供

随着最近升级到1.4版,Tensorflow在库核心中包含了
tf.data
。 is中描述的一个“主要新特性”,即“用于
应用自定义转换函数”。这与现有的有何不同?

区别在于
map
将分别对
数据集的每个元素执行一个函数,而
apply
将一次性对整个
数据集执行一个函数(如文档中的示例所示)

apply
的参数是一个函数,当
map
的参数是一个函数,它接受一个
Dataset
并返回一个
Dataset
,而
map
的参数是一个接受一个元素并返回一个转换后的元素。

是绝对正确的。你可能还想知道我们为什么要介绍,我想我会提供一些背景资料

tf.data
API有一组核心转换,如
Dataset.map()
Dataset.filter()
——它们通常在广泛的数据集中有用,不太可能更改,并作为
tf.data.Dataset
对象上的方法实现。特别是,它们与TensorFlow中的其他核心API受相同的约束

然而,核心方法有点限制。我们还希望在将新转换添加到核心之前能够自由地进行实验,并允许其他库开发人员创建自己的可重用转换。因此,在TensorFlow 1.4中,我们划分了一组自定义转换,这些转换存在于
tf.contrib.data
中。自定义转换包括一些具有非常特定功能的转换(如),以及一些API仍在不断变化的转换(如)。最初,我们将这些自定义转换实现为从
Dataset
Dataset
的函数,这对管道的语法流产生了不幸的影响。例如:

dataset = tf.data.TFRecordDataset(...).map(...)

# Method chaining breaks when we apply a custom transformation.
dataset = custom_transformation(dataset, x, y, z)

dataset = dataset.shuffle(...).repeat(...).batch(...)
由于这似乎是一种常见的模式,我们添加了
Dataset.apply()
,作为在单个管道中链接核心和自定义转换的一种方式:

dataset = (tf.data.TFRecordDataset(...)
           .map(...)
           .apply(custom_transformation(x, y, z))
           .shuffle(...)
           .repeat(...)
           .batch(...))

这是总体方案中的一个次要功能,但希望它有助于使
tf.data
程序更易于阅读,库更易于扩展。

我没有足够的声誉发表评论,但我只是想指出,实际上可以使用map应用于数据集中的多个元素,这与@sunreef在自己的帖子中的评论相反

根据文档,map将作为参数

map_func:映射张量嵌套结构的函数(具有 由self.output\u形状和self.output\u类型定义的形状和类型) 到另一个嵌套的张量结构

输出_形状由数据集定义,可以使用批处理等api函数进行修改。因此,例如,您可以仅使用dataset.batch和.map执行批标准化,方法是:

dataset = dataset ...
dataset.batch(batch_size)
dataset.map(normalize_fn)

apply()
的主要功能似乎是在您真正想要对整个数据集进行转换时

简单地说,
apply()
transformation\u func
的论点是
Dataset
map()
map\u func
的参数是
element

…我想知道与
apply
一起使用的新函数的文档在哪里。现在我看到函数在tf.**contrib**.data中,而Dataset API被移动到了tf.data中,这就是我搜索的地方。我恐怕在实际操作中仍然不理解其中的区别<代码>映射
用于转换数据集中的值,而
应用
对数据集本身进行“操作”。。。因此,<代码>应用< /代码>也可以替换<代码> map < /C> >“代码>应用< /代码>,当您需要同时考虑多个元素时。例如,如果您想创建一个数据集中平均有五个连续元素的数据集,那么使用
map
我明白了!好的,现在有道理了。因此,如果我理解正确,
apply
可以完全替换
map
(因为如果它可以访问所有项目,它也可以一次访问一个项目,就像
map
),但是为
apply
编写函数并不像编写对值本身进行操作的函数那样简单,因此,出于实际原因,我们需要保留
map
。这有意义吗?我就是这么理解的,是的。如果您想用
apply
调用替换
map
,那么
apply
中的函数无论如何都必须执行与
map
等效的操作。谢谢!!这正是我希望理解的,也是我完全掌握新界面所缺少的部分。我会将@Sunreef的答案标记为“the”答案,但事实上这两个答案是互补的。@mrry map和apply是如何执行的,它们是否每次都在批大小上执行?一旦图形初始化,迭代器的下一个元素是否应用于整个数据集?我问这个问题的原因是,如果在每个批次上应用,加载像imagenet这样的数据集可能需要更长的时间,而整个批次都是一次性的dataset@Eliethesaiyan
tf.data
中的大多数转换都是无状态和流式的,这意味着,当处理可能不适合内存的大型数据集时,它们可以立即返回结果,并消耗很少的内存。这意味着,如果在这些转换之后有一个
Dataset.repeat()
,那么它们将在每次传递数据时执行。如果要避免这种情况,请在要执行一次的转换之后添加一个
Dataset.cache()
。@mrry您能否提供一个
自定义转换的“hello world实现”
?您的用例确实可以通过批处理和映射的组合来构建,