We proceed with the recipe as follows:
- Download the dogs and cats data from Kaggle (https://www.kaggle.com/c/dogs-vs-cats/data) and create a data directory containing two subdirectories, train and validation, each of which has two additional subdirectory, dogs and cats respectively.
- Import the Keras modules that will be used later for our computation and save a few useful constants:
from keras import applications
from keras.preprocessing.image import ImageDataGenerator
from keras import optimizers
from keras.models import Sequential, Model
from keras.layers import Dropout, Flatten, Dense
from keras import optimizers
img_width, img_height = 256, 256
batch_size = 16
epochs = 50
train_data_dir = 'data/dogs_and_cats/train'
validation_data_dir = 'data/dogs_and_cats/validation'
#OUT CATEGORIES
OUT_CATEGORIES=1
#number of train, validation samples
nb_train_samples = 2000
nb_validation_samples =
- Load the pretrained on the ImageNet VGG16 network and omit the last layer because we will add a custom classification network on the top of the prebuilt VGG16 and replace the last classification layer:
# load the VGG16 model pretrained on imagenet
base_model = applications.VGG16(weights = "imagenet", include_top=False, input_shape = (img_width, img_height, 3))
base_model.summary()
Here is the output of the preceding code:
- Freeze a certain number of lower layers for the pretrained VGG16 network. In this case, we decide to freeze the initial 15 layers:
# Freeze the 15 lower layers for layer in base_model.layers[:15]: layer.trainable = False
- Add a custom set of top layers for classification:
# Add custom to layers # build a classifier model to put on top of the convolutional model top_model = Sequential() top_model.add(Flatten(input_shape=base_model.output_shape[1:]))
top_model.add(Dense(256, activation='relu')) top_model.add(Dropout(0.5)) top_model.add(Dense(OUT_CATEGORIES, activation='sigmoid'))
- The custom network should be pretrained separately and here, we omit this part for the sake of simplicity, leaving this task to the reader:
#top_model.load_weights(top_model_weights_path)
- Create a new network that is the juxtaposition of the pretrained VGG16 network and our pretrained custom network:
# creating the final model, a composition of
# pre-trained and
model = Model(inputs=base_model.input, outputs=top_model(base_model.output))
# compile the model
model.compile(loss = "binary_crossentropy", optimizer = optimizers.SGD(lr=0.0001, momentum=0.9), metrics=["accuracy"])
- Retrain the juxtaposed new model still keeping the 15 lowest layers of VGG16 frozen. In this particular example, we also use an Image Augumentator to increase our training set:
# Initiate the train and test generators with data Augumentation
train_datagen = ImageDataGenerator(
rescale = 1./255,
horizontal_flip = True)
test_datagen = ImageDataGenerator(rescale=1. / 255)
train_generator = train_datagen.flow_from_directory(
train_data_dir,
target_size=(img_height, img_width),
batch_size=batch_size,
class_mode='binary')
validation_generator = test_datagen.flow_from_directory(
validation_data_dir,
target_size=(img_height, img_width),
batch_size=batch_size,
class_mode='binary', shuffle=False)
model.fit_generator(
train_generator,
steps_per_epoch=nb_train_samples // batch_size,
epochs=epochs,
validation_data=validation_generator,
validation_steps=nb_validation_samples // batch_size,
verbose=2, workers=12)
- Evaluate the results on the juxtaposed network:
score = model.evaluate_generator(validation_generator, nb_validation_samples/batch_size)
scores = model.predict_generator(validation_generator, nb_validation_samples/batch_size)