【问题标题】:How to make tf.data.Dataset return all of the elements in one call?如何让 tf.data.Dataset 在一次调用中返回所有元素?
【发布时间】:2018-06-16 00:55:27
【问题描述】:

有没有一种简单的方法来获取tf.data.Dataset 中的整个元素集?即我想将数据集的批量大小设置为我的数据集的大小,而无需专门传递元素的数量。这对于我想一次性测量整个数据集的准确性的验证数据集很有用。我很惊讶没有一种方法可以获取 tf.data.Dataset 的大小

【问题讨论】:

  • 您也可以使用tf.metrics.accuracy 并在每批验证数据上运行sess.run(update_op)。最后,致电sess.run(accuracy) 应该可以为您提供总体准确度。
  • 我确信使用 tensorflow API 和估算器是在浪费时间。我花了很多时间学习它们,然后你面临一个又一个的限制,就像你提到的那样。我只会创建自己的数据集和批处理生成器。

标签: tensorflow tensorflow-datasets


【解决方案1】:

TensorFlow 的 get_single_element() 最终是 around,它正是这样做的 - 在一次调用中返回所有元素。

这避免了使用.map() 或iter() 生成和使用迭代器的需要(这对于大型数据集可能成本很高)。

get_single_element() 返回一个封装数据集所有成员的张量(或张量的元组或字典)。我们需要将数据集的所有成员批量传递到一个元素中。

这可用于获取特征作为张量数组,或特征和标签作为元组或字典(张量数组),具体取决于原始数据集的创建方式。

查看 SO 上的 answer 以获取将特征和标签解包到张量数组元组中的示例。

【讨论】:

    【解决方案2】:

    补充约翰的回答:

    total = []
    for element in val_ds.as_numpy_iterator(): 
      total.append(element[1])
    
    all_total = np.concatenate(total)
    print(all_total)
    

    【讨论】:

      【解决方案3】:

      在 Tensorflow 2.0

      中

      您可以使用as_numpy_iterator枚举数据集

      for element in Xtrain.as_numpy_iterator(): 
        print(element) 
      

      【讨论】:

        【解决方案4】:

        tf.data API 创建一个名为'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
        

        【讨论】:

          【解决方案5】:

          不确定这在最新版本的 TensorFlow 中是否仍然有效,但如果这是绝对需要的,一个 hacky 解决方案是创建一个大于数据集大小的批次。您不需要知道数据集有多大,只需请求更大的批大小即可。

          【讨论】:

          • Tensorflow 2.5.0 中丑陋但仍然有效的解决方案
          【解决方案6】:

          简而言之,没有一个很好的方法来获取尺寸/长度; tf.data.Dataset 是为数据管道构建的,因此有一个迭代器结构(在我的理解和我对the Dataset ops code 的阅读中。来自programmer's guide:

          tf.data.Iterator 提供了从数据集中提取元素的主要方法。 Iterator.get_next() 返回的操作在执行时会产生 Dataset 的下一个元素,通常充当输入管道代码和模型之间的接口。

          而且,就其本质而言,迭代器没有方便的大小/长度概念;看这里:Getting number of elements in an iterator in Python

          更一般地说,为什么会出现这个问题?如果你调用batch,你也会得到一个tf.data.Dataset,所以无论你在批处理上运行什么,你都应该能够在整个数据集上运行;它将遍历所有元素并计算验证准确性。换句话说,我认为您实际上并不需要尺寸/长度来做您想做的事情。

          【讨论】:

          • 我的代码接受训练和验证 tfrecords 文件,并将它们转换为两个 tf.Datasets,其中有一个迭代器可以初始化为两个数据集(类似于 TF 文档中的examples)。训练数据的时期数和批量大小在我的控制范围内,我可以轻松地在训练数据集上应用 .batch() 和 .repeat() 方法。但是,对于验证数据,我想创建一个包含所有样本的批次,但我不一定知道 tfrecord 文件中有多少样本。
          • 我明白了;感谢您的解释。我想说的是,当您运行“.batch()”时,它会返回一个与数据集类型相同的对象。因此,无论您在批处理上调用什么,您都应该能够调用数据集本身(只是无需调用批处理)。
          猜你喜欢
          • 1970-01-01
          • 2016-06-28
          • 2021-12-22
          • 1970-01-01
          • 1970-01-01
          • 2011-04-11
          • 1970-01-01
          • 2020-01-15
          • 1970-01-01
          相关资源
          最近更新 更多