In TensorFlow 2, are Datasets less efficient when doing image augmentation and combining numpy and ImageDataGenerator?

Viewed 424

tf.keras.preprocessing.image.ImageDataGenerator is super simple and easy to use to perform data augmentation. However, it seems to be much slower than using tf.data.Dataset to load data. I tried to load images tf.data.Dataset but couldn't figure out how to do the same data augmentation such as randomly shifting the width and height, randomly rotate, etc. I see in github that all these tf.keras.image.ImageDataGenerator augmentations seem to be using this function tf.keras.preprocessing.image.apply_affine_transform; however, the input must be numpy arrays.

For the best performance, do I have to rewrite the tf.keras.preprocessing.image.apply_affine_transform function so it takes TensorFlow tensors or can I just change the image to numpy during preprocessing phase in tf.data.Dataset, use the apply_affine_transform function for data augmentation, and cast it back to a Tensor?

Additionally, there is also tf.data.Dataset.from_generator() which looks like it can take an ImageDataGenerator.

Which is faster and more efficient for data loading: option 1, 2, or 3?

import tensorflow as tf

AUTOTUNE = tf.data.experimental.AUTOTUNE

batch_size=32

option 1

def preprocess(filename): tfImg = tf.io.read_file(file_path) numpyImg = tf.image.decode_jpeg(tfImg, channels=3).numpy() augNumpy = tf.keras.preprocessing.image.apply_affine_transform(numpyImg, change_some_arguments_here_for_augmentation) return tf.cast(augNumpy, tf.float32). # return augmented image as Tensor

list_ds = tf.data.Dataset.list_files(str(data_dir/'*/*'))

newAugmentedDataset = list_ds.map(preprocess, num_parallel_calls=AUTOTUNE).shuffle(buffer_size=1000).repeat().batch_size(batch_size).prefetch(AUTOTUNE)

option 2

def preprocess(filename): tfImg = tf.io.read_file(file_path) tfImg = tf.image.decode_jpeg(tfImg, channels=3) return rewritten_apply_affine_function(tfImg,...)

list_ds = tf.data.Dataset.list_files(str(data_dir/'*/*'))

newAugmentedDataset = list_ds.map(preprocess, num_parallel_calls=AUTOTUNE).shuffle(buffer_size=1000).repeat().batch_size(batch_size).prefecth(AUTOTUNE)

option 3

train_data_generator = ImageDataGenerator(augmentations_here)

ftrain_generator = train_data_generator.flow_from_directory(directory_here, shuffle=False)

ftrain_generator_ds = tf.data.Dataset.from_generator(lambda : ftrain_generator, output_types=(tf.float32), output_shapes = (tf.TensorShape([None, height_here, width_here, num_channel]).prefetch(AUTOTUNE)

any of the options above goes into .fit

model.fit(dataset_here, steps_per_epoch=sample_count/batch_size)

0 Answers
Related