web-dev-qa-db-ja.com

tf.data.Datasetがすべての要素を1回の呼び出しで返すようにする方法は?

tf.data.Dataset内の要素のセット全体を取得する簡単な方法はありますか?つまり、データセットのバッチサイズを、要素数を明示的に渡さずにデータセットのサイズに設定したいと考えています。これは、データセット全体の精度を一度に測定したい検証データセットに役立ちます。 tf.data.Datasetのサイズを取得する方法がないことに驚いています

9
Milad

tf.data AP​​Iは、適切な接頭辞/接尾辞(該当する場合)を使用して、'tensors/component'というテンソルを作成します。インスタンスを作成した後。名前でテンソルを評価し、バッチサイズとして使用できます。

#Ignore the warnings
import warnings
warnings.filterwarnings("ignore")

import pandas as pd
import tensorflow as tf
import numpy as np

import matplotlib.pyplot as plt
plt.rcParams['figure.figsize'] = (8,7)
%matplotlib inline


from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("MNIST_data/")

Xtrain = mnist.train.images[mnist.train.labels < 2]
ytrain = mnist.train.labels[mnist.train.labels < 2]

print(Xtrain.shape)
#(11623, 784)
print(ytrain.shape)
#(11623,)  

#Data parameters
num_inputs = 28
num_classes = 2
num_steps=28

# create the training dataset
Xtrain = tf.data.Dataset.from_tensor_slices(Xtrain).map(lambda x: tf.reshape(x,(num_steps, num_inputs)))
# apply a one-hot transformation to each label for use in the neural network
ytrain = tf.data.Dataset.from_tensor_slices(ytrain).map(lambda z: tf.one_hot(z, num_classes))
# Zip the x and y training data together and batch and Prefetch data for faster consumption
train_dataset = tf.data.Dataset.Zip((Xtrain, ytrain)).batch(128).prefetch(128)

iterator = tf.data.Iterator.from_structure(train_dataset.output_types,train_dataset.output_shapes)
X, y = iterator.get_next()

training_init_op = iterator.make_initializer(train_dataset)

def get_tensors(graph=tf.get_default_graph()):
    return [t for op in graph.get_operations() for t in op.values()]

get_tensors()
#<tf.Tensor 'tensors_1/component_0:0' shape=(11623,) dtype=uint8>,
#<tf.Tensor 'batch_size:0' shape=() dtype=int64>,
#<tf.Tensor 'drop_remainder:0' shape=() dtype=bool>,
#<tf.Tensor 'buffer_size:0' shape=() dtype=int64>,
#<tf.Tensor 'IteratorV2:0' shape=() dtype=resource>,
#<tf.Tensor 'IteratorToStringHandle:0' shape=() dtype=string>,
#<tf.Tensor 'IteratorGetNext:0' shape=(?, 28, 28) dtype=float32>,
#<tf.Tensor 'IteratorGetNext:1' shape=(?, 2) dtype=float32>,
#<tf.Tensor 'TensorSliceDataset:0' shape=() dtype=variant>,
#<tf.Tensor 'MapDataset:0' shape=() dtype=variant>,
#<tf.Tensor 'TensorSliceDataset_1:0' shape=() dtype=variant>,
#<tf.Tensor 'MapDataset_1:0' shape=() dtype=variant>,
#<tf.Tensor 'ZipDataset:0' shape=() dtype=variant>,
#<tf.Tensor 'BatchDatasetV2:0' shape=() dtype=variant>,
#<tf.Tensor 'PrefetchDataset:0' shape=() dtype=variant>]

sess = tf.InteractiveSession()
print('Size of Xtrain: %d' % tf.get_default_graph().get_tensor_by_name('tensors/component_0:0').eval().shape[0])
#Size of Xtrain: 11623
2
ARAT

つまり、サイズ/長さを取得する良い方法はありません。 _tf.data.Dataset_はデータのパイプライン用に構築されているため、イテレーター構造を持っています(私の理解では、私の読んだ Dataset opsコード に従います。 プログラマーズガイド から) :

_tf.data.Iterator_は、データセットから要素を抽出する主な方法を提供します。 Iterator.get_next()によって返される操作は、実行時にデータセットの次の要素を生成し、通常、入力パイプラインコードとモデル間のインターフェースとして機能します。

そして、その性質上、反復子にはサイズ/長さという便利な概念がありません。ここを参照してください: Pythonのイテレータの要素数を取得する

より一般的には、なぜこの問題が発生するのですか? batchを呼び出すと、_tf.data.Dataset_も取得されるため、バッチで実行しているものはすべて、データセット全体で実行できるはずです。すべての要素を反復処理し、検証精度を計算します。言い換えれば、あなたがやりたいことをするのに実際にサイズ/長さが必要だとは思わない。

2
muskrat

Tensorflow 2.0

as_numpy_iterator を使用してデータセットを列挙できます

for element in Xtrain.as_numpy_iterator(): 
  print(element) 
0
John Doe

TensorFlowの最新バージョンでこれがまだ機能するかどうかはわかりませんが、これが絶対に必要な場合は、データセットのサイズよりも大きいバッチを作成するというハックなソリューションがあります。データセットの大きさを知る必要はありません。より大きなバッチサイズをリクエストするだけです。

0
Milad