Image classifier for the SVHN dataset

目录

<!DOCTYPE html>

Capstone Project

Capstone Project

Image classifier for the SVHN dataset

Instructions

In this notebook, you will create a neural network that classifies real-world images digits. You will use concepts from throughout this course in building, training, testing, validating and saving your Tensorflow classifier model.

This project is peer-assessed. Within this notebook you will find instructions in each section for how to complete the project. Pay close attention to the instructions as the peer review will be carried out according to a grading rubric that checks key parts of the project instructions. Feel free to add extra cells into the notebook as required.

How to submit

When you have completed the Capstone project notebook, you will submit a pdf of the notebook for peer review. First ensure that the notebook has been fully executed from beginning to end, and all of the cell outputs are visible. This is important, as the grading rubric depends on the reviewer being able to view the outputs of your notebook. Save the notebook as a pdf (File -> Download as -> PDF via LaTeX). You should then submit this pdf for review.

Let's get started!

We'll start by running some imports, and loading the dataset. For this project you are free to make further imports throughout the notebook as you wish.

In [27]:
import tensorflow as tf
from scipy.io import loadmat

import matplotlib.pyplot as plt
import numpy as np

SVHN overview image For the capstone project, you will use the SVHN dataset. This is an image dataset of over 600,000 digit images in all, and is a harder dataset than MNIST as the numbers appear in the context of natural scene images. SVHN is obtained from house numbers in Google Street View images.

  • Y. Netzer, T. Wang, A. Coates, A. Bissacco, B. Wu and A. Y. Ng. "Reading Digits in Natural Images with Unsupervised Feature Learning". NIPS Workshop on Deep Learning and Unsupervised Feature Learning, 2011.

Your goal is to develop an end-to-end workflow for building, training, validating, evaluating and saving a neural network that classifies a real-world image into one of ten classes.

In [28]:
# Run this cell to load the dataset

train = loadmat('data/train_32x32.mat')
test = loadmat('data/test_32x32.mat')

Both train and test are dictionaries with keys X and y for the input images and labels respectively.

In [29]:
train["X"][0].shape
Out[29]:
(32, 3, 73257)
In [30]:
test["y"].shape
Out[30]:
(26032, 1)
In [31]:
a  = np.where(test["y"]<10, test["y"], 0)
a = np.unique(a, return_counts=True)
a
Out[31]:
(array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], dtype=uint8),
 array([1744, 5099, 4149, 2882, 2523, 2384, 1977, 2019, 1660, 1595]))

1. Inspect and preprocess the dataset

  • Extract the training and testing images and labels separately from the train and test dictionaries loaded for you.
  • Select a random sample of images and corresponding labels from the dataset (at least 10), and display them in a figure.
  • Convert the training and test images to grayscale by taking the average across all colour channels for each pixel. Hint: retain the channel dimension, which will now have size 1.
  • Select a random sample of the grayscale images and corresponding labels from the dataset (at least 10), and display them in a figure.
In [32]:
train_data = np.transpose(train["X"], (3,0,1,2))
train_targets = np.where(train["y"]<10, train["y"], 0)
test_data = np.transpose(test["X"], (3,0,1,2))
test_targets = np.where(test["y"]<10, test["y"], 0)
In [33]:
fig=plt.figure(figsize=(32, 32))
columns = 10
rows = 1
for i in range(1, columns*rows +1):
    fig.add_subplot(rows, columns, i)
    plt.imshow(train_data[i])
    plt.axis("off")
plt.show()
In [34]:
train_data_gray = np.mean(train_data, axis=-1)
test_data_gray = np.mean(test_data, axis=-1)
In [35]:
fig=plt.figure(figsize=(32, 32))
columns = 10
rows = 1
for i in range(1, columns*rows +1):
    fig.add_subplot(rows, columns, i)
    plt.imshow(train_data_gray[i])
    plt.axis("off")
plt.show()

2. MLP neural network classifier

  • Build an MLP classifier model using the Sequential API. Your model should use only Flatten and Dense layers, with the final layer having a 10-way softmax output.
  • You should design and build the model yourself. Feel free to experiment with different MLP architectures. Hint: to achieve a reasonable accuracy you won't need to use more than 4 or 5 layers.
  • Print out the model summary (using the summary() method)
  • Compile and train the model (we recommend a maximum of 30 epochs), making use of both training and validation sets during the training run.
  • Your model should track at least one appropriate metric, and use at least two callbacks during training, one of which should be a ModelCheckpoint callback.
  • As a guide, you should aim to achieve a final categorical cross entropy training loss of less than 1.0 (the validation loss might be higher).
  • Plot the learning curves for loss vs epoch and accuracy vs epoch for both training and validation sets.
  • Compute and display the loss and accuracy of the trained model on the test set.
In [36]:
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Flatten, Dense
In [37]:
def get_new_model(input_shape):
    model = Sequential([
        Flatten(input_shape=input_shape),
        Dense(units=128, activation="relu"),
        Dense(units=128, activation="relu"),
        Dense(units=128, activation="relu"),
        Dense(units=64, activation="relu"),
        Dense(units=64, activation="relu"),
        Dense(units=64, activation="relu"),

        Dense(units=10,use_bias=True, activation="softmax",bias_initializer='ones')
    ])
    model.compile(optimizer="adam", loss="sparse_categorical_crossentropy",metrics=["acc"])
    return model
In [38]:
mlp_model = get_new_model(train_data_gray[0].shape)
mlp_model.summary()
Model: "sequential_1"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
flatten_1 (Flatten)          (None, 1024)              0         
_________________________________________________________________
dense_7 (Dense)              (None, 128)               131200    
_________________________________________________________________
dense_8 (Dense)              (None, 128)               16512     
_________________________________________________________________
dense_9 (Dense)              (None, 128)               16512     
_________________________________________________________________
dense_10 (Dense)             (None, 64)                8256      
_________________________________________________________________
dense_11 (Dense)             (None, 64)                4160      
_________________________________________________________________
dense_12 (Dense)             (None, 64)                4160      
_________________________________________________________________
dense_13 (Dense)             (None, 10)                650       
=================================================================
Total params: 181,450
Trainable params: 181,450
Non-trainable params: 0
_________________________________________________________________
In [39]:
checkpoint_best_path = "model_checkpoint_best/checkpoint"
checkpoint_best = tf.keras.callbacks.ModelCheckpoint(
    filepath=checkpoint_best_path,
    save_weights_only=True,
    save_best_only=True,
    save_freq="epoch",
    verbose=2
)
earlystoping = tf.keras.callbacks.EarlyStopping(min_delta=0.001,patience=5)
class training_callback(tf.keras.callbacks.Callback):
    def on_train_begin(self, logs=None):
        print("Start training....")
    def on_train_end(self, logs=None):
        print("Finished training!")
In [40]:
history = mlp_model.fit(train_data_gray, train_targets, validation_split=0.2, epochs=30, batch_size=512, verbose=2, 
                    callbacks=[checkpoint_best,earlystoping, training_callback()])
Train on 58605 samples, validate on 14652 samples
Start training....
Epoch 1/30

Epoch 00001: val_loss improved from inf to 2.31268, saving model to model_checkpoint_best/checkpoint
58605/58605 - 15s - loss: 4.9295 - acc: 0.1375 - val_loss: 2.3127 - val_acc: 0.1582
Epoch 2/30

Epoch 00002: val_loss improved from 2.31268 to 2.29652, saving model to model_checkpoint_best/checkpoint
58605/58605 - 12s - loss: 2.2981 - acc: 0.1764 - val_loss: 2.2965 - val_acc: 0.1923
Epoch 3/30

Epoch 00003: val_loss improved from 2.29652 to 2.22045, saving model to model_checkpoint_best/checkpoint
58605/58605 - 11s - loss: 2.2296 - acc: 0.2041 - val_loss: 2.2204 - val_acc: 0.1942
Epoch 4/30

Epoch 00004: val_loss improved from 2.22045 to 2.02536, saving model to model_checkpoint_best/checkpoint
58605/58605 - 12s - loss: 2.1127 - acc: 0.2650 - val_loss: 2.0254 - val_acc: 0.3120
Epoch 5/30

Epoch 00005: val_loss improved from 2.02536 to 1.79277, saving model to model_checkpoint_best/checkpoint
58605/58605 - 12s - loss: 1.8875 - acc: 0.3522 - val_loss: 1.7928 - val_acc: 0.3871
Epoch 6/30

Epoch 00006: val_loss improved from 1.79277 to 1.66023, saving model to model_checkpoint_best/checkpoint
58605/58605 - 12s - loss: 1.7137 - acc: 0.4130 - val_loss: 1.6602 - val_acc: 0.4245
Epoch 7/30

Epoch 00007: val_loss improved from 1.66023 to 1.48898, saving model to model_checkpoint_best/checkpoint
58605/58605 - 12s - loss: 1.5643 - acc: 0.4673 - val_loss: 1.4890 - val_acc: 0.5033
Epoch 8/30

Epoch 00008: val_loss improved from 1.48898 to 1.40066, saving model to model_checkpoint_best/checkpoint
58605/58605 - 12s - loss: 1.4500 - acc: 0.5164 - val_loss: 1.4007 - val_acc: 0.5422
Epoch 9/30

Epoch 00009: val_loss improved from 1.40066 to 1.31677, saving model to model_checkpoint_best/checkpoint
58605/58605 - 12s - loss: 1.3507 - acc: 0.5580 - val_loss: 1.3168 - val_acc: 0.5691
Epoch 10/30

Epoch 00010: val_loss improved from 1.31677 to 1.29341, saving model to model_checkpoint_best/checkpoint
58605/58605 - 12s - loss: 1.2597 - acc: 0.5926 - val_loss: 1.2934 - val_acc: 0.5814
Epoch 11/30

Epoch 00011: val_loss improved from 1.29341 to 1.22135, saving model to model_checkpoint_best/checkpoint
58605/58605 - 12s - loss: 1.2089 - acc: 0.6117 - val_loss: 1.2214 - val_acc: 0.6146
Epoch 12/30

Epoch 00012: val_loss improved from 1.22135 to 1.21198, saving model to model_checkpoint_best/checkpoint
58605/58605 - 12s - loss: 1.1332 - acc: 0.6400 - val_loss: 1.2120 - val_acc: 0.6176
Epoch 13/30

Epoch 00013: val_loss improved from 1.21198 to 1.16683, saving model to model_checkpoint_best/checkpoint
58605/58605 - 12s - loss: 1.1049 - acc: 0.6517 - val_loss: 1.1668 - val_acc: 0.6304
Epoch 14/30

Epoch 00014: val_loss improved from 1.16683 to 1.14750, saving model to model_checkpoint_best/checkpoint
58605/58605 - 12s - loss: 1.0933 - acc: 0.6567 - val_loss: 1.1475 - val_acc: 0.6452
Epoch 15/30

Epoch 00015: val_loss improved from 1.14750 to 1.03627, saving model to model_checkpoint_best/checkpoint
58605/58605 - 12s - loss: 1.0477 - acc: 0.6714 - val_loss: 1.0363 - val_acc: 0.6768
Epoch 16/30

Epoch 00016: val_loss did not improve from 1.03627
58605/58605 - 12s - loss: 0.9917 - acc: 0.6928 - val_loss: 1.0602 - val_acc: 0.6681
Epoch 17/30

Epoch 00017: val_loss did not improve from 1.03627
58605/58605 - 12s - loss: 0.9927 - acc: 0.6905 - val_loss: 1.0418 - val_acc: 0.6754
Epoch 18/30

Epoch 00018: val_loss improved from 1.03627 to 0.97695, saving model to model_checkpoint_best/checkpoint
58605/58605 - 12s - loss: 0.9472 - acc: 0.7065 - val_loss: 0.9769 - val_acc: 0.7036
Epoch 19/30

Epoch 00019: val_loss improved from 0.97695 to 0.91583, saving model to model_checkpoint_best/checkpoint
58605/58605 - 13s - loss: 0.9193 - acc: 0.7154 - val_loss: 0.9158 - val_acc: 0.7202
Epoch 20/30

Epoch 00020: val_loss did not improve from 0.91583
58605/58605 - 12s - loss: 0.9033 - acc: 0.7193 - val_loss: 0.9922 - val_acc: 0.6899
Epoch 21/30

Epoch 00021: val_loss did not improve from 0.91583
58605/58605 - 12s - loss: 0.9017 - acc: 0.7223 - val_loss: 0.9444 - val_acc: 0.7127
Epoch 22/30

Epoch 00022: val_loss improved from 0.91583 to 0.90364, saving model to model_checkpoint_best/checkpoint
58605/58605 - 12s - loss: 0.8639 - acc: 0.7345 - val_loss: 0.9036 - val_acc: 0.7250
Epoch 23/30

Epoch 00023: val_loss improved from 0.90364 to 0.89663, saving model to model_checkpoint_best/checkpoint
58605/58605 - 12s - loss: 0.8448 - acc: 0.7398 - val_loss: 0.8966 - val_acc: 0.7266
Epoch 24/30

Epoch 00024: val_loss improved from 0.89663 to 0.87524, saving model to model_checkpoint_best/checkpoint
58605/58605 - 12s - loss: 0.8349 - acc: 0.7422 - val_loss: 0.8752 - val_acc: 0.7331
Epoch 25/30

Epoch 00025: val_loss did not improve from 0.87524
58605/58605 - 12s - loss: 0.8235 - acc: 0.7473 - val_loss: 0.9086 - val_acc: 0.7213
Epoch 26/30

Epoch 00026: val_loss did not improve from 0.87524
58605/58605 - 12s - loss: 0.8111 - acc: 0.7508 - val_loss: 1.0186 - val_acc: 0.6868
Epoch 27/30

Epoch 00027: val_loss did not improve from 0.87524
58605/58605 - 12s - loss: 0.8081 - acc: 0.7518 - val_loss: 0.8770 - val_acc: 0.7317
Epoch 28/30

Epoch 00028: val_loss did not improve from 0.87524
58605/58605 - 12s - loss: 0.7933 - acc: 0.7557 - val_loss: 0.9535 - val_acc: 0.7065
Epoch 29/30

Epoch 00029: val_loss did not improve from 0.87524
58605/58605 - 12s - loss: 0.7733 - acc: 0.7621 - val_loss: 0.8862 - val_acc: 0.7366
Finished training!
In [41]:
import pandas as pd
In [42]:
df = pd.DataFrame(history.history)
df.plot(y=["loss","val_loss"])
df.plot(y=["acc","val_acc"])
Out[42]:
<matplotlib.axes._subplots.AxesSubplot at 0x7f8444991a20>
In [43]:
mlp_model.evaluate(test_data_gray, test_targets, verbose=0)
Out[43]:
[0.9823977961339464, 0.71734786]
In [44]:
plt.imshow(test_data_gray[1024])
Out[44]:
<matplotlib.image.AxesImage at 0x7f84457714e0>
In [45]:
np.argmax(mlp_model.predict(test_data_gray[1024][np.newaxis,...]))
Out[45]:
2

3. CNN neural network classifier

  • Build a CNN classifier model using the Sequential API. Your model should use the Conv2D, MaxPool2D, BatchNormalization, Flatten, Dense and Dropout layers. The final layer should again have a 10-way softmax output.
  • You should design and build the model yourself. Feel free to experiment with different CNN architectures. Hint: to achieve a reasonable accuracy you won't need to use more than 2 or 3 convolutional layers and 2 fully connected layers.)
  • The CNN model should use fewer trainable parameters than your MLP model.
  • Compile and train the model (we recommend a maximum of 30 epochs), making use of both training and validation sets during the training run.
  • Your model should track at least one appropriate metric, and use at least two callbacks during training, one of which should be a ModelCheckpoint callback.
  • You should aim to beat the MLP model performance with fewer parameters!
  • Plot the learning curves for loss vs epoch and accuracy vs epoch for both training and validation sets.
  • Compute and display the loss and accuracy of the trained model on the test set.
In [46]:
from tensorflow.keras.layers import Conv2D, MaxPool2D, BatchNormalization, Flatten, Dense, Dropout
In [47]:
def get_cnn_model(input_shape,wd,reg):
    model =  Sequential([
        Conv2D(filters=16, kernel_size=(3,3),activation="relu",input_shape=input_shape,kernel_regularizer=tf.keras.regularizers.l2(reg)),
        Conv2D(filters=8, kernel_size=(3,3), activation="relu"),
        MaxPool2D(pool_size=(3,3)),
        Dropout(wd),
        Dense(units=32, activation="relu"),
        BatchNormalization(),
        Dense(units=32, activation="relu"),
        Flatten(),
        Dense(units=10, activation="softmax")
        
    ])
    model.compile(optimizer="adam", loss="sparse_categorical_crossentropy",metrics=["acc"])
    return model
In [48]:
cnn_model = get_cnn_model(train_data_gray[0][...,np.newaxis].shape, 0.5, 0.01)
cnn_model.summary()
Model: "sequential_2"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv2d (Conv2D)              (None, 30, 30, 16)        160       
_________________________________________________________________
conv2d_1 (Conv2D)            (None, 28, 28, 8)         1160      
_________________________________________________________________
max_pooling2d (MaxPooling2D) (None, 9, 9, 8)           0         
_________________________________________________________________
dropout (Dropout)            (None, 9, 9, 8)           0         
_________________________________________________________________
dense_14 (Dense)             (None, 9, 9, 32)          288       
_________________________________________________________________
batch_normalization (BatchNo (None, 9, 9, 32)          128       
_________________________________________________________________
dense_15 (Dense)             (None, 9, 9, 32)          1056      
_________________________________________________________________
flatten_2 (Flatten)          (None, 2592)              0         
_________________________________________________________________
dense_16 (Dense)             (None, 10)                25930     
=================================================================
Total params: 28,722
Trainable params: 28,658
Non-trainable params: 64
_________________________________________________________________
In [49]:
checkpoint_best_cnn_path = "model_checkpoint_best_cnn/checkpoint"
checkpoint_best = tf.keras.callbacks.ModelCheckpoint(
    filepath=checkpoint_best_cnn_path,
    save_weights_only=True,
    save_best_only=True,
    save_freq="epoch",
    verbose=2
)
earlystoping = tf.keras.callbacks.EarlyStopping(min_delta=0.001,patience=5)
class training_callback(tf.keras.callbacks.Callback):
    def on_train_begin(self, logs=None):
        print("Start training....")
    def on_train_end(self, logs=None):
        print("Finished training!")
In [50]:
history = cnn_model.fit(train_data_gray[...,np.newaxis], train_targets, validation_split=0.2, epochs=30, batch_size=512, verbose=1, 
                    callbacks=[checkpoint_best, earlystoping, training_callback()])
Train on 58605 samples, validate on 14652 samples
Start training....
Epoch 1/30
58368/58605 [============================>.] - ETA: 0s - loss: 1.8555 - acc: 0.3801
Epoch 00001: val_loss improved from inf to 1.57061, saving model to model_checkpoint_best_cnn/checkpoint
58605/58605 [==============================] - 250s 4ms/sample - loss: 1.8541 - acc: 0.3807 - val_loss: 1.5706 - val_acc: 0.4784
Epoch 2/30
58368/58605 [============================>.] - ETA: 0s - loss: 1.1845 - acc: 0.6306
Epoch 00002: val_loss improved from 1.57061 to 1.03491, saving model to model_checkpoint_best_cnn/checkpoint
58605/58605 [==============================] - 241s 4ms/sample - loss: 1.1839 - acc: 0.6309 - val_loss: 1.0349 - val_acc: 0.7184
Epoch 3/30
58368/58605 [============================>.] - ETA: 0s - loss: 0.9825 - acc: 0.6986
Epoch 00003: val_loss improved from 1.03491 to 0.87107, saving model to model_checkpoint_best_cnn/checkpoint
58605/58605 [==============================] - 229s 4ms/sample - loss: 0.9822 - acc: 0.6986 - val_loss: 0.8711 - val_acc: 0.7517
Epoch 4/30
58368/58605 [============================>.] - ETA: 0s - loss: 0.9067 - acc: 0.7223
Epoch 00004: val_loss improved from 0.87107 to 0.75893, saving model to model_checkpoint_best_cnn/checkpoint
58605/58605 [==============================] - 240s 4ms/sample - loss: 0.9065 - acc: 0.7222 - val_loss: 0.7589 - val_acc: 0.7933
Epoch 5/30
58368/58605 [============================>.] - ETA: 0s - loss: 0.8556 - acc: 0.7387
Epoch 00005: val_loss did not improve from 0.75893
58605/58605 [==============================] - 237s 4ms/sample - loss: 0.8550 - acc: 0.7388 - val_loss: 0.7600 - val_acc: 0.7790
Epoch 6/30
58368/58605 [============================>.] - ETA: 0s - loss: 0.8393 - acc: 0.7443
Epoch 00006: val_loss improved from 0.75893 to 0.73237, saving model to model_checkpoint_best_cnn/checkpoint
58605/58605 [==============================] - 235s 4ms/sample - loss: 0.8396 - acc: 0.7444 - val_loss: 0.7324 - val_acc: 0.7849
Epoch 7/30
58368/58605 [============================>.] - ETA: 0s - loss: 0.8105 - acc: 0.7494
Epoch 00007: val_loss improved from 0.73237 to 0.67818, saving model to model_checkpoint_best_cnn/checkpoint
58605/58605 [==============================] - 239s 4ms/sample - loss: 0.8097 - acc: 0.7496 - val_loss: 0.6782 - val_acc: 0.8009
Epoch 8/30
58368/58605 [============================>.] - ETA: 0s - loss: 0.7895 - acc: 0.7603
Epoch 00008: val_loss did not improve from 0.67818
58605/58605 [==============================] - 244s 4ms/sample - loss: 0.7894 - acc: 0.7603 - val_loss: 0.7117 - val_acc: 0.7852
Epoch 9/30
58368/58605 [============================>.] - ETA: 0s - loss: 0.7773 - acc: 0.7626
Epoch 00009: val_loss improved from 0.67818 to 0.67764, saving model to model_checkpoint_best_cnn/checkpoint
58605/58605 [==============================] - 246s 4ms/sample - loss: 0.7774 - acc: 0.7625 - val_loss: 0.6776 - val_acc: 0.8033
Epoch 10/30
58368/58605 [============================>.] - ETA: 0s - loss: 0.7658 - acc: 0.7648
Epoch 00010: val_loss did not improve from 0.67764
58605/58605 [==============================] - 242s 4ms/sample - loss: 0.7661 - acc: 0.7646 - val_loss: 0.6807 - val_acc: 0.7991
Epoch 11/30
58368/58605 [============================>.] - ETA: 0s - loss: 0.7406 - acc: 0.7732
Epoch 00011: val_loss improved from 0.67764 to 0.63230, saving model to model_checkpoint_best_cnn/checkpoint
58605/58605 [==============================] - 240s 4ms/sample - loss: 0.7405 - acc: 0.7733 - val_loss: 0.6323 - val_acc: 0.8146
Epoch 12/30
58368/58605 [============================>.] - ETA: 0s - loss: 0.7261 - acc: 0.7799
Epoch 00012: val_loss did not improve from 0.63230
58605/58605 [==============================] - 244s 4ms/sample - loss: 0.7266 - acc: 0.7797 - val_loss: 0.6641 - val_acc: 0.8026
Epoch 13/30
58368/58605 [============================>.] - ETA: 0s - loss: 0.7013 - acc: 0.7874
Epoch 00013: val_loss did not improve from 0.63230
58605/58605 [==============================] - 240s 4ms/sample - loss: 0.7011 - acc: 0.7875 - val_loss: 0.6443 - val_acc: 0.8103
Epoch 14/30
58368/58605 [============================>.] - ETA: 0s - loss: 0.6964 - acc: 0.7908
Epoch 00014: val_loss improved from 0.63230 to 0.61327, saving model to model_checkpoint_best_cnn/checkpoint
58605/58605 [==============================] - 240s 4ms/sample - loss: 0.6962 - acc: 0.7909 - val_loss: 0.6133 - val_acc: 0.8204
Epoch 15/30
58368/58605 [============================>.] - ETA: 0s - loss: 0.6927 - acc: 0.7900
Epoch 00015: val_loss did not improve from 0.61327
58605/58605 [==============================] - 244s 4ms/sample - loss: 0.6930 - acc: 0.7898 - val_loss: 0.6427 - val_acc: 0.8106
Epoch 16/30
58368/58605 [============================>.] - ETA: 0s - loss: 0.6790 - acc: 0.7946
Epoch 00016: val_loss did not improve from 0.61327
58605/58605 [==============================] - 243s 4ms/sample - loss: 0.6791 - acc: 0.7945 - val_loss: 0.6447 - val_acc: 0.8092
Epoch 17/30
58368/58605 [============================>.] - ETA: 0s - loss: 0.6766 - acc: 0.7960
Epoch 00017: val_loss improved from 0.61327 to 0.61224, saving model to model_checkpoint_best_cnn/checkpoint
58605/58605 [==============================] - 243s 4ms/sample - loss: 0.6764 - acc: 0.7960 - val_loss: 0.6122 - val_acc: 0.8207
Epoch 18/30
58368/58605 [============================>.] - ETA: 0s - loss: 0.6694 - acc: 0.7982
Epoch 00018: val_loss did not improve from 0.61224
58605/58605 [==============================] - 241s 4ms/sample - loss: 0.6693 - acc: 0.7983 - val_loss: 0.6643 - val_acc: 0.8047
Epoch 19/30
58368/58605 [============================>.] - ETA: 0s - loss: 0.6732 - acc: 0.7971
Epoch 00019: val_loss improved from 0.61224 to 0.60660, saving model to model_checkpoint_best_cnn/checkpoint
58605/58605 [==============================] - 242s 4ms/sample - loss: 0.6728 - acc: 0.7972 - val_loss: 0.6066 - val_acc: 0.8223
Epoch 20/30
58368/58605 [============================>.] - ETA: 0s - loss: 0.6659 - acc: 0.7994
Epoch 00020: val_loss did not improve from 0.60660
58605/58605 [==============================] - 241s 4ms/sample - loss: 0.6663 - acc: 0.7992 - val_loss: 0.6254 - val_acc: 0.8160
Epoch 21/30
58368/58605 [============================>.] - ETA: 0s - loss: 0.6514 - acc: 0.8032
Epoch 00021: val_loss did not improve from 0.60660
58605/58605 [==============================] - 239s 4ms/sample - loss: 0.6522 - acc: 0.8029 - val_loss: 0.6388 - val_acc: 0.8118
Epoch 22/30
58368/58605 [============================>.] - ETA: 0s - loss: 0.6592 - acc: 0.8011
Epoch 00022: val_loss did not improve from 0.60660
58605/58605 [==============================] - 238s 4ms/sample - loss: 0.6590 - acc: 0.8011 - val_loss: 0.6508 - val_acc: 0.8066
Epoch 23/30
58368/58605 [============================>.] - ETA: 0s - loss: 0.6558 - acc: 0.8002
Epoch 00023: val_loss improved from 0.60660 to 0.60656, saving model to model_checkpoint_best_cnn/checkpoint
58605/58605 [==============================] - 238s 4ms/sample - loss: 0.6558 - acc: 0.8002 - val_loss: 0.6066 - val_acc: 0.8219
Epoch 24/30
58368/58605 [============================>.] - ETA: 0s - loss: 0.6434 - acc: 0.8073
Epoch 00024: val_loss improved from 0.60656 to 0.60267, saving model to model_checkpoint_best_cnn/checkpoint
58605/58605 [==============================] - 235s 4ms/sample - loss: 0.6440 - acc: 0.8071 - val_loss: 0.6027 - val_acc: 0.8228
Epoch 25/30
58368/58605 [============================>.] - ETA: 0s - loss: 0.6519 - acc: 0.8023
Epoch 00025: val_loss did not improve from 0.60267
58605/58605 [==============================] - 239s 4ms/sample - loss: 0.6515 - acc: 0.8023 - val_loss: 0.8419 - val_acc: 0.7458
Epoch 26/30
58368/58605 [============================>.] - ETA: 0s - loss: 0.6432 - acc: 0.8051
Epoch 00026: val_loss did not improve from 0.60267
58605/58605 [==============================] - 236s 4ms/sample - loss: 0.6433 - acc: 0.8050 - val_loss: 0.6811 - val_acc: 0.7974
Epoch 27/30
58368/58605 [============================>.] - ETA: 0s - loss: 0.6389 - acc: 0.8075
Epoch 00027: val_loss improved from 0.60267 to 0.60197, saving model to model_checkpoint_best_cnn/checkpoint
58605/58605 [==============================] - 236s 4ms/sample - loss: 0.6394 - acc: 0.8075 - val_loss: 0.6020 - val_acc: 0.8204
Epoch 28/30
58368/58605 [============================>.] - ETA: 0s - loss: 0.6321 - acc: 0.8090
Epoch 00028: val_loss did not improve from 0.60197
58605/58605 [==============================] - 236s 4ms/sample - loss: 0.6320 - acc: 0.8091 - val_loss: 0.6577 - val_acc: 0.8045
Epoch 29/30
58368/58605 [============================>.] - ETA: 0s - loss: 0.6304 - acc: 0.8099
Epoch 00029: val_loss did not improve from 0.60197
58605/58605 [==============================] - 236s 4ms/sample - loss: 0.6305 - acc: 0.8098 - val_loss: 0.6363 - val_acc: 0.8088
Finished training!
In [51]:
df = pd.DataFrame(history.history)
df.plot(y=["loss","val_loss"])
df.plot(y=["acc","val_acc"])
Out[51]:
<matplotlib.axes._subplots.AxesSubplot at 0x7f842c0b04a8>
In [ ]:
 
In [52]:
del mlp_model, cnn_model

4. Get model predictions

  • Load the best weights for the MLP and CNN models that you saved during the training run.
  • Randomly select 5 images and corresponding labels from the test set and display the images with their labels.
  • Alongside the image and label, show each model’s predictive distribution as a bar chart, and the final model prediction given by the label with maximum probability.
In [53]:
mlp_model = get_new_model(train_data_gray[0].shape)
cnn_model = get_cnn_model(train_data_gray[0][...,np.newaxis].shape, 0.5, 0.001)
In [54]:
mlp_model.load_weights("model_checkpoint_best/checkpoint")
mlp_model.summary()
Model: "sequential_3"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
flatten_3 (Flatten)          (None, 1024)              0         
_________________________________________________________________
dense_17 (Dense)             (None, 128)               131200    
_________________________________________________________________
dense_18 (Dense)             (None, 128)               16512     
_________________________________________________________________
dense_19 (Dense)             (None, 128)               16512     
_________________________________________________________________
dense_20 (Dense)             (None, 64)                8256      
_________________________________________________________________
dense_21 (Dense)             (None, 64)                4160      
_________________________________________________________________
dense_22 (Dense)             (None, 64)                4160      
_________________________________________________________________
dense_23 (Dense)             (None, 10)                650       
=================================================================
Total params: 181,450
Trainable params: 181,450
Non-trainable params: 0
_________________________________________________________________
In [55]:
cnn_model.load_weights("model_checkpoint_best_cnn/checkpoint")
cnn_model.summary()
Model: "sequential_4"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv2d_2 (Conv2D)            (None, 30, 30, 16)        160       
_________________________________________________________________
conv2d_3 (Conv2D)            (None, 28, 28, 8)         1160      
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 9, 9, 8)           0         
_________________________________________________________________
dropout_1 (Dropout)          (None, 9, 9, 8)           0         
_________________________________________________________________
dense_24 (Dense)             (None, 9, 9, 32)          288       
_________________________________________________________________
batch_normalization_1 (Batch (None, 9, 9, 32)          128       
_________________________________________________________________
dense_25 (Dense)             (None, 9, 9, 32)          1056      
_________________________________________________________________
flatten_4 (Flatten)          (None, 2592)              0         
_________________________________________________________________
dense_26 (Dense)             (None, 10)                25930     
=================================================================
Total params: 28,722
Trainable params: 28,658
Non-trainable params: 64
_________________________________________________________________
In [59]:
random_idx = np.random.choice(test_data.shape[0], 5)
random_test_data_gray = test_data_gray[random_idx, ...]
random_test_data = test_data_gray[random_idx, ...]
random_test_targets = test_targets[random_idx,...]
In [60]:
mlp_predictions = mlp_model.predict(random_test_data_gray)
fig, axes = plt.subplots(5, 2, figsize=(16, 12))
fig.subplots_adjust(hspace=0.4,wspace=-0.2)
for i, (prediction, image, label) in enumerate(zip(mlp_predictions, random_test_data, random_test_targets)):
    axes[i, 0].imshow(np.squeeze(image))
    axes[i, 0].get_xaxis().set_visible(False)
    axes[i, 0].get_yaxis().set_visible(False)
    axes[i, 0].text(10, -1.5, f"Digit {label}")
    axes[i, 1].bar(np.arange(0, 10), prediction)
    axes[i, 1].set_xticks(np.arange(0, 10))
    axes[i, 1].set_title("Categorical distribution. Model prediction")
plt.show()
In [61]:
cnn_predictions = cnn_model.predict(random_test_data_gray[...,np.newaxis])
fig, axes = plt.subplots(5, 2, figsize=(16, 12))
fig.subplots_adjust(hspace=0.4,wspace=-0.2)
for i, (prediction, image, label) in enumerate(zip(cnn_predictions, random_test_data, random_test_targets)):
    axes[i, 0].imshow(np.squeeze(image))
    axes[i, 0].get_xaxis().set_visible(False)
    axes[i, 0].get_yaxis().set_visible(False)
    axes[i, 0].text(10, -1.5, f"Digit {label}")
    axes[i, 1].bar(np.arange(0, 10), prediction)
    axes[i, 1].set_xticks(np.arange(0, 10))
    axes[i, 1].set_title("Categorical distribution. Model prediction")
plt.show()
In [ ]: