Come utilizzare correttamente ImageDataGenerator in Keras?

0

Domanda

Io sto giocando con aumento di dati in Keras ultimamente e sto utilizzando di base ImageDataGenerator. Ho imparato nel modo più duro è in realtà un generatore, non iteratore (perché type(train_aug_ds)<class 'keras.preprocessing.image.DirectoryIterator'> Ho pensato che è un iteratore). Ho anche controllato qualche blog sul suo utilizzo, ma non rispondono a tutte le mie domande.

Così, ho caricato i miei dati come questo:

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 per addestrare il mio modello ho fatto la seguente:

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

E ha funzionato. Io sono un po ' confuso come funziona, perché train_aug_ds è un generatore, e quindi dovrebbe dare infinitamente grandi set di dati. E la documentazione dice:

Durante il passaggio di un infinitamente ripetuta set di dati, è necessario specificare il steps_per_epoch argomento.

Che non ho fatto, ma funziona. Ha qualche dedurre il numero di passi? Anche se si utilizza solo aumentata dati, oppure anche in usa non aumentata immagini in batch?

Quindi, fondamentalmente, la mia domanda è: come utilizzare questo generatore correttamente con funzione fit per avere tutti i dati del training set, tra cui le originali, non aumentata immagini e aumentata immagini, e per scorrere più volte/passaggi (per adesso sembra solo un passo per ogni epoca)?

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

Migliore risposta

1

Penso che la documentazione può essere molto confusa, e immagino che il comportamento è diverso a seconda della Tensorflow e Keras versione. Per esempio, in questo post, l'utente descrive l'esatto comportamento che ti aspetti. In generale, il flow_from_directory() il metodo permette di leggere le immagini direttamente da una directory e aumentare la loro, mentre il modello è stato addestrato e come già detto qui, si ripete per ogni campione in ogni cartella di ogni epoca. Utilizzando l'esempio seguente, è possibile verificare che questo è il caso (TF 2.7) osservando la seguente procedura per epoca nella barra di stato:

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 si avvolge flow_from_directory con tf.data.Dataset.from_generator come questa:

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

Noterete che la barra di avanzamento appare come questo, perché steps_per_epoch non è stato definito in modo esplicito:

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

E se si aggiunge questo parametro, potrete vedere i passaggi che la barra di avanzamento:

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

Infine, per la tua domanda:

Come utilizzare questo generatore correttamente con la funzione fit per avere tutti i i dati in mio set di allenamento, tra cui le originali, non aumentata immagini e aumentata immagini, e per scorrere più volte/passo?

Si può semplicemente aumentare il steps_per_epoch al di là di number of samples // batch_size moltiplicando per alcuni fattori:

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

Ora invece di 58 passaggi all'epoca si dispone di 116.

2021-11-23 17:22:32

In altre lingue

Questa pagina è in altre lingue

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