Como usar corretamente ImageDataGenerator em Keras?

0

Pergunta

Eu estou jogando com o aumento de dados em Keras ultimamente e estou usando o basic ImageDataGenerator. Eu aprendi da maneira mais difícil é na verdade um gerador, não iterador (porque type(train_aug_ds)<class 'keras.preprocessing.image.DirectoryIterator'> Eu pensei que é uma iteração). Eu também verificado alguns blogs sobre a usá-lo, mas eles não responder a todas as minhas perguntas.

Então, eu carreguei a minha dados 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,
)

E para treinar o meu modelo eu fiz o seguinte:

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

E funcionou. Estou um pouco confuso em como ele funciona, porque train_aug_ds é um gerador, de modo que deve dar infinitamente grande conjunto de dados. Documentação e diz:

Quando passar uma infinita repetição de conjunto de dados, você deve especificar o steps_per_epoch argumento.

O que eu não fiz, ainda assim, ele funciona. Ele, de alguma forma, inferir o número de passos? Além disso, ele usa apenas dados aumentados, ou ele usa também não aumentada imagens em lote?

Então, basicamente, a minha pergunta é como usar este gerador corretamente com a função fit para ter todos os dados na minha conjunto de treinamento, incluindo o original, não aumentada imagens e aumentada imagens, e para percorrer várias vezes/passos (agora parece que é apenas um passo por época)?

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

Melhor resposta

1

Eu acho que a documentação pode ser bastante confuso e eu imagino que o comportamento é diferente, dependendo do seu Tensorflow e Keras versão. Por exemplo, neste post, o usuário está descrevendo o comportamento exato que você está esperando. Geralmente, o flow_from_directory() o método permite que você leia as imagens diretamente a partir de um diretório e aumentá-los enquanto o modelo está sendo treinados e como já foi dito aqui, ele repete para cada amostra em cada pasta de cada época. Usando o exemplo a seguir, você pode verificar que este é o caso (no TF 2.7), observando os passos por época na barra de progresso:

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

Se você quebrar flow_from_directory com tf.data.Dataset.from_generator como esta:

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))

Você notará que a barra de progresso parece assim porque steps_per_epoch não foi explicitamente definido:

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

E se você adicionar esse parâmetro, você vai ver os passos na barra de progresso:

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

Finalmente, à sua pergunta:

Como usar este gerador corretamente com função de ajuste para ter todos os de dados no meu conjunto de treinamento, incluindo o original, não aumentada e imagens aumentada imagens, e para percorrer várias vezes/passo?

Você pode, simplesmente, aumentar a steps_per_epoch além de number of samples // batch_size multiplicando por algum fator:

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

Agora, em vez de 58 passos por época você tem 116.

2021-11-23 17:22:32

Em outros idiomas

Esta página está em outros idiomas

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