web-dev-qa-db-ja.com

`Dataset.from_tensors`と` Dataset.from_tensor_slices`の違いは?

形状(num_features, num_examples)のNumPyマトリックスとして表されるデータセットがあり、それをTensorFlowタイプtf.Datasetに変換したい。

これら2つのメソッドDataset.from_tensorsDataset.from_tensor_slicesの違いを理解しようと努力しています。正しいものとその理由は何ですか?

TensorFlowのドキュメント( link )では、from_tensor_slicesを使用する場合、テンソルは0次元で同じサイズでなければなりませんが、両方のメソッドがテンソルのネストされた構造を受け入れます。

30
Llewlyn

from_tensorsは、入力を結合して、単一の要素を持つデータセットを返します。

t = tf.constant([[1, 2], [3, 4]])
ds = tf.data.Dataset.from_tensors(t)   # [[1, 2], [3, 4]]

from_tensor_slicesは、入力テンソルの各行に個別の要素を持つデータセットを作成します。

t = tf.constant([[1, 2], [3, 4]])
ds = tf.data.Dataset.from_tensor_slices(t)   # [1, 2], [3, 4]
43
MatthewScarpino

1)2つの主な違いは、 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])))

2) here で説明されている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)

上記では、from_tensorsは3Dテンソルを作成し、from_tensor_slices入力テンソルをマージします。これは、異なる画像チャネルの異なるソースがあり、それらを1つのRGB画像テンソルに連結する場合に便利です。

3)前の回答で言及したfrom_tensors入力テンソルを1つの大きなテンソルに変換します。

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,)))
7
Amir

これを試して :

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]]])
5
u2gilles