Cómo usar correctamente los ImageDataGenerator en Keras?

0

Pregunta

Yo estoy jugando con el aumento de datos en Keras y últimamente estoy usando básica ImageDataGenerator. Aprendí de la manera difícil que es en realidad un generador, no iterator (porque type(train_aug_ds) da <class 'keras.preprocessing.image.DirectoryIterator'> Pensé que es un iterador). También comprobé pocos blogs sobre su uso, pero no para responder a todas mis preguntas.

Así que, me cargan mis datos como este:

train_aug = ImageDataGenerator(
    rescale=1./255,
    horizontal_flip=True,
    height_shift_range=0.1,
    width_shift_range=0.1,
    brightness_range=(0.5,1.5),
    zoom_range = [1, 1.5],
)
train_aug_ds = train_aug.flow_from_directory(
    directory='./train',
    target_size=image_size,
    batch_size=batch_size,
)

Y para entrenar a mi modelo me hicieron la siguiente:

model.fit(
    train_aug_ds,
    epochs=150,
    validation_data=(valid_aug_ds,),
)

Y funcionó. Estoy un poco confundido cómo funciona, porque train_aug_ds es el generador, por lo que debe dar infinitamente grande conjunto de datos. Y la documentación dice:

Al pasar un infinitamente repetida conjunto de datos, debe especificar el steps_per_epoch argumento.

Que yo no hice, sin embargo, funciona. ¿Alguna manera de inferir el número de pasos? También, el uso de sólo aumentada de datos, o también se utiliza la no-aumentada imágenes en lote?

Así que, básicamente, mi pregunta es cómo utilizar este generador correctamente con la función fit para tener todos los datos en mi conjunto de entrenamiento, incluyendo el original, no aumentada imágenes y aumentada e imágenes, y el ciclo a través de ella varias veces/pasos (ahora parece que hace sólo un paso por la época)?

keras python tensorflow
2021-11-23 11:26:56
1

Mejor respuesta

1

Creo que la documentación puede ser bastante confuso y me imagino que el comportamiento es diferente en función de su Tensorflow y Keras versión. Por ejemplo, en este post, el usuario es el que describe el comportamiento exacto que usted está esperando. En general, el flow_from_directory() el método permite leer las imágenes directamente desde un directorio y aumentarlas, mientras que su modelo está siendo entrenado y como ya se ha dicho aquí, se repite para cada una de las muestras en cada carpeta de cada época. Utilizando el ejemplo siguiente, se puede comprobar que este es el caso (en TF 2.7) mirando los pasos por la época en la barra de progreso:

import tensorflow as tf

BATCH_SIZE = 64

flowers = tf.keras.utils.get_file(
    'flower_photos',
    'https://storage.googleapis.com/download.tensorflow.org/example_images/flower_photos.tgz',
    untar=True)

img_gen = tf.keras.preprocessing.image.ImageDataGenerator(
    rescale=1./255,
    horizontal_flip=True,
)

train_ds = img_gen.flow_from_directory(flowers, batch_size=BATCH_SIZE, shuffle=True, class_mode='sparse')
num_classes = 5

model = tf.keras.Sequential([
  tf.keras.layers.Conv2D(16, 3, padding='same', activation='relu', input_shape=(256, 256, 3)),
  tf.keras.layers.MaxPooling2D(),
  tf.keras.layers.Conv2D(32, 3, padding='same', activation='relu'),
  tf.keras.layers.MaxPooling2D(),
  tf.keras.layers.Conv2D(64, 3, padding='same', activation='relu'),
  tf.keras.layers.MaxPooling2D(),
  tf.keras.layers.Flatten(),
  tf.keras.layers.Dense(128, activation='relu'),
  tf.keras.layers.Dense(num_classes)
])

model.compile(optimizer='adam',
              loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True))

epochs=10
history = model.fit(
  train_ds,
  epochs=epochs
)
Found 3670 images belonging to 5 classes.
Epoch 1/10
 6/58 [==>...........................] - ETA: 3:02 - loss: 2.0608

Si te envuelva flow_from_directory con tf.data.Dataset.from_generator como este:

train_ds = tf.data.Dataset.from_generator(
    lambda: img_gen.flow_from_directory(flowers, batch_size=BATCH_SIZE, shuffle=True, class_mode='sparse'),
    output_types=(tf.float32, tf.float32))

Usted notará que la barra de progreso se parece a esto porque steps_per_epoch no se ha definido explícitamente:

Epoch 1/10
Found 3670 images belonging to 5 classes.
     29/Unknown - 104s 4s/step - loss: 2.0364

Y si se agrega este parámetro, usted va a ver los pasos en la barra de progreso:

history = model.fit(
  train_ds,
  steps_per_epoch = len(from_directory),
  epochs=epochs
)
Found 3670 images belonging to 5 classes.
Epoch 1/10
 3/58 [>.............................] - ETA: 3:19 - loss: 4.1357

Por último, a su pregunta:

Cómo utilizar este generador correctamente con la función de ajuste para tener todos los los datos de mi conjunto de entrenamiento, incluyendo el original, no aumentada imágenes y aumentada e imágenes, y el ciclo a través de ella varias veces/paso?

Usted puede simplemente aumentar la steps_per_epoch más allá de number of samples // batch_size multiplicando por algún factor:

history = model.fit(
  train_ds,
  steps_per_epoch = len(from_directory)*2,
  epochs=epochs
)
Found 3670 images belonging to 5 classes.
Epoch 1/10
  1/116 [..............................] - ETA: 12:11 - loss: 1.5885

Ahora, en lugar de 58 pasos cada época tiene 116.

2021-11-23 17:22:32

En otros idiomas

Esta página está en otros idiomas

Русский
..................................................................................................................
Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Slovenský
..................................................................................................................