Huseyn Gasimov
Huseyn Gasimov
Creator of this blog.
Aug 31, 2018 4 min read

Simple Image Classification With Keras

thumbnail for this post

In my previous blog post, I classified CIFAR10 image data set using Tensorflow. I had to write a lot of code and the accuracy was not satisfactory for me. Now I will try to build a model with better accuracy writing less code. Let’s see how it goes.

Keras

This time I will use Keras instead of Tensorflow. Keras is a high-level neural networks API, written in Python and capable of running on top of TensorFlow, CNTK, or Theano. It was developed with a focus on enabling fast experimentation.

Load data and libraries

Let’s load the libraries first.

import matplotlib.pyplot as plt
import time
from keras.models import Sequential
from keras.layers import Conv2D, MaxPooling2D
from keras.layers import Activation, Dropout, Flatten, Dense
from keras.optimizers import Adam
from keras.utils import to_categorical

from keras.datasets import cifar10

%matplotlib inline

Now I load the CIFAR10 data set of 50,000 32×32 color training images, labeled over 10 categories, and 10,000 test images.

CIFAR10 dataset

(x_train, y_train), (x_test, y_test) = cifar10.load_data()

Let’s see an image from this data set:

plt.imshow(x_train[5,:,:,:])
print('y =', y_train[5])

Image from CIFAR10 dataset

Now I check the shape of the training and test set variables.

print('x_train.shape =', x_train.shape)
print('x_test.shape =', x_test.shape)
print('y_train.shape =', y_train.shape)
print('y_test.shape =', y_test.shape)
x_train.shape = (50000, 32, 32, 3)
x_test.shape = (10000, 32, 32, 3)
y_train.shape = (50000, 1)
y_test.shape = (10000, 1)

The training and test labels are numbers in range [0-10]. I need to convert them to one-hot format before I use them.

n_classes = 10

y_train_onehot = to_categorical(y_train, n_classes)
y_test_onehot = to_categorical(y_test, n_classes)

print('y_train_onehot.shape =', y_train_onehot.shape)
print('y_test_onehot.shape =', y_test_onehot.shape)
y_train_onehot.shape = (50000, 10)
y_test_onehot.shape = (10000, 10)

Build Keras model

I built my model in Tensorflow in my previous post. The model had this architecture:

Network

Now I will build it in Keras.

def createModel():
    model = Sequential()
    model.add(Conv2D(32, (3, 3), padding='same', activation='relu', input_shape=(32, 32, 3)))
    model.add(MaxPooling2D(pool_size=(3, 3), strides=(2,2), padding='same'))
    model.add(Dropout(0.3))
 
    model.add(Conv2D(64, (3, 3), padding='same', activation='relu'))
    model.add(MaxPooling2D(pool_size=(3, 3), strides=(2,2), padding='same'))
    model.add(Dropout(0.3))
 
    model.add(Flatten())
    model.add(Dense(n_classes, activation='softmax'))
     
    return model

It’s amazing that one can build the same Tensorflow model with 10 lines of code in Keras.

Now let’s train our model:

def printElapsedTime(start_time):
  elapsed_time = time.time() - start_time
  print('elapsed time:', time.strftime("%H:%M:%S", time.gmtime(elapsed_time)))

model1 = createModel()
batch_size = 128
epochs = 50

opt = Adam(lr=0.0001)
model1.compile(optimizer=opt, loss='categorical_crossentropy', metrics=['accuracy'])

# start training  
start_time = time.time()  
history = model1.fit(x_train, y_train_onehot, batch_size=batch_size, epochs=epochs, verbose=1)
printElapsedTime(start_time)
Epoch 150
5000050000 [==================] – 11s 211us/step – loss: 14.2199 – acc: 0.1101

Epoch 5050
5000050000 [==================] – 8s 160us/step – loss: 0.8841 – acc: 0.6938

elapsed time: 00:06:34

Now let’s evaluate our model:

model1.evaluate(x_test, y_test_onehot)
1000010000 [==============================] – 1s 147us/step
[0.9298853613853455, 0.6834]

I had test loss = 0.93 and test accuracy = 0.68 after 50 epochs.

Improving the model

One of the techniques to improve the model accuracy is adding more layers to the network. Let’s add one more CONV2D block and one Dense layer to the network.

def createModel2():
    model = Sequential()
    model.add(Conv2D(64, (3, 3), padding='same', activation='relu', input_shape=(32, 32, 3)))
    model.add(MaxPooling2D(pool_size=(2, 2)))
    model.add(Dropout(0.3))
 
    model.add(Conv2D(64, (3, 3), padding='same', activation='relu'))
    model.add(MaxPooling2D(pool_size=(2, 2)))
    model.add(Dropout(0.3))
 
    model.add(Conv2D(64, (3, 3), padding='same', activation='relu'))
    model.add(MaxPooling2D(pool_size=(2, 2)))
    model.add(Dropout(0.3))
 
    model.add(Flatten())
    model.add(Dense(512, activation='relu'))
    model.add(Dropout(0.5))
    model.add(Dense(n_classes, activation='softmax'))
     
    return model

Now I train the new model:

model2 = createModel2()
model2.compile(optimizer=opt, loss='categorical_crossentropy', metrics=['accuracy'])
  
start_time = time.time()
history = model2.fit(x_train, y_train_onehot, batch_size=batch_size, epochs=epochs, verbose=1)
printElapsedTime(start_time)
Epoch 150
5000050000 [==================] – 14s 279us/step – loss: 13.6624 – acc: 0.1243

Epoch 5050
5000050000 [==================] – 10s 203us/step – loss: 0.8560 – acc: 0.7024
elapsed time: 00:08:58

Let’s test the model:

model2.evaluate(x_test, y_test_onehot)
1000010000 [==============================] – 2s 169us/step
[0.7776505652427673, 0.7394]

As it was expected, the second model was able to do better than the first one (73% test accuracy) after 50 epochs but it took it more time to do so.

Now I plot the lost and accuracy history:

# Loss Curves
plt.figure(figsize=[8,6])
plt.plot(history.history['loss'],'r',linewidth=3.0)
plt.legend(['Training loss'],fontsize=18)
plt.xlabel('Epochs ',fontsize=16)
plt.ylabel('Loss',fontsize=16)
plt.title('Loss Curves',fontsize=16)

# Accuracy Curves
plt.figure(figsize=[8,6])
plt.plot(history.history['acc'],'r',linewidth=3.0)
plt.legend(['Training Accuracy'],fontsize=18)
plt.xlabel('Epochs ',fontsize=16)
plt.ylabel('Accuracy',fontsize=16)
plt.title('Accuracy Curves',fontsize=16)

Loss curve

Accuracy curve

As you see, the accuracy was still on rise after 50 epochs. Model accuracy would increase if I kept the training running even more.

Summary

Just a quick recap. In this blog post, I first wrote 10 lines of code using Keras to create a deep convolutional network. It classified the CIFAR10 data set with 68% accuracy after short training (just 50 epochs). Later, I was able to improve the classification accuracy (73%) by adding more layers to my convolutional network.