批量大小可变的TensorFlow DataSet from_generator

发布于 2021-01-29 16:22:01

我正在尝试使用TensorFlow Dataset
API通过该from_generator方法读取HDF5文件。除非批处理大小没有均匀地划分为事件数,否则一切都会正常进行。我不太了解如何使用API​​进行灵活的批处理。

如果事情没有平均分配,则会出现如下错误:

2018-08-31 13:47:34.274303: W tensorflow/core/framework/op_kernel.cc:1263] Invalid argument: ValueError: `generator` yielded an element of shape (1, 28, 28, 1) where an element of shape (11, 28, 28, 1) was expected.
Traceback (most recent call last):

  File "/Users/perdue/miniconda3/envs/py3a/lib/python3.6/site-packages/tensorflow/python/ops/script_ops.py", line 206, in __call__
    ret = func(*args)

  File "/Users/perdue/miniconda3/envs/py3a/lib/python3.6/site-packages/tensorflow/python/data/ops/dataset_ops.py", line 452, in generator_py_func
    "of shape %s was expected." % (ret_array.shape, expected_shape))

ValueError: `generator` yielded an element of shape (1, 28, 28, 1) where an element of shape (11, 28, 28, 1) was expected.

我有一个脚本可以在此处重现错误(以及获取若干MB所需数据文件的说明-Fashion MNIST):

https://gist.github.com/gnperdue/b905a9c2dd4c08b53e0539d6aa3d3dc6

最重要的代码可能是:

def make_fashion_dset(file_name, batch_size, shuffle=False):
    dgen = _make_fashion_generator_fn(file_name, batch_size)
    features_shape = [batch_size, 28, 28, 1]
    labels_shape = [batch_size, 10]
    ds = tf.data.Dataset.from_generator(
        dgen, (tf.float32, tf.uint8),
        (tf.TensorShape(features_shape), tf.TensorShape(labels_shape))
    )
    ...

其中dgen是发电机功能从HDF5读取:

def _make_fashion_generator_fn(file_name, batch_size):
    reader = FashionHDF5Reader(file_name)
    nevents = reader.openf()

    def example_generator_fn():
        start_idx, stop_idx = 0, batch_size
        while True:
            if start_idx >= nevents:
                reader.closef()
                return
            yield reader.get_examples(start_idx, stop_idx)
            start_idx, stop_idx = start_idx + batch_size, stop_idx + batch_size

    return example_generator_fn

问题的核心是我们必须在中声明张量形状from_generator,但是我们需要灵活地在迭代时沿线更改该形状。

有一些解决方法-删除最后几个样本以获得均等的划分,或者仅使用1的批处理大小…但是如果您不能丢失任何样本并且第一个批处理大小很慢,则第一个是不好的。

有什么想法或意见吗?谢谢!

关注者
0
被浏览
51
1 个回答
  • 面试哥
    面试哥 2021-01-29
    为面试而生,有面试问题,就找面试哥。

    在中指定张量形状时from_generator,您可以将其None用作元素来指定尺寸可变的尺寸。这样,您可以容纳不同大小的批次,尤其是“剩余”批次,它比您要求的批次大小小一些。所以你会用

    def make_fashion_dset(file_name, batch_size, shuffle=False):
        dgen = _make_fashion_generator_fn(file_name, batch_size)
        features_shape = [None, 28, 28, 1]
        labels_shape = [None, 10]
        ds = tf.data.Dataset.from_generator(
            dgen, (tf.float32, tf.uint8),
            (tf.TensorShape(features_shape), tf.TensorShape(labels_shape))
        )
        ...
    


知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看