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

时间:2018-01-22 19:47:03

标签: tensorflow tensorflow-datasets

TL; DR:我的input_fn一步生成7张图片。我想单独使用它们(1x1000x1000x3 7次)而不是单张图像(7x1000x1000x3),以便能够将它们混合并在多批次之间混合。

我的数据,图片非常大:5000x9000x3个功能和5000x9000x1标签,因此我将它们存储为JPEG并将压缩的图像提供给input_fngen_fn解压缩他们和parser_fn输出7x1000x1000x3& 7x1000x1000x1(7种随机作物,总是作为嵌套元组)。现在的问题是,我不希望我的输入是那些7图像,而是将7作为“批量大小”。我的尝试如下:

# 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“批次”。

根据How do I create padded batches in Tensorflow for tf.train.SequenceExample data using the DataSet API?的建议,我尝试使用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)。

图像是我的架构中的瓶颈,我可以对所有作物进行预处理,但这意味着会丢失一些潜在的随机作物和数据增加。重复不是一个选项(时间/内存限制),我不能让代码工作,任何想法可能是错的?

1 个答案:

答案 0 :(得分:2)

事实证明,此代码可以完美地工作,并使最初的7个随机作物变平。

错误,未显示/包含在上面的剪辑中,而是来自我的生成器,它产生了一个列表而不是一个元组。为了让Tensorflow正确理解发生器正在产生2个值(特征,  标签),它必须返回一个tuple,但是我错误地产生list,以便有效地告诉Tensorflow只有一个值。

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