【问题标题】:How can I combine ImageDataGenerator with TensorFlow datasets in TF2?如何在 TF2 中将 ImageDataGenerator 与 TensorFlow 数据集结合起来?
【发布时间】:2020-01-08 15:15:10
【问题描述】:

我有一个classify猫狗的TF数据集:

import tensorflow_datasets as tfds
SPLIT_WEIGHTS = (8, 1, 1)
splits = tfds.Split.TRAIN.subsplit(weighted=SPLIT_WEIGHTS)

(raw_train, raw_validation, raw_test), metadata = tfds.load(
    'cats_vs_dogs', split=list(splits),
    with_info=True, as_supervised=True)

在示例中,他们使用了一些带有地图功能的图像增强功能。我想知道这是否也可以通过 ImageDataGenerator 描述的 here 类来完成:

from tensorflow.keras.preprocessing.image import ImageDataGenerator
train_image_generator = ImageDataGenerator(rescale=1./255) # Generator for our training data
train_data_gen = train_image_generator.flow_from_directory(batch_size=batch_size,
                                                           directory=train_dir,
                                                           shuffle=True,
                                                           target_size=(IMG_HEIGHT, IMG_WIDTH),
                                                           class_mode='binary')

我面临的问题是我只能看到3 ways 才能使用ImageDataGenerator:pandas 数据框、numpy 数组和图像目录。 有没有办法同时使用 Tensorflow 数据集并结合这些方法?

【问题讨论】:

    标签: python tensorflow keras tensorflow2.0


    【解决方案1】:

    是的,但它有点棘手。
    Keras ImageDataGenerator 适用于 numpy.arrays 而不是 tf.Tensor,因此我们必须使用 Tensorflow 的 numpy_function。这将允许我们对 tf.data.Dataset 内容执行操作,就像它是 numpy 数组一样。

    首先,让我们声明我们将在数据集上.map 的函数(假设您的数据集由图像、标签对组成):

    # We will take 1 original image and create 5 augmented images:
    HOW_MANY_TO_AUGMENT = 5
    
    def augment(image, label):
    
      # Create generator and fit it to an image
      img_gen = tf.keras.preprocessing.image.ImageDataGenerator(rescale=1./255)
      img_gen.fit(image)
    
      # We want to keep original image and label
      img_results = [(image/255.).astype(np.float32)] 
      label_results = [label]
    
      # Perform augmentation and keep the labels
      augmented_images = [next(img_gen.flow(image)) for _ in range(HOW_MANY_TO_AUGMENT)]
      labels = [label for _ in range(HOW_MANY_TO_AUGMENT)]
    
      # Append augmented data and labels to original data
      img_results.extend(augmented_images)
      label_results.extend(labels)
    
      return img_results, label_results
    

    现在,为了在tf.data.Dataset 中使用这个函数,我们必须声明一个numpy_function

    def py_augment(image, label):
      func = tf.numpy_function(augment, [image, label], [tf.float32, tf.int32])
      return func
    

    py_augment 可以像这样安全地使用:

    augmented_dataset_ds = image_label_dataset.map(py_augment)

    数据集中的image 部分现已成型 (HOW_MANY_TO_AUGMENT, image_height, image_width, channels)。 要将其转换为简单的(1, image_height, image_width, channels),您只需使用unbatch

    unbatched_augmented_dataset_ds = augmented_dataset_ds.unbatch()

    所以整个部分看起来像这样:

    HOW_MANY_TO_AUGMENT = 5
    
    def augment(image, label):
    
      # Create generator and fit it to an image
      img_gen = tf.keras.preprocessing.image.ImageDataGenerator(rescale=1./255)
      img_gen.fit(image)
    
      # We want to keep original image and label
      img_results = [(image/255.).astype(np.float32)] 
      label_results = [label]
    
      # Perform augmentation and keep the labels
      augmented_images = [next(img_gen.flow(image)) for _ in range(HOW_MANY_TO_AUGMENT)]
      labels = [label for _ in range(HOW_MANY_TO_AUGMENT)]
    
      # Append augmented data and labels to original data
      img_results.extend(augmented_images)
      label_results.extend(labels)
    
      return img_results, label_results
    
    def py_augment(image, label):
      func = tf.numpy_function(augment, [image, label], [tf.float32, tf.int32])
      return func
    
    unbatched_augmented_dataset_ds = augmented_dataset_ds.map(py_augment).unbatch()
    
    # Iterate over the dataset for preview:
    for image, label in unbatched_augmented_dataset_ds:
        ...
    

    【讨论】:

      【解决方案2】:

      一个想法是您可以创建一个生成器包装函数,该函数使用您的 tfds 数据集来加载批量大小的倍数。然后将这些图像、标签传递给 ImageDataGenerator 的 flow 方法,该方法将以您所需的批量大小的速率生成增强数据。

      例如:

      def tfds_imgen(ds, imgen, batch_size, batches_per):
          for images, labels in ds:
              flow_ = imgen.flow(images, labels, batch_size=batch_size)
              for _ in range(batches_per):
                  yield next(flow_)
      
      raw_train_ds = tfds.load(
          'cats_vs_dogs', split='train',
          batch_size=SOME_MULTIPLE_OF_32,
          as_supervised=True)
      
      imgen = ImageDataGenerator(...)
      
      train_ds = tfds_imgen(
          raw_train_ds.as_numpy_iterator(), imgen,
          batch_size=32, batches_per=SOME_MULTIPLE_OF_32 // 32)
      

      【讨论】:

        【解决方案3】:

        一种方法是通过 keras 预处理层添加数据增强,使增强成为模型的一部分(参见此处:https://www.tensorflow.org/tutorials/images/data_augmentation#data_augmentation_2)。

        文档中的示例:

        data_augmentation = tf.keras.Sequential([
          layers.RandomFlip("horizontal_and_vertical"),
          layers.RandomRotation(0.2),
        ])
        

        【讨论】:

          猜你喜欢
          • 2021-07-25
          • 1970-01-01
          • 2022-12-04
          • 2019-08-15
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-11-02
          • 1970-01-01
          相关资源
          最近更新 更多