`Dataset.from_tensors`和`Dataset.from_tensor_slices`之间的区别?

Lle*_*lyn 32 python tensorflow tensorflow-datasets

我有一个数据集表示为NumPy形状矩阵,(num_features, num_examples)我希望将其转换为TensorFlow类型tf.Dataset.

我正在努力去理解这两种方法之间的区别:Dataset.from_tensorsDataset.from_tensor_slices.什么是正确的,为什么?

TensorFlow文档(链接)表示两种方法都接受张量的嵌套结构,尽管使用from_tensor_slices张量时在第0维应该具有相同的大小.

Mat*_*ino 46

from_tensors 组合输入并将数据集与单个元素一起返回:

t = tf.constant([[1, 2], [3, 4]])
ds = tf.data.Dataset.from_tensors(t)   # [[1, 2], [3, 4]]
Run Code Online (Sandbox Code Playgroud)

from_tensor_slices 为输入张量的每一行创建一个带有单独元素的数据集:

t = tf.constant([[1, 2], [3, 4]])
ds = tf.data.Dataset.from_tensor_slices(t)   # [1, 2], [3, 4]
Run Code Online (Sandbox Code Playgroud)

  • @MathewScarpino:你能详细说明何时何时使用? (18认同)
  • 我认为混乱的根源(至少是这样)是名字。由于 from_tensor_slices 从原始数据创建切片...理想的名称应该是“to_tensor_slices” - 因为您正在获取数据并从中创建张量切片。一旦你按照这些思路思考,TF2 的所有文档对我来说就变得非常清晰了! (5认同)
  • 对我来说,文档中缺少的一个关键信息是多个张量作为元组传递给这些方法,例如“from_tensors((t1,t2,t3,))”。有了这些知识,“from_tensors”创建了一个数据集,其中每个输入张量就像数据集的“行”,而“from_tensor_slices”创建了一个数据集,其中每个输入张量都是数据的“列”;因此在后一种情况下,所有张量必须具有相同的长度,并且结果数据集的元素(行)是每列具有一个元素的元组。 (2认同)

小智 10

我认为@MatthewScarpino 清楚地解释了这两种方法之间的差异。

下面我试着描述一下这两种方法的典型用法:

  • from_tensors 可以用来从几个小数据集构造一个更大的数据集,即数据集的大小(长度)变大;

  • whilefrom_tensor_slices可用于将不同元素组合成一个数据集,例如,将特征和标签组合成一个数据集(这也是张量的第一维应该相同的原因)。也就是说,数据集变得“更宽”。


Ami*_*mir 9

1)两者之间的主要区别在于,嵌套元素的from_tensor_slices第0级必须具有相同的尺寸:

# exception: ValueError: Dimensions 10 and 9 are not compatible
dataset1 = tf.data.Dataset.from_tensor_slices(
    (tf.random_uniform([10, 4]), tf.random_uniform([9])))
# OK
dataset2 = tf.data.Dataset.from_tensors(
    (tf.random_uniform([10, 4]), tf.random_uniform([9])))
Run Code Online (Sandbox Code Playgroud)

2)第二个区别(这里解释)是tf.Dataset的输入是列表时。例如:

dataset1 = tf.data.Dataset.from_tensor_slices(
    [tf.random_uniform([2, 3]), tf.random_uniform([2, 3])])

dataset2 = tf.data.Dataset.from_tensors(
    [tf.random_uniform([2, 3]), tf.random_uniform([2, 3])])

print(dataset1) # shapes: (2, 3)
print(dataset2) # shapes: (2, 2, 3)
Run Code Online (Sandbox Code Playgroud)

在上面,from_tensorsfrom_tensor_slices合并输入张量的同时创建3D张量。如果您具有不同图像通道的不同来源,并希望将它们串联为一个RGB图像张量,则此方法很方便。

3)在上一个答案中提到的A,from_tensors将输入张量转换为一个大张量:

import tensorflow as tf

tf.enable_eager_execution()

dataset1 = tf.data.Dataset.from_tensor_slices(
    (tf.random_uniform([4, 2]), tf.random_uniform([4])))

dataset2 = tf.data.Dataset.from_tensors(
    (tf.random_uniform([4, 2]), tf.random_uniform([4])))

for i, item in enumerate(dataset1):
    print('element: ' + str(i + 1), item[0], item[1])

print(30*'-')

for i, item in enumerate(dataset2):
    print('element: ' + str(i + 1), item[0], item[1])
Run Code Online (Sandbox Code Playgroud)

输出:

element: 1 tf.Tensor(... shapes: ((2,), ()))
element: 2 tf.Tensor(... shapes: ((2,), ()))
element: 3 tf.Tensor(... shapes: ((2,), ()))
element: 4 tf.Tensor(... shapes: ((2,), ()))
-------------------------
element: 1 tf.Tensor(... shapes: ((4, 2), (4,)))
Run Code Online (Sandbox Code Playgroud)


u2g*_*les 6

尝试这个 :

import tensorflow as tf  # 1.13.1
tf.enable_eager_execution()

t1 = tf.constant([[11, 22], [33, 44], [55, 66]])

print("\n=========     from_tensors     ===========")
ds = tf.data.Dataset.from_tensors(t1)
print(ds.output_types, end=' : ')
print(ds.output_shapes)
for e in ds:
    print (e)

print("\n=========   from_tensor_slices    ===========")
ds = tf.data.Dataset.from_tensor_slices(t1)
print(ds.output_types, end=' : ')
print(ds.output_shapes)
for e in ds:
    print (e)
Run Code Online (Sandbox Code Playgroud)

输出:

=========      from_tensors    ===========
<dtype: 'int32'> : (3, 2)
tf.Tensor(
[[11 22]
 [33 44]
 [55 66]], shape=(3, 2), dtype=int32)

=========   from_tensor_slices      ===========
<dtype: 'int32'> : (2,)
tf.Tensor([11 22], shape=(2,), dtype=int32)
tf.Tensor([33 44], shape=(2,), dtype=int32)
tf.Tensor([55 66], shape=(2,), dtype=int32)
Run Code Online (Sandbox Code Playgroud)

输出几乎是不言自明的,但是如您所见,from_tensor_slices()在其第一维上对from_tensors()的输出(将是其输出)进行切片。您也可以尝试:

t1 = tf.constant([[[11, 22], [33, 44], [55, 66]],
                  [[110, 220], [330, 440], [550, 660]]])
Run Code Online (Sandbox Code Playgroud)


小智 5

简单来说:

from_tensors()

返回:单个元素,
类型:TensorDataset

from_tensor_slices()

返回:输入长度的多个元素
, 类型:TensorSliceDataset

解释:

from_tensors()

带一维输入

import tensorflow as tf
dataset_ft = tf.data.Dataset.from_tensors([1, 2, 3])
type(dataset_ft)

>>> tensorflow.python.data.ops.dataset_ops.TensorDataset
Run Code Online (Sandbox Code Playgroud)

现在,如果我们循环遍历这个数据集,我们只会得到一个对象:

for _ in dataset_ft:
    print(_)  

>>> tf.Tensor([1 2 3], shape=(3,), dtype=int32)
Run Code Online (Sandbox Code Playgroud)

如果我们提供二维或更多维输入怎么办?

带二维输入

import tensorflow as tf
dataset_ft = tf.data.Dataset.from_tensors([[1, 2, 3], [4, 5, 6]])
type(dataset_ft)

>>> tensorflow.python.data.ops.dataset_ops.TensorDataset
Run Code Online (Sandbox Code Playgroud)

现在,如果我们循环遍历这个数据集,我们仍然只能得到一个对象:

for _ in dataset_ft:
    print(_)

>>> tf.Tensor(
>>> [[1 2 3]
>>> [4 5 6]], shape=(2, 3), dtype=int32)
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,形状或生成的张量是输入时的。形状没有变化。

from_tensor_slices()

它删除第一个维度并将其用作数据集维度。

带一维输入

import tensorflow as tf
dataset_fts = tf.data.Dataset.from_tensor_slices([1, 2, 3])
type(dataset_fts)

>>> tensorflow.python.data.ops.dataset_ops.TensorSliceDataset
Run Code Online (Sandbox Code Playgroud)

现在,如果我们循环这个数据集,我们将有多个对象:

for _ in dataset_fts:
    print(_)

>>> tf.Tensor(1, shape=(), dtype=int32)
>>> tf.Tensor(2, shape=(), dtype=int32)
>>> tf.Tensor(3, shape=(), dtype=int32)
Run Code Online (Sandbox Code Playgroud)

如果我们提供二维或更多维输入怎么办?

带二维输入

import tensorflow as tf
dataset_fts = tf.data.Dataset.from_tensor_slices([[1, 2, 3], [4, 5, 6]])
type(dataset_fts)

>>> tensorflow.python.data.ops.dataset_ops.TensorSliceDataset
Run Code Online (Sandbox Code Playgroud)

如果我们循环遍历这个二维数据集,我们将有两个一维元素:

for _ in dataset_fts:
    print(_)

>>> tf.Tensor([1 2 3], shape=(3,), dtype=int32)
>>> tf.Tensor([4 5 6], shape=(3,), dtype=int32)
Run Code Online (Sandbox Code Playgroud)

这是我能解释的最简单的。为了更好地理解,我建议您使用不同的输入运行这两个函数并查看返回元素的形状。