Keras is a high-level Python library for working with neural networks. In this module, we’ll demonstrate using Keras to solve an image classification problem.
This is the seventh module in our series on learning Python and its use in machine learning and AI. In the previous one, we discussed the use of NLTK for text analysis. Let’s now dive into Keras, a high-level library for neural networks.
Installing Keras is easy with Anaconda's
conda install keras
This immediately installs all the dependencies you'll need.
Keras can use one of several available libraries as its backend, which is the part that handles low-level operations such as tensors. We'll use TensorFlow, which is the default.
To start, we’re going to slightly tweak the configuration of TensorFlow. Specifically, we’ll set the
allow_growth option to true, which allows TensorFlow to dynamically grow the used GPU memory rather than allocating everything beforehand. If we don’t, TensorFlow may try to allocate so much that your GPU runs out of memory immediately (it did for me). To do this, put the following code at the beginning of your file:
If your backend is TensorFlow 1.x:
from keras.backend.tensorflow_backend import set_session
import tensorflow as tf
config = tf.ConfigProto()
config.gpu_options.allow_growth = True
For TensorFlow 2.x, you'll have to call the
set_memory_growth function for your GPU. You can read more about the details behind this in the tf.config.experimental.set_memory_growth documentation.
Which version do you have? Check the result of the command
conda list to see what your TensorFlow version is. I got 1.13.1 on one computer and 2.1.0 on another, even with the same Anaconda installation command.
If you want to force Keras to use your CPU instead of your GPU, add this before the first Keras import:
os.environ['CUDA_VISIBLE_DEVICES'] = '-1'
This is a lot slower than GPU, but if you don’t have a lot of GPU memory you may want to do this.
Image Classification with Keras
We're going to demonstrate Keras for image classification, using the Intel Image Classification dataset. This dataset contains images of six classes, separated into six different directories, which is very handy because Keras offers built-in functionality to work with data in that format.
While you don’t have to worry too much about the math behind neural networks, you do need a sufficient understanding because you have to specify exactly what layers your model consists of.
One of the models Keras offers is the sequential model, a stack of layers. Creating a sequential model and adding layers is very easy:
from keras.models import Sequential
model = Sequential()
Here’s what our model will look like for the image classification:
from keras.models import Sequential
from keras.layers import Conv2D, MaxPooling2D
from keras.layers import Dropout, Flatten, Dense
from keras.layers.normalization import BatchNormalization
model = Sequential()
model.add(Conv2D(32, kernel_size=(3, 3), activation="relu", input_shape=(150, 150, 3)))
model.add(Conv2D(64, kernel_size=(3, 3), activation="relu"))
model.add(Conv2D(128, kernel_size=(3, 3), activation="relu"))
The construction of a neural network model is beyond the scope of this module, but in short: The pattern of a repetition of a convolution layer (with an increasing number of filters because the patterns get more complex), a max pooling layer, and batch normalization is often used as the first step in image classification problems. The output of that step is multi-dimensional and we flatten it to a one-dimensional vector with a Flatten layer. We end with a couple of densely connected layers with a dropout layer in between to help fight against overfitting. The last layer must output a vector with six elements because we have six categories.
Next, we compile the model, meaning we configure it for training:
Our loss function,
sparse_categorical_crossentropy, is a good fit for classification problems without overlap between categories. See the Keras documentation for a full discussion of loss functions. We're using the Adam optimizer. A full list of optimizers can be found in the relevant documentation. And
metrics specifies what the model evaluates during training and testing.
Fitting the Model
Now that we have the structure of our model, we can fit it to our dataset.
from keras.preprocessing.image import ImageDataGenerator
datagen = ImageDataGenerator(validation_split=0.2)
batch_size=32, target_size=(150,150), class_mode="sparse",
batch_size=32, target_size=(150, 150), class_mode="sparse",
(Feel free to decrease the number of epochs if you want to go through the process a little faster, with lower accuracy, especially if you’re using CPU. 40 epochs take quite a while.)
As per Keras documentation, this is what an
Generate batches of tensor image data with real-time data augmentation. The data will be looped over (in batches).
Our example doesn’t do any data augmentation. We'll take a look at that feature a little later.
In the preceding code,
validation_split=0.2 means we'll use 20% of the training set for validation. Since the dataset only comes with a training set and a test set, we’ll have to use a subset of the training set as a validation set.
flow_from_directory is a neat built-in function that is perfect for a dataset structure like we have: a subdirectory for each category.
class_mode="sparse" means that we’re working with one-dimensional integer labels.
fit_generator fits the model to
ImageDataGenerator, in a number of epochs that we specify.
Testing the Model
After training, we can test the model with the
evaluate_generator function. Just like
fit_generator, it takes a generator as an argument. We can create one for our test data, similar to what we did for the training data:
test_datagen = ImageDataGenerator()
This will return an array of two values for our example: loss and accuracy. (You can check that by looking at the
I had an accuracy of 81.7%, which isn’t too bad for a relatively simple model on a non-trivial dataset.
You can now use the
model.predict method to generate predictions on any image. This method takes a NumPy array of images as input, where an image is also a NumPy array of shape (150, 150, 3). To make a prediction on one image, you can do this:
import numpy as np
skimage.io.imread will read an image and
expand_dims will add another dimension to the array. The output is an array of predictions, where each prediction is an array of values indicating the probability of each category.
Data augmentation is when you generate new training data based on your existing training set, to improve accuracy and generalization and reduce overfitting.
For images, data augmentation can be done with several transformations on the images: rotations, flipping, zooming, shifting, shearing, and so on.
ImageDataGenerator makes this easy. To apply data augmentation to our model, change just two lines of the code.
ImageDataGenerator with more parameters, specifying what transformations we want:
datagen = ImageDataGenerator(rotation_range=30,
There are a lot more possibilities — see the Image Preprocessing documentation for a full list of parameters.
The second line is the
fit_generator call. This function has optional
validation_steps parameters that we could leave out previously because we had a fixed number of training samples. With data augmentation, we have a potentially much larger number of training samples, so we have to specify how many we want to use. If we don't, the function will just use our fixed-size sample set. One step corresponds with a batch of the given
Again, feel free to reduce the number of epochs or the number of steps if you’d like the process to be faster. I had an accuracy of 85.5% with this, after 2-3 hours of training.
Saving and Restoring a Model
Keras allows you to save your trained model in the HDF5 format:
Restoring the model is a single line as well:
model = keras.models.load_model("images_model.h5")
This requires the
h5py package, which should have been installed if you used
conda install. If you don't have it, run this pip command in a Jupyter Notebook cell:
!pip install --upgrade h5py
In this module, we walked through the use of Keras in an image classification problem. Keras has a lot more layers available than the ones we used here. If you want to dive deeper, you can use the Keras documentation as a starting point. Iit also offers plenty of examples of common deep learning problems.
In the next module, we'll take a brief look at TensorFlow, NumPy, and scikit-learn.