Dataset.from_tensors 和 Dataset.from_tensor_slices 有什么区别?
What is the difference between Dataset.from_tensors and Dataset.from_tensor_slices?
我有一个表示为形状 (num_features, num_examples)
的 NumPy 矩阵的数据集,我希望将其转换为 TensorFlow 类型 tf.Dataset
。
我正在努力理解这两种方法之间的区别:Dataset.from_tensors
和 Dataset.from_tensor_slices
。什么是正确的,为什么?
TensorFlow 文档 (link) 说这两种方法都接受张量的嵌套结构,尽管在使用 from_tensor_slices
时张量在第 0 维的大小应该相同。
from_tensors
将输入和 returns 数据集与单个元素组合:
>>> t = tf.constant([[1, 2], [3, 4]])
>>> ds = tf.data.Dataset.from_tensors(t)
>>> [x for x in ds]
[<tf.Tensor: shape=(2, 2), dtype=int32, numpy=
array([[1, 2],
[3, 4]], dtype=int32)>]
from_tensor_slices
为输入张量的每一行创建一个具有单独元素的数据集:
>>> t = tf.constant([[1, 2], [3, 4]])
>>> ds = tf.data.Dataset.from_tensor_slices(t)
>>> [x for x in ds]
[<tf.Tensor: shape=(2,), dtype=int32, numpy=array([1, 2], dtype=int32)>,
<tf.Tensor: shape=(2,), dtype=int32, numpy=array([3, 4], dtype=int32)>]
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, first dimension is same
dataset2 = tf.data.Dataset.from_tensors(
(tf.random_uniform([10, 4]), tf.random_uniform([10])))
2) here 解释的第二个区别是 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)
在上面,from_tensors
创建一个 3D 张量,而 from_tensor_slices
合并输入张量。如果您有不同图像通道的不同来源并希望将它们连接成一个 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])
输出:
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,)))
试试这个:
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)
输出:
========= 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)
输出几乎是不言自明的,但如您所见,from_tensor_slices() 在其第一个维度上对 from_tensors() 的输出(输出是什么)进行切片。您也可以尝试使用 :
t1 = tf.constant([[[11, 22], [33, 44], [55, 66]],
[[110, 220], [330, 440], [550, 660]]])
我认为@MatthewScarpino 清楚地解释了这两种方法之间的区别。
这里我试着描述一下这两种方法的典型用法:
from_tensors
可用于从几个小数据集构建更大的数据集,即数据集的大小(长度)变大;
而from_tensor_slices
可用于将不同的元素组合到一个数据集中,例如,将特征和标签组合到一个数据集中(这也是张量的第一维应该相同的原因).即数据集变为"wider".
简单来说:
from_tensors()
returns:单元素,
类型:TensorDataset
from_tensor_slices()
returns:输入长度的多个元素,
类型:TensorSliceDataset
解释:
from_tensors()
With 1-D input
import tensorflow as tf
dataset_ft = tf.data.Dataset.from_tensors([1, 2, 3])
type(dataset_ft)
>>> tensorflow.python.data.ops.dataset_ops.TensorDataset
现在,如果我们遍历这个数据集,我们只会得到一个对象:
for _ in dataset_ft:
print(_)
>>> tf.Tensor([1 2 3], shape=(3,), dtype=int32)
如果我们提供二维或更多维度的输入会怎样?
With 2-D input
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
现在,如果我们遍历这个数据集,我们仍然只会得到一个对象:
for _ in dataset_ft:
print(_)
>>> tf.Tensor(
>>> [[1 2 3]
>>> [4 5 6]], shape=(2, 3), dtype=int32)
如您所见,形状或生成的张量是输入时的。形状没有变化。
from_tensor_slices()
它删除第一个维度并将其用作数据集维度。
With 1-D input
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
现在,如果我们遍历这个数据集,我们将有多个对象:
for _ in dataset_fts:
print(_)
>>> tf.Tensor(1, shape=(), dtype=int32)
>>> tf.Tensor(2, shape=(), dtype=int32)
>>> tf.Tensor(3, shape=(), dtype=int32)
如果我们提供二维或更多维度的输入会怎样?
With 2-D input
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
如果我们遍历这个二维数据集,我们将有两个一维元素:
for _ in dataset_fts:
print(_)
>>> tf.Tensor([1 2 3], shape=(3,), dtype=int32)
>>> tf.Tensor([4 5 6], shape=(3,), dtype=int32)
这是我能解释的最简单的了。为了更好地理解,我建议您 运行 这两个具有不同输入的函数,并查看返回元素的形状。
我有一个表示为形状 (num_features, num_examples)
的 NumPy 矩阵的数据集,我希望将其转换为 TensorFlow 类型 tf.Dataset
。
我正在努力理解这两种方法之间的区别:Dataset.from_tensors
和 Dataset.from_tensor_slices
。什么是正确的,为什么?
TensorFlow 文档 (link) 说这两种方法都接受张量的嵌套结构,尽管在使用 from_tensor_slices
时张量在第 0 维的大小应该相同。
from_tensors
将输入和 returns 数据集与单个元素组合:
>>> t = tf.constant([[1, 2], [3, 4]])
>>> ds = tf.data.Dataset.from_tensors(t)
>>> [x for x in ds]
[<tf.Tensor: shape=(2, 2), dtype=int32, numpy=
array([[1, 2],
[3, 4]], dtype=int32)>]
from_tensor_slices
为输入张量的每一行创建一个具有单独元素的数据集:
>>> t = tf.constant([[1, 2], [3, 4]])
>>> ds = tf.data.Dataset.from_tensor_slices(t)
>>> [x for x in ds]
[<tf.Tensor: shape=(2,), dtype=int32, numpy=array([1, 2], dtype=int32)>,
<tf.Tensor: shape=(2,), dtype=int32, numpy=array([3, 4], dtype=int32)>]
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, first dimension is same
dataset2 = tf.data.Dataset.from_tensors(
(tf.random_uniform([10, 4]), tf.random_uniform([10])))
2) here 解释的第二个区别是 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)
在上面,from_tensors
创建一个 3D 张量,而 from_tensor_slices
合并输入张量。如果您有不同图像通道的不同来源并希望将它们连接成一个 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])
输出:
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,)))
试试这个:
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)
输出:
========= 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)
输出几乎是不言自明的,但如您所见,from_tensor_slices() 在其第一个维度上对 from_tensors() 的输出(输出是什么)进行切片。您也可以尝试使用 :
t1 = tf.constant([[[11, 22], [33, 44], [55, 66]],
[[110, 220], [330, 440], [550, 660]]])
我认为@MatthewScarpino 清楚地解释了这两种方法之间的区别。
这里我试着描述一下这两种方法的典型用法:
from_tensors
可用于从几个小数据集构建更大的数据集,即数据集的大小(长度)变大;而
from_tensor_slices
可用于将不同的元素组合到一个数据集中,例如,将特征和标签组合到一个数据集中(这也是张量的第一维应该相同的原因).即数据集变为"wider".
简单来说:
from_tensors()
returns:单元素,
类型:TensorDataset
from_tensor_slices()
returns:输入长度的多个元素,
类型:TensorSliceDataset
解释:
from_tensors()
With 1-D input
import tensorflow as tf
dataset_ft = tf.data.Dataset.from_tensors([1, 2, 3])
type(dataset_ft)
>>> tensorflow.python.data.ops.dataset_ops.TensorDataset
现在,如果我们遍历这个数据集,我们只会得到一个对象:
for _ in dataset_ft:
print(_)
>>> tf.Tensor([1 2 3], shape=(3,), dtype=int32)
如果我们提供二维或更多维度的输入会怎样?
With 2-D input
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
现在,如果我们遍历这个数据集,我们仍然只会得到一个对象:
for _ in dataset_ft:
print(_)
>>> tf.Tensor(
>>> [[1 2 3]
>>> [4 5 6]], shape=(2, 3), dtype=int32)
如您所见,形状或生成的张量是输入时的。形状没有变化。
from_tensor_slices()
它删除第一个维度并将其用作数据集维度。
With 1-D input
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
现在,如果我们遍历这个数据集,我们将有多个对象:
for _ in dataset_fts:
print(_)
>>> tf.Tensor(1, shape=(), dtype=int32)
>>> tf.Tensor(2, shape=(), dtype=int32)
>>> tf.Tensor(3, shape=(), dtype=int32)
如果我们提供二维或更多维度的输入会怎样?
With 2-D input
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
如果我们遍历这个二维数据集,我们将有两个一维元素:
for _ in dataset_fts:
print(_)
>>> tf.Tensor([1 2 3], shape=(3,), dtype=int32)
>>> tf.Tensor([4 5 6], shape=(3,), dtype=int32)
这是我能解释的最简单的了。为了更好地理解,我建议您 运行 这两个具有不同输入的函数,并查看返回元素的形状。