Tensorflow 数据集 API:映射函数为每个输入生成多个输出

Tensorflow Dataset API: map function producing multiple outputs per one input

TL;DR:我的 input_fn 一步从 1 生成 7 张图像。我想单独使用它们中的每一张(1x1000x1000x3 7 次)而不是作为单个图像 (7x1000x1000x3),至于能够将它们洗牌并在多个批次中混合。

我的数据、图像非常大:5000x9000x3 特征和 5000x9000x1 标签,所以我将它们存储为 JPEG 并将压缩图像提供给 input_fngen_fn 解压缩它们并 parser_fn 输出 7x1000x1000x3 & 7x1000x1000x1 (7 个随机作物,始终作为嵌套元组)。现在的问题是,我不希望我的输入是那些 7 图像,而是将 7 作为 "the batch size"。我的尝试如下:

# Where `gen_fn` outputs JPEG encoded strings (bytes in python)
dataset = tf.dataset.Dataset.from_generator(gen_fn, (tf.string, 
tf.string))
print(dataset) # debug, shown below

# Produces ([7, 1000, 1000, 3], [7, 1000, 1000, 1])
dataset = dataset.map(lambda features, labels: parser_fn)
print(dataset) # debug, shown below

# Attempts to flatten out the 0th dimension
# Effectively produces ([1000, 1000, 3], [1000, 1000, 1])
dataset = dataset.flat_map(lambda x,y: tf.dataset.Dataset.from_tensor_slices((x, y))
print(dataset) # debug, shown below

# Shuffle all of them to avoid biasing the network
# dataset = dataset.shuffle(63) # 9*7

# Prefetch, repeat (does not have any effect, tested)
dataset = dataset.prefetch(1)
print(dataset) # debug, shown below
dataset = dataset.repeat(1)
print(dataset) # debug, shown below

# Batch
dataset = dataset.batch(1)
print(dataset) # debug, shown below

itr = dataset.make_one_shot_iterator()
features, labels = itr.get_next()
return features, labels

打印到控制台

<FlatMapDataset shapes: (<unknown>, <unknown>), types: (tf.string, tf.string)>
<MapDataset shapes: ((7, 1000, 1000, 3), (7, 1000, 1000, 1)), types: (tf.float32, tf.float32)>
<FlatMapDataset shapes: ((1000, 1000, 3), (1000, 1000, 1)), types: (tf.float32, tf.float32)>
<PrefetchDataset shapes: ((1000, 1000, 3), (1000, 1000, 1)), types: (tf.float32, tf.float32)>
<RepeatDataset shapes: ((1000, 1000, 3), (1000, 1000, 1)), types: (tf.float32, tf.float32)>
<BatchDataset shapes: ((?, 1000, 1000, 3), (?, 1000, 1000, 1)), types: (tf.float32, tf.float32)>

它加载正常,但一旦开始训练我得到 TypeError: If shallow structure is a sequence, input must also be a sequence. Input has type: <class 'list'>. 完全删除 batch 调用工作正常并输出 1000x1000x3 "batches".

按照 中的建议,我尝试使用 padded_batch 而不是 batch 作为:

dataset = dataset.padded_batch(self.__batch_size, dataset.output_shapes)

导致

<PaddedBatchDataset shapes: ((?, 1000, 1000, 3), (?, 1000, 1000, 1)), types: (tf.float32, tf.float32)>

但遗憾的是得到了同样的结果。

一个 github 问题 https://github.com/tensorflow/tensorflow/issues/14451 建议多次重复初始图像。但这要么意味着多次解压缩同一图像(节省内存,速度慢得多),要么重复多次全分辨率图像(每次重复意味着 400MB)。

图像是我架构中的一个瓶颈,我可以预处理所有作物,但这将意味着失去一些潜在的随机作物和数据增强。重复不是一个选项(time/memory 约束)并且我无法使该代码工作,知道可能是什么问题吗?

事实证明,这段代码运行良好,并将最初的 7 个随机裁剪结果展平。

错误,而不是上面片段中的 shown/included,而是来自我的生成器,它生成了一个列表而不是一个元组。为了让 Tensorflow 正确理解生成器正在产生 2 个值(特征, 标签),它必须 return 一个 tuple,但我的错误地产生了一个 list,以有效地告诉 Tensorflow 只有 1 个值。

主要的挫折是错误是在运行时抛出的,而不是在构建图形时抛出的,因此调试它变得相当困难并且主要由反复试验组成。