tf.data.Dataset.map与tf.data.Dataset.interleave

1、map(一对一

map(
    map_func, num_parallel_calls=None
)

在此数据集的元素之间映射map_func。
此转换将map_func应用于此数据集的每个元素,并返回一个新的数据集,该数据集包含转换后的元素,顺序与它们在输入中出现的顺序相同。

示例:

a = Dataset.range(1, 6)  # ==> [ 1, 2, 3, 4, 5 ]

a.map(lambda x: x + 1)  # ==> [ 2, 3, 4, 5, 6 ]

map_func的输入签名由这个数据集中每个元素的结构决定。 例如:

# NOTE: The following examples use `{ ... }` to represent the contents of a dataset.
# Each element is a `tf.Tensor` object.
a = { 1, 2, 3, 4, 5 }
# `map_func` takes a single argument of type `tf.Tensor` with the same shape and dtype.
result = a.map(lambda x: ...)

# Each element is a tuple containing two `tf.Tensor` objects.
b = { (1, "foo"), (2, "bar"), (3, "baz") }
# `map_func` takes two arguments of type `tf.Tensor`.
result = b.map(lambda x_int, y_str: ...)

# Each element is a dictionary mapping strings to `tf.Tensor` objects.
c = { {"a": 1, "b": "foo"}, {"a": 2, "b": "bar"}, {"a": 3, "b": "baz"} }
# `map_func` takes a single argument of type `dict` with the same keys as the elements.
result = c.map(lambda d: ...)

map_func返回的一个或多个值决定返回数据集中每个元素的结构。

# `map_func` returns a scalar `tf.Tensor` of type `tf.float32`.
def f(...):
  return tf.constant(37.0)
result = dataset.map(f)
result.output_classes == tf.Tensor
result.output_types == tf.float32
result.output_shapes == []  # scalar

# `map_func` returns two `tf.Tensor` objects.
def g(...):
  return tf.constant(37.0), tf.constant(["Foo", "Bar", "Baz"])
result = dataset.map(g)
result.output_classes == (tf.Tensor, tf.Tensor)
result.output_types == (tf.float32, tf.string)
result.output_shapes == ([], [3])

# Python primitives, lists, and NumPy arrays are implicitly converted to
# `tf.Tensor`.
def h(...):
  return 37.0, ["Foo", "Bar", "Baz"], np.array([1.0, 2.0] dtype=np.float64)
result = dataset.map(h)
result.output_classes == (tf.Tensor, tf.Tensor, tf.Tensor)
result.output_types == (tf.float32, tf.string, tf.float64)
result.output_shapes == ([], [3], [2])

# `map_func` can return nested structures.
def i(...):
  return {"a": 37.0, "b": [42, 16]}, "foo"
result.output_classes == ({"a": tf.Tensor, "b": tf.Tensor}, tf.Tensor)
result.output_types == ({"a": tf.float32, "b": tf.int32}, tf.string)
result.output_shapes == ({"a": [], "b": [2]}, [])

map_func可以接受作为参数并返回任何类型的数据集元素。

请注意,不管map_func是在什么上下文中定义的(eager vs.graph),tf.data都会跟踪函数并将其作为图形执行。 要在函数内部使用Python代码,您有两个选择:

1)依赖AutoGraph将Python代码转换为等价的图计算,这种方法的缺点是AutoGraph可以转换部分而不是全部Python代码。

2)使用tf.py_function,它允许您编写任意Python代码,但通常会导致比1)更差的性能。例如:

d = tf.data.Dataset.from_tensor_slices(['hello', 'world'])

# transform a string tensor to upper case string using a Python function
def upper_case_fn(t: tf.Tensor) -> str:
    return t.numpy().decode('utf-8').upper()

d.map(lambda x: tf.py_function(func=upper_case_fn,
      inp=[x], Tout=tf.string))  # ==> [ "HELLO", "WORLD" ]

参数:

map_func: 将一个数据集元素映射到另一个数据集元素的函数。

num_parallel_calls:(可选) 一个tf.int32标量tf.tensor,表示要并行异步处理的数字元素。 如果未指定,则将按顺序处理元素。 如果使用值tf.data.experimental.AUTOTUNE ,则根据可用CPU动态设置并行调用的数量。

返回:

Dataset:一个数据集

2、interleave(一对多

思想:对现有的dataset中的每一个元素做处理,每个元素做完处理后会产生一个新的结果,interleave会把这些新的结果合并起来,形成一个新的数据集。
常用case: 文件名dataset -> 具体数据集

interleave(
    map_func, cycle_length=AUTOTUNE, block_length=1, num_parallel_calls=None
)

在此数据集中映射“map_func”,并对结果进行interleave(交错)。例如,可以使用DataSet.Interleave()并发处理许多输入文件: 同时预处理4个文件,并交错处理每个文件中的16条记录。

# Preprocess 4 files concurrently, and interleave blocks of 16 records from
# each file.
filenames = ["/var/data/file1.txt", "/var/data/file2.txt", ...]
dataset = (Dataset.from_tensor_slices(filenames)
           .interleave(lambda x:
               TextLineDataset(x).map(parse_fn, num_parallel_calls=1),
               cycle_length=4, block_length=16))

cycle_length和block_length参数控制生成元素的顺序,cycle_length控制并发处理的输入元素的数量,如果将cycle_length设置为1,则此转换将一次处理一个输入元素,并将产生与tf.data.dataset.flat_map相同的结果。 通常,此转换将应用map_func到cycle_length输入元素,在返回的数据集对象上打开迭代器,并循环遍历它们,从每个迭代器生成block_length个连续元素,并在每次到达迭代器末尾时使用下一个输入元素。

case:

a = Dataset.range(1, 6)  # ==> [ 1, 2, 3, 4, 5 ]

# NOTE: New lines indicate "block" boundaries.
a.interleave(lambda x: Dataset.from_tensors(x).repeat(6),
            cycle_length=2, block_length=4)  # ==> [1, 1, 1, 1,
                                             #      2, 2, 2, 2,
                                             #      1, 1,
                                             #      2, 2,
                                             #      3, 3, 3, 3,
                                             #      4, 4, 4, 4,
                                             #      3, 3,
                                             #      4, 4,
                                             #      5, 5, 5, 5,
                                             #      5, 5]

注意:只要map_func是纯函数,则此转换产生的元素顺序是确定的。 如果map_func包含任何有状态操作,则访问该状态的顺序是未定义的。

参数:

map_func:将数据集元素映射到数据集的函数。
cycle_length:(可选) 将并发处理的输入元素数。 如果未指定,则该值将从可用的CPU内核数中得出。 如果将num_parallel_calls参数设置为tf.data.experimental.AUTOTUNE,则cycle_length参数将标识最大并行度。
block_length:(可选) 在循环到另一个输入元素之前,从每个输入元素产生的连续元素数量。
num_parallel_calls:(可选) 如果指定,该实现将创建一个线程池,用于异步和并行地从循环元素中获取输入。 默认行为是从循环元素中同步获取输入,而不具有并行性。 如果使用值tf.data.experimental.AUTOTUNE ,则根据可用CPU动态设置并行调用的数量。

返回:

Dataset: 一个数据集

示例:

dataset = tf.data.Dataset.from_tensor_slices(np.arange(10))
dataset = dataset.repeat(3).batch(7)

dataset2 = dataset.interleave(
    lambda v: tf.data.Dataset.from_tensor_slices(v), # 1、map_fn:做什么样的变换
    cycle_length = 5, #/ 2、cycle_length:并行程度:并行处理dataset中的多少个元素
    block_length = 5, #/ 3、block_length:从map_fn变换的结果中每次取多少元素:达到一个均匀混合效果
)
for item in dataset2:
    print(item)
tf.Tensor(0, shape=(), dtype=int32)
tf.Tensor(1, shape=(), dtype=int32)
tf.Tensor(2, shape=(), dtype=int32)
tf.Tensor(3, shape=(), dtype=int32)
tf.Tensor(4, shape=(), dtype=int32)
tf.Tensor(7, shape=(), dtype=int32)
tf.Tensor(8, shape=(), dtype=int32)
tf.Tensor(9, shape=(), dtype=int32)
tf.Tensor(0, shape=(), dtype=int32)
tf.Tensor(1, shape=(), dtype=int32)
tf.Tensor(4, shape=(), dtype=int32)
tf.Tensor(5, shape=(), dtype=int32)
tf.Tensor(6, shape=(), dtype=int32)
tf.Tensor(7, shape=(), dtype=int32)
tf.Tensor(8, shape=(), dtype=int32)
tf.Tensor(1, shape=(), dtype=int32)
tf.Tensor(2, shape=(), dtype=int32)
tf.Tensor(3, shape=(), dtype=int32)
tf.Tensor(4, shape=(), dtype=int32)
tf.Tensor(5, shape=(), dtype=int32)
tf.Tensor(8, shape=(), dtype=int32)
tf.Tensor(9, shape=(), dtype=int32)
tf.Tensor(5, shape=(), dtype=int32)
tf.Tensor(6, shape=(), dtype=int32)
tf.Tensor(2, shape=(), dtype=int32)
tf.Tensor(3, shape=(), dtype=int32)
tf.Tensor(9, shape=(), dtype=int32)
tf.Tensor(0, shape=(), dtype=int32)
tf.Tensor(6, shape=(), dtype=int32)
tf.Tensor(7, shape=(), dtype=int32)

3、Interleave与map的差别:

它们的差别在于,interleave是把原来dataset里的每个元素都生成一个新的dataset,然后再把生成的新dataset合并起来。

而map则是把原来dataset中的每个元素做一次变换,得到一个新的dataset。

区别则是原来的dataset中的每个元素会不会生成一个新的dataset。

 

  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值