Machine Learning Engineer Nanodegree

Deep Learning

📑   Practice Project 4: Convolutional Neural Networks

In this notebook, we train an MLP to classify images from the CIFAR-10 database.

1. Load CIFAR-10 Database

In [1]:
%%html
<style>
@import url('https://fonts.googleapis.com/css?family=Orbitron|Roboto');
body {background-color: #add8e6;} 
a {color: darkblue; font-family: 'Roboto';} 
h1 {color: steelblue; font-family: 'Orbitron'; text-shadow: 4px 4px 4px #aaa;} 
h2, h3 {color: #483d8b; font-family: 'Orbitron'; text-shadow: 4px 4px 4px #aaa;}
h4 {color: slategray; font-family: 'Roboto';}
span {text-shadow: 4px 4px 4px #ccc;}
div.output_prompt, div.output_area pre {color: #483d8b;}
div.input_prompt, div.output_subarea {color: darkblue;}      
div.output_stderr pre {background-color: #add8e6;}  
div.output_stderr {background-color: #483d8b;}        
</style>
In [2]:
import keras
from keras.datasets import cifar10

# load the pre-shuffled train and test data
(x_train, y_train), (x_test, y_test) = cifar10.load_data()
Using TensorFlow backend.

2. Visualize the First 24 Training Images

In [3]:
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline

fig = plt.figure(figsize=(20,5))
for i in range(36):
    ax = fig.add_subplot(3, 12, i + 1, xticks=[], yticks=[])
    ax.imshow(np.squeeze(x_train[i]))

3. Rescale the Images by Dividing Every Pixel in Every Image by 255

In [4]:
# rescale [0,255] --> [0,1]
x_train = x_train.astype('float32')/255
x_test = x_test.astype('float32')/255 

4. Break Dataset into Training, Testing, and Validation Sets

In [5]:
from keras.utils import np_utils

# one-hot encode the labels
num_classes = len(np.unique(y_train))
y_train = keras.utils.to_categorical(y_train, num_classes)
y_test = keras.utils.to_categorical(y_test, num_classes)

# break training set into training and validation sets
(x_train, x_valid) = x_train[5000:], x_train[:5000]
(y_train, y_valid) = y_train[5000:], y_train[:5000]

# print shape of training set
print('x_train shape:', x_train.shape)

# print number of training, validation, and test images
print(x_train.shape[0], 'train samples')
print(x_test.shape[0], 'test samples')
print(x_valid.shape[0], 'validation samples')
x_train shape: (45000, 32, 32, 3)
45000 train samples
10000 test samples
5000 validation samples

5. Define the Model Architecture

In [6]:
from keras.models import Sequential
from keras.layers import Dense, Dropout, Flatten

# define the model
model = Sequential()
model.add(Flatten(input_shape = x_train.shape[1:]))
model.add(Dense(1000, activation='relu'))
model.add(Dropout(0.2))
model.add(Dense(512, activation='relu'))
model.add(Dropout(0.2))
model.add(Dense(num_classes, activation='softmax'))

model.summary()
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
flatten_1 (Flatten)          (None, 3072)              0         
_________________________________________________________________
dense_1 (Dense)              (None, 1000)              3073000   
_________________________________________________________________
dropout_1 (Dropout)          (None, 1000)              0         
_________________________________________________________________
dense_2 (Dense)              (None, 512)               512512    
_________________________________________________________________
dropout_2 (Dropout)          (None, 512)               0         
_________________________________________________________________
dense_3 (Dense)              (None, 10)                5130      
=================================================================
Total params: 3,590,642
Trainable params: 3,590,642
Non-trainable params: 0
_________________________________________________________________

6. Compile the Model

In [7]:
# compile the model
model.compile(loss='categorical_crossentropy', optimizer='rmsprop', 
                  metrics=['accuracy'])

7. Train the Model

In [8]:
from keras.callbacks import ModelCheckpoint   

# train the model
checkpointer = ModelCheckpoint(filepath='MLP.weights.best.hdf5', verbose=1, 
                               save_best_only=True)
hist = model.fit(x_train, y_train, batch_size=32, epochs=20,
          validation_data=(x_valid, y_valid), callbacks=[checkpointer], 
          verbose=2, shuffle=True)
Train on 45000 samples, validate on 5000 samples
Epoch 1/20
Epoch 00000: val_loss improved from inf to 2.15134, saving model to MLP.weights.best.hdf5
123s - loss: 2.1609 - acc: 0.2718 - val_loss: 2.1513 - val_acc: 0.2664
Epoch 2/20
Epoch 00001: val_loss improved from 2.15134 to 1.83867, saving model to MLP.weights.best.hdf5
128s - loss: 1.8507 - acc: 0.3297 - val_loss: 1.8387 - val_acc: 0.3506
Epoch 3/20
Epoch 00002: val_loss improved from 1.83867 to 1.76270, saving model to MLP.weights.best.hdf5
129s - loss: 1.8051 - acc: 0.3514 - val_loss: 1.7627 - val_acc: 0.3614
Epoch 4/20
Epoch 00003: val_loss improved from 1.76270 to 1.71057, saving model to MLP.weights.best.hdf5
134s - loss: 1.7839 - acc: 0.3621 - val_loss: 1.7106 - val_acc: 0.3824
Epoch 5/20
Epoch 00004: val_loss improved from 1.71057 to 1.69024, saving model to MLP.weights.best.hdf5
126s - loss: 1.7718 - acc: 0.3677 - val_loss: 1.6902 - val_acc: 0.3980
Epoch 6/20
Epoch 00005: val_loss did not improve
132s - loss: 1.7608 - acc: 0.3715 - val_loss: 1.7071 - val_acc: 0.3854
Epoch 7/20
Epoch 00006: val_loss improved from 1.69024 to 1.65185, saving model to MLP.weights.best.hdf5
135s - loss: 1.7564 - acc: 0.3770 - val_loss: 1.6519 - val_acc: 0.4106
Epoch 8/20
Epoch 00007: val_loss did not improve
126s - loss: 1.7623 - acc: 0.3782 - val_loss: 1.7093 - val_acc: 0.3998
Epoch 9/20
Epoch 00008: val_loss did not improve
133s - loss: 1.7594 - acc: 0.3786 - val_loss: 1.7448 - val_acc: 0.3716
Epoch 10/20
Epoch 00009: val_loss did not improve
131s - loss: 1.7602 - acc: 0.3760 - val_loss: 1.6682 - val_acc: 0.4122
Epoch 11/20
Epoch 00010: val_loss did not improve
135s - loss: 1.7605 - acc: 0.3810 - val_loss: 1.6712 - val_acc: 0.4106
Epoch 12/20
Epoch 00011: val_loss did not improve
136s - loss: 1.7609 - acc: 0.3823 - val_loss: 1.6906 - val_acc: 0.3850
Epoch 13/20
Epoch 00012: val_loss did not improve
131s - loss: 1.7605 - acc: 0.3810 - val_loss: 1.7001 - val_acc: 0.3932
Epoch 14/20
Epoch 00013: val_loss did not improve
135s - loss: 1.7632 - acc: 0.3766 - val_loss: 1.7886 - val_acc: 0.3718
Epoch 15/20
Epoch 00014: val_loss did not improve
133s - loss: 1.7709 - acc: 0.3732 - val_loss: 1.6947 - val_acc: 0.3970
Epoch 16/20
Epoch 00015: val_loss did not improve
135s - loss: 1.7808 - acc: 0.3722 - val_loss: 1.6813 - val_acc: 0.4072
Epoch 17/20
Epoch 00016: val_loss did not improve
120s - loss: 1.7787 - acc: 0.3788 - val_loss: 1.8042 - val_acc: 0.3452
Epoch 18/20
Epoch 00017: val_loss did not improve
125s - loss: 1.7833 - acc: 0.3780 - val_loss: 1.6720 - val_acc: 0.4138
Epoch 19/20
Epoch 00018: val_loss did not improve
126s - loss: 1.7762 - acc: 0.3785 - val_loss: 1.7488 - val_acc: 0.3774
Epoch 20/20
Epoch 00019: val_loss did not improve
122s - loss: 1.7828 - acc: 0.3719 - val_loss: 1.7936 - val_acc: 0.3638

8. Load the Model with the Best Classification Accuracy on the Validation Set

In [9]:
# load the weights that yielded the best validation accuracy
model.load_weights('MLP.weights.best.hdf5')

9. Calculate Classification Accuracy on Test Set

In [10]:
# evaluate and print test accuracy
score = model.evaluate(x_test, y_test, verbose=0)
print('\n', 'Test accuracy:', score[1])
 Test accuracy: 0.4128