Convolutional Neural Networks Model - YOU CANalytics

Import libraries and data

In [1]:
import numpy as np
import pandas as pd
from sklearn.metrics import confusion_matrix
from sklearn.externals import joblib
import matplotlib.pyplot as plt
from sklearn import metrics
import keras
from keras.datasets import mnist
(Image_train, Number_train), (Image_test, Number_test) = mnist.load_data()
Using TensorFlow backend.
Downloading data from https://s3.amazonaws.com/img-datasets/mnist.npz
11493376/11490434 [==============================] - 3s 0us/step

Reshape and normalize data before modeling

In [ ]:
Image_train = Image_train.reshape((60000, 28,28,1))
Image_train = Image_train.astype('float32') / 255

Image_test = Image_test.reshape((10000, 28 ,28,1))
Image_test = Image_test.astype('float32') / 255

Design the CNN model using Keras / Tensorflow

In [3]:
from keras import layers
from keras import models

mnist_cnn = models.Sequential()

mnist_cnn.add(layers.Conv2D(filters = 64, kernel_size = (3, 3), activation='relu',
                 input_shape = (28, 28, 1)))
mnist_cnn.add(layers.MaxPool2D(strides=(2,2)))
mnist_cnn.add(layers.Conv2D(filters = 64, kernel_size = (3, 3), activation='relu'))
mnist_cnn.add(layers.MaxPool2D(strides=(2,2)))
mnist_cnn.add(layers.Conv2D(filters = 32, kernel_size = (3, 3), activation='relu'))

mnist_cnn.add(layers.Flatten())
mnist_cnn.add(layers.Dense(512, activation='relu'))
mnist_cnn.add(layers.Dropout(0.5))
mnist_cnn.add(layers.Dense(64, activation='relu'))
mnist_cnn.add(layers.Dense(10, activation='softmax'))

mnist_cnn.summary()

mnist_cnn.compile(optimizer='Adamax',
                loss='categorical_crossentropy',
                metrics=['accuracy'])
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv2d_1 (Conv2D)            (None, 26, 26, 64)        640       
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 13, 13, 64)        0         
_________________________________________________________________
conv2d_2 (Conv2D)            (None, 11, 11, 64)        36928     
_________________________________________________________________
max_pooling2d_2 (MaxPooling2 (None, 5, 5, 64)          0         
_________________________________________________________________
conv2d_3 (Conv2D)            (None, 3, 3, 32)          18464     
_________________________________________________________________
flatten_1 (Flatten)          (None, 288)               0         
_________________________________________________________________
dense_1 (Dense)              (None, 512)               147968    
_________________________________________________________________
dropout_1 (Dropout)          (None, 512)               0         
_________________________________________________________________
dense_2 (Dense)              (None, 64)                32832     
_________________________________________________________________
dense_3 (Dense)              (None, 10)                650       
=================================================================
Total params: 237,482
Trainable params: 237,482
Non-trainable params: 0
_________________________________________________________________

Convert the output numbers to categories

In [ ]:
from keras.utils import to_categorical

Number_train = to_categorical(Number_train)
Number_test = to_categorical(Number_test)

Train the model

In [5]:
mnist_cnn.fit(Image_train, Number_train, epochs=5, batch_size=128)
Epoch 1/5
60000/60000 [==============================] - 10s 160us/step - loss: 0.2814 - acc: 0.9103
Epoch 2/5
60000/60000 [==============================] - 6s 108us/step - loss: 0.0788 - acc: 0.9759
Epoch 3/5
60000/60000 [==============================] - 6s 108us/step - loss: 0.0549 - acc: 0.9832
Epoch 4/5
60000/60000 [==============================] - 6s 108us/step - loss: 0.0444 - acc: 0.9862
Epoch 5/5
60000/60000 [==============================] - 6s 108us/step - loss: 0.0355 - acc: 0.9888
Out[5]:
<keras.callbacks.History at 0x7fd511342cf8>
In [6]:
test_loss, test_acc = mnist_cnn.evaluate(Image_test, Number_test)
10000/10000 [==============================] - 1s 98us/step

Measure the accuracy on the test dataset

In [7]:
print('test_acc:', test_acc)
test_acc: 0.9918

Confusion matrix for the CNN Model on the test dataset

In [8]:
# Keras model to make the prediction
Number_predict = mnist_cnn.predict_classes(Image_test)
import seaborn as sns
cm = metrics.confusion_matrix(Number_test.argmax(1), Number_predict)
plt.figure(figsize=(9,9))
sns.heatmap(cm, annot=True, fmt=".0f", linewidths=.5, square = True, cmap = 'Blues_r');
plt.ylabel('Actual Number');
plt.xlabel('Predicted Number');
all_sample_title = 'Confusion Matrix : Convolutional Neural Network'
plt.title(all_sample_title, size = 15);

Visualize CNN layers

Import an image of a number (0) for which we will visualize the intermediate CNN layers to develop intuition

In [9]:
index=25
import matplotlib
import matplotlib.pyplot as plt
plt.imshow(Image_test[index].reshape(28,28), cmap = matplotlib.cm.binary)
Out[9]:
<matplotlib.image.AxesImage at 0x7fd508fe21d0>

Extract CNN intermediate layers and preprocess the image for the CNN model

In [ ]:
from keras import models
layer_outputs=[layer.output for layer in mnist_cnn.layers[:5]]
Image_test_0 = Image_test[index,:]
Image_test_0=Image_test_0.reshape(1,28,28,1)
Image_test_0 = Image_test_0.astype('float32') / 255
activation_model=models.Model(inputs=mnist_cnn.input, outputs=layer_outputs)
activations=activation_model.predict(Image_test_0)

Plot all the CNN (Convolutional and MaxPool) layers

In [11]:
import keras

# These are the names of the layers, so can have them as part of our plot
layer_names = []
for layer in mnist_cnn.layers[:5]:
    layer_names.append(layer.name)

images_per_row = 16

# Now let's display our feature maps
for layer_name, layer_activation in zip(layer_names, activations):
    # This is the number of features in the feature map
    n_features = layer_activation.shape[-1]

    # The feature map has shape (1, size, size, n_features)
    size = layer_activation.shape[1]

    # We will tile the activation channels in this matrix
    n_cols = n_features // images_per_row
    display_grid = np.zeros((size * n_cols, images_per_row * size))

    # We'll tile each filter into this big horizontal grid
    for col in range(n_cols):
        for row in range(images_per_row):
            channel_image = layer_activation[0,
                                             :, :,
                                             col * images_per_row + row]
            # Post-process the feature to make it visually palatable
            channel_image -= channel_image.mean()
            channel_image /= channel_image.std()
            channel_image *= 64
            channel_image += 128
            channel_image = np.clip(channel_image, 0, 255).astype('uint8')
            display_grid[col * size : (col + 1) * size,
                         row * size : (row + 1) * size] = channel_image

    # Display the grid
    scale = 1. / size
    plt.figure(figsize=(scale * display_grid.shape[1],
                        scale * display_grid.shape[0]))
    plt.title(layer_name)
    plt.grid(False)
    plt.imshow(display_grid, aspect='auto',cmap='inferno')
    
plt.show()
/usr/local/lib/python3.6/dist-packages/ipykernel_launcher.py:30: RuntimeWarning: invalid value encountered in true_divide

Get the shape of each element of CNN layers

In [12]:
index=4
activations[index].shape
first_layer=activations[index]
print(first_layer.shape)
(1, 3, 3, 32)

Visualize just one element of a CNN layer

In [13]:
plt.matshow(first_layer[0,:,:,2],cmap='inferno')
Out[13]:
<matplotlib.image.AxesImage at 0x7fd5085a18d0>