【问题标题】:How to use parallel_interleave in TensorFlow如何在 TensorFlow 中使用 parallel_interleave
【发布时间】:2018-04-26 15:12:34
【问题描述】:

我正在阅读 TensorFlow benchmarks repo 中的代码。以下代码是从 TFRecord 文件创建 TensorFlow 数据集的部分:

ds = tf.data.TFRecordDataset.list_files(tfrecord_file_names)
ds = ds.apply(interleave_ops.parallel_interleave(tf.data.TFRecordDataset, cycle_length=10))

我正在尝试更改此代码以直接从 JPEG 图像文件创建数据集:

ds = tf.data.Dataset.from_tensor_slices(jpeg_file_names)
ds = ds.apply(interleave_ops.parallel_interleave(?, cycle_length=10))

我不知道该写什么?地方。 parallel_interleave() 中的 map_func 是 TFRecord 文件的 tf.data.TFRecordDataset 类的 __init__(),但我不知道为 JPEG 文件写什么。

我们不需要在这里做任何转换。因为我们将压缩两个数据集,然后再进行转换。代码如下:

counter = tf.data.Dataset.range(batch_size)
ds = tf.data.Dataset.zip((ds, counter))
ds = ds.apply( \
     batching.map_and_batch( \
     map_func=preprocess_fn, \
     batch_size=batch_size, \
     num_parallel_batches=num_splits))

因为我们不需要在 ?地方,我尝试使用一个空的map_func,但是出现错误“map_funcmust return aDataset`对象”。我也尝试使用 tf.data.Dataset,但输出显示 Dataset 是一个抽象类,不允许放在那里。

有人可以帮忙吗?非常感谢。

【问题讨论】:

  • 一开始为什么要使用parallel_interleave?当您想要读取从磁盘或网络中检索数据并且速度可能很慢的多个数据集时,它很有用。在你的情况下,听起来你不需要那个。如果是这样,当您跳过这一步时,确切的问题是什么?

标签: python tensorflow


【解决方案1】:

parallel_interleave 在您有将 source 数据集的每个元素转换为 destination 数据集的多个元素的转换时很有用。我不确定他们为什么在基准存储库中这样使用它,而他们本可以将 map 与并行调用一起使用。

以下是我建议使用parallel_interleave 从多个目录读取图像的方法,每个目录包含一个类:

classes = sorted(glob(directory + '/*/')) # final slash selects directories only
num_classes = len(classes)

labels = np.arange(num_classes, dtype=np.int32)

dirs = DS.from_tensor_slices((classes, labels))               # 1
files = dirs.apply(tf.contrib.data.parallel_interleave(
    get_files, cycle_length=num_classes, block_length=4,      # 2
    sloppy=False)) # False is important ! Otherwise it mixes labels
files = files.cache()
imgs = files.map(read_decode, num_parallel_calls=20)\.        # 3
            .apply(tf.contrib.data.shuffle_and_repeat(100))\
            .batch(batch_size)\
            .prefetch(5)

分为三个步骤。首先,我们获取目录列表及其标签 (#1)。

然后,我们将这些映射到文件数据集。但是如果我们做一个简单的.flatmap(),我们最终会得到标签0的所有文件,然后是标签1的所有文件,然后是2等等......然后我们需要非常大洗牌缓冲区以获得有意义的洗牌。

因此,我们改为应用 parallel_interleave (#2)。这是get_files()

def get_files(dir_path, label):
    globbed = tf.string_join([dir_path, '*.jpg'])
    files = tf.matching_files(globbed)

    num_files = tf.shape(files)[0] # in the directory
    labels = tf.tile([label], [num_files, ]) # expand label to all files
    return DS.from_tensor_slices((files, labels))

使用parallel_interleave 可确保每个目录的list_files 并行运行,因此当第一个目录中的第一个block_length 文件被列出时,第二个目录中的第一个block_length 文件也将是可用(也来自第 3、第 4 等)。此外,生成的数据集将包含每个标签的交错块,例如1 1 1 1 2 2 2 2 3 3 3 3 3 1 1 1 1 ...(3 个班级和block_length=4

最后,我们从文件列表 (#3) 中读取图像。这里是read_and_decode()

def read_decode(path, label):
    img = tf.image.decode_image(tf.read_file(path), channels=3)
    img = tf.image.resize_bilinear(tf.expand_dims(img, axis=0), target_size)
    img = tf.squeeze(img, 0)
    img = preprocess_fct(img) # should work with Tensors !

    label = tf.one_hot(label, num_classes)
    img = tf.Print(img, [path, label], 'Read_decode')
    return (img, label)

这个函数接受一个图像路径及其标签,并为每个返回一个张量:路径的图像张量和标签的 one_hot 编码。这也是您可以对图像进行所有转换的地方。在这里,我进行大小调整和基本预处理。

【讨论】:

    猜你喜欢
    • 2019-07-15
    • 1970-01-01
    • 2018-10-22
    • 2017-03-26
    • 2019-02-20
    • 2017-01-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多