Survey of Keras's image related generators
In François Chollet's Deep learning with Python, he teaches how to build image classification models using ImageDataGenerators. Let's look into how these are made and how to use them.
Use images in a folder
A standard snippet from his book to prepare the datasets would look like this:
train_datagen = ImageDataGenerator(rescale=1./255, rotation_range=40, width_shift_range=.2, height_shift_range=.2, shear_range=.2, zoom_range=.2, horizontal_flip=True, fill_mode='nearest') test_datagen = ImageDataGenerator(rescale=1./255) batch_size=30 target_size=224 train_generator = train_datagen.flow_from_directory(train_dir, target_size=(target_size,target_size), batch_size=batch_size) validation_generator = test_datagen.flow_from_directory(validation_dir, target_size=(target_size,target_size), batch_size=batch_size) > Found 3512 images belonging to 6 classes. > Found 633 images belonging to 6 classes.
ImageDataGenerator generates an iterator of batches of images and labels using a folder's directory structure. It also takes a few parameters that make the iterator apply random transformations. This helps prevent overfitting.
By default it assumes a categorical classification model. If you want binary, set
class_mode to "binary".
flow_from_directory creates the
Train a model with a pre-trained model
Then to train the model, you could use a pre-trained image classification model, freeze it, put a Dense network on top, and train it.
import tensorflow as tf from tensorflow.keras import layers, models from tensorflow.keras.applications import Xception conv_base = Xception(include_top=False, input_shape=(target_size, target_size, 3)) # Freeze the pre-trained model's base conv_base.trainable = False model = models.Sequential() model.add(conv_base) model.add(layers.Flatten()) model.add(layers.Dense(512, activation='relu')) model.add(layers.Dense(train_generator.num_classes, activation='softmax')) model.compile(loss='categorical_crossentropy', metrics=['accuracy']) model.summary() history = model.fit(train_generator, steps_per_epoch=len(train_generator), epochs=20, validation_data=validation_generator, validation_steps=len(validation_generator), callbacks=[tf.keras.callbacks.EarlyStopping(patience=1)])
Printing out the first batch
If you want to iterate through the Iterator manually to inspect its data, you could use a loop:
for x_batch, y_batch in directoryIterator: print(x_batch) print(y_batch) break;
This will print out the first batch. If you didn't put the break, it would loop infinitely.
Getting steps per epoch
If you want to know how many steps you'd need to cover one epoch during training, you'd need to know how many images are being provided and divide that by the batch size. The
DirectoryIterator actually does that for us in
Looping through the data once
On top of
__getitem__. So one simple way to loop through it is:
for i in range(len(directoryIterator)): x_batch, y_batch = directoryIterator[i] ...
Another way, which is more verbose, is to do:
i = 0 steps_per_epoch = len(directoryIterator) for (x_batch, y_batch) in directoryIterator: ... i += 1 if (i == steps_per_epoch): break
Finding the number of classes
I wasn't able to find where in the source code it was computed, but this works:
Finding the mapping of class index to class names
As per the doc of flow_from_directory:
Determining if it's binary or categorical
One could look at
num_classes, but that doesn't cover the case of a categorical model with only two classes. Instead check its