使用tf.dataset.Dataset进行数据增强

6
为了使用Google Colabs TPUs我需要一个tf.dataset.Dataset。那么如何在这样的数据集上使用数据增强呢?
更具体地说,我的代码如下:
def get_dataset(batch_size=200):
  datasets, info = tfds.load(name='mnist', with_info=True, as_supervised=True,
                             try_gcs=True)
  mnist_train, mnist_test = datasets['train'], datasets['test']

  def scale(image, label):
    image = tf.cast(image, tf.float32)
    image /= 255.0

    label = tf.one_hot(label,10)

    return image, label

  train_dataset = mnist_train.map(scale).shuffle(10000).batch(batch_size)
  test_dataset = mnist_test.map(scale).batch(batch_size)

  return train_dataset, test_dataset

这会被输入到这个中:
# TPU Strategy ...
with strategy.scope():
  model = create_model()
  model.compile(loss="categorical_crossentropy",
                optimizer="adam",
                metrics=["acc"])

train_dataset, test_dataset = get_dataset()

model.fit(train_dataset,
          epochs=20,
          verbose=1,
          validation_data=test_dataset)

那么,我怎样才能在这里使用数据增强呢?据我所知,我不能使用tf.keras ImageDataGenerator,对吗? 我尝试了以下方法,但没有成功。
data_generator = ...

model.fit_generator(data_generator.flow(train_dataset, batch_size=32),
                    steps_per_epoch=len(train_dataset) / 32, epochs=20)

通常情况下,train_xtrain_y 会被作为两个参数传递给 flow 函数,而不是"打包"成一个tf.dataset.Dataset对象。

1个回答

8
您可以使用tf.image函数。 tf.image模块包含各种图像处理功能。
例如:
您可以在函数def get_dataset中添加以下功能。
  • 将每个图像转换为tf.float64,范围在0-1之间。
  • cache()结果,因为这些结果可以在每个repeat之后重新使用
  • 使用random_flip_left_right随机左右翻转每个图像。
  • 使用random_contrast随机更改图像的对比度。
  • 通过repeat使图像数量增加两倍,重复所有步骤。
代码 -
mnist_train = mnist_train.map(
    lambda image, label: (tf.image.convert_image_dtype(image, tf.float32), label)
).cache(
).map(
    lambda image, label: (tf.image.random_flip_left_right(image), label)
).map(
    lambda image, label: (tf.image.random_contrast(image, lower=0.0, upper=1.0), label)
).shuffle(
    1000
).
batch(
    batch_size
).repeat(2)

类似地,您可以使用其他功能,如random_flip_up_downrandom_crop函数,分别随机垂直(上下翻转)翻转图像和随机剪裁张量到给定大小。


您的get_dataset函数将如下所示 -

def get_dataset(batch_size=200):
  datasets, info = tfds.load(name='mnist', with_info=True, as_supervised=True,
                             try_gcs=True)
  mnist_train, mnist_test = datasets['train'], datasets['test']

  train_dataset = mnist_train.map(
               lambda image, label: (tf.image.convert_image_dtype(image, tf.float32),label)
              ).cache(
              ).map(
                    lambda image, label: (tf.image.random_flip_left_right(image), label)
              ).map(
                    lambda image, label: (tf.image.random_contrast(image, lower=0.0, upper=1.0), label)
              ).shuffle(
                    1000
              ).batch(
                    batch_size
              ).repeat(2)

  test_dataset = mnist_test.map(scale).batch(batch_size)

  return train_dataset, test_dataset

增加了由@Andrew H建议的链接,该链接提供了有关数据增强的端到端示例,同时还使用了mnist数据集。

希望这回答了你的问题。祝学习愉快。


虽然我个人认为大量的lambda表达式很难解析,但这是一个信息丰富的答案。每个映射都可以放入一个更大的映射中,类似于这里: https://www.tensorflow.org/tutorials/images/data_augmentation#augment_a_dataset_and_train_a_model_with_it - Andrew Holmgren
@Andrew H - 感谢您提供链接,非常有帮助。我已将其添加到答案中。 - user11530462
@Lukas Nießen - 希望我们已经回答了您的问题。如果您对答案满意,请接受并点赞答案。 - user11530462
1
为什么不先使用repeat,然后再使用map呢?这样,我们可以获得两倍大小的不同数据集,而不是相同数据重复两次。 - C.K.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接