Keras ImageDataGenerator with flow_from_directory()

Keras’ ImageDataGenerator class allows the users to perform image augmentation while training the model. If you do not have sufficient knowledge about data augmentation, please refer to this tutorial which has explained the various transformation methods with examples. You can also refer this Keras’ ImageDataGenerator tutorial which has explained how this ImageDataGenerator class work.

Keras’ ImageDataGenerator class provide three different functions to loads the image dataset in memory and generates batches of augmented data. These three functions are:

  • .flow()
  • .flow_from_directory()
  • .flow_from_dataframe.()

 

Each of these function is achieving the same task to loads the image dataset in memory and generates batches of augmented data, but the way to accomplish the task is different.

This tutorial has explained flow_from_directory() function with example.  The flow_from_directory() method takes a path of a directory and generates batches of augmented data.

The directory structure is very important when you are using flow_from_directory() methodThe flow_from_directory() assumes:

  1. The root directory contains at least two folders one for train and one for the test.
  2. The train folder should contain n sub-directories each containing images of respective classes.
  3. The test folder should contain a single folder, which stores all test images.

 

The below figure represents the directory structure:

The syntax to call flow_from_directory() function is as follows:

flow_from_directory(directory, target_size=(256, 256), color_mode='rgb', classes=None, class_mode='categorical', batch_size=32, shuffle=True, seed=None, save_to_dir=None, save_prefix='', save_format='png', follow_links=False, subset=None, interpolation='nearest')

Prepare Dataset

For demonstration, we use the fruit dataset which has two types of fruit such as banana and Apricot. Each class contain 50 images. You can download the dataset here and save & unzip it in your current working directory. we need to train a  classifier which can classify the input fruit image into class Banana or Apricot.

Directory Structure

The directory structure must be like as below:

| --- data
|     | --- train
|     |     | --- Apricot [50 images]
|     |     | --- Banana  [50 images]
|     | --- test
|     |     | --- predict [25 images]

Let’s plot the images of train data.

In [1]:
%matplotlib inline
import matplotlib.pyplot as plt
import os
src_path = "data/train/"
sub_class = os.listdir(src_path)

fig = plt.figure(figsize=(10,5))
path = os.path.join(src_path,sub_class[0])
for i in range(4):
    plt.subplot(240 + 1 + i)
    img = plt.imread(os.path.join(path,str(i)+'.jpg'))
    plt.imshow(img, cmap=plt.get_cmap('gray'))

path = os.path.join(src_path,sub_class[1])
for i in range(4,8):
    plt.subplot(240 + 1 + i)
    img = plt.imread(os.path.join(path,str(i)+'.jpg'))
    plt.imshow(img, cmap=plt.get_cmap('gray'))

Out[1]:

Implementing a training Script

Let’s import the required packages.

In [2]:
from keras.models import Sequential
from keras.layers import Conv2D, MaxPooling2D, Dense, Flatten, Dropout
from keras.preprocessing.image import ImageDataGenerator

Let’s initialize Keras’ ImageDataGenerator class

In [3]:
src_path_train = "data/train/"
src_path_test = "data/test/"

train_datagen = ImageDataGenerator(
        rescale=1 / 255.0,
        rotation_range=20,
        zoom_range=0.05,
        width_shift_range=0.05,
        height_shift_range=0.05,
        shear_range=0.05,
        horizontal_flip=True,
        fill_mode="nearest",
        validation_split=0.20)

test_datagen = ImageDataGenerator(rescale=1 / 255.0)

Let’s initialize our training, validation and testing generator:

In [4]:
batch_size = 8
train_generator = image_datagen.flow_from_directory(
    directory=src_path_train,
    target_size=(100, 100),
    color_mode="rgb",
    batch_size=batch_size,
    class_mode="categorical",
    subset='training',
    shuffle=True,
    seed=42
)
valid_generator = image_datagen.flow_from_directory(
    directory=src_path_train,
    target_size=(100, 100),
    color_mode="rgb",
    batch_size=batch_size,
    class_mode="categorical",
    subset='validation',
    shuffle=True,
    seed=42
)
test_generator = test_datagen.flow_from_directory(
    directory=src_path_test,
    target_size=(100, 100),
    color_mode="rgb",
    batch_size=1,
    class_mode=None,
    shuffle=False,
    seed=42
)
Out[4]:
Found 80 images belonging to 2 classes.
Found 20 images belonging to 2 classes.
Found 25 images belonging to 1 classes.

Let’s define the Convolutional Neural Network (CNN)

In [5]:
def prepare_model():
    model = Sequential()
    model.add(Conv2D(32,kernel_size=(3,3),activation='relu',input_shape=(100, 100, 3)))
    model.add(MaxPooling2D(pool_size=(2, 2)))
    model.add(Flatten())
    model.add(Dense(16, activation='relu'))
    model.add(Dense(2, activation='sigmoid'))
    model.compile(loss="binary_crossentropy",optimizer="adam",metrics=['accuracy'])
    return model

Let’s train the model using fit_generator:

In [6]:
model = prepare_model()
model.fit_generator(train_generator,
                    validation_data = train_generator,
                    steps_per_epoch = train_generator.n//train_generator.batch_size,
                    validation_steps = valid_generator.n//valid_generator.batch_size,
                    epochs=5)
Out[6]:
Epoch 1/5
2/2 [==============================] - 1s 727ms/step - loss: 1.9084 - acc: 0.5000 - val_loss: 0.9224 - val_acc: 0.7250
Epoch 2/5
2/2 [==============================] - 1s 463ms/step - loss: 1.1861 - acc: 0.6215 - val_loss: 0.7474 - val_acc: 0.7250
Epoch 3/5
2/2 [==============================] - 1s 454ms/step - loss: 0.5270 - acc: 0.8359 - val_loss: 0.5052 - val_acc: 0.7312
Epoch 4/5
2/2 [==============================] - 1s 366ms/step - loss: 0.5657 - acc: 0.7326 - val_loss: 0.4277 - val_acc: 0.7500
Epoch 5/5
2/2 [==============================] - 1s 487ms/step - loss: 0.2244 - acc: 0.8906 - val_loss: 0.0822 - val_acc: 1.0000

Let’s evaluate our model performance

In [7]: 
score = model.evaluate_generator(valid_generator)
print('Test loss:', score[0])
print('Test accuracy:', score[1])

Out[7]:
Test loss: 0.000340
Test accuracy: 1.0

Let’s make a prediction on a test data using Keras’ predict_generator

In [7]:
predict=model.predict_generator(test_generator)
# predict the class label
y_classes = predict.argmax(axis=-1)

.     .     .

Leave a Reply

Your email address will not be published. Required fields are marked *

Computer Vision Tutorials

Prepare COCO dataset of a specific subset of classes for semantic image segmentation

YOLOV4: Train a yolov4-tiny on the custom dataset using google colab.

Video classification techniques with Deep Learning

Keras ImageDataGenerator with flow_from_dataframe()

Keras ImageDataGenerator with flow()

Keras ImageDataGenerator

Keras fit, fit_generator, train_on_batch

Keras Modeling | Sequential vs Functional API

Save and Load Keras Model

Convolutional Neural Networks (CNN) with Keras in Python

Transfer Learning for Image Recognition Using Pre-Trained Models

An introduction to Transfer Learning

Keras ImageDataGenerator and Data Augmentation

Introduction to Computer Vision