In [1]:
import tensorflow as tf

# Importing matplotlib to plot images.
import matplotlib.pyplot as plt
import numpy as np
%matplotlib inline

# Importing SK-learn to calculate precision and recall
import sklearn
import sklearn.metrics

# Used for graph export
from tensorflow.python.framework import graph_util
from tensorflow.python.framework import graph_io
from keras.models import load_model
from keras import backend as K

tf.__version__


/usr/local/lib/python3.6/dist-packages/h5py/__init__.py:36: FutureWarning: Conversion of the second argument of issubdtype from `float` to `np.floating` is deprecated. In future, it will be treated as `np.float64 == np.dtype(float).type`.
  from ._conv import register_converters as _register_converters
Using TensorFlow backend.
Out[1]:
'1.5.0'

In [2]:
# the data, split between train and test sets
(x_train, y_train), (x_test, y_test) = tf.keras.datasets.mnist.load_data()

In [3]:
# flatten image data <- NOT FOR CNN
#x_train = x_train.reshape(-1, 784)
#x_test = x_test.reshape(-1, 784)

# For CNNs  ->
###   DIFFERENT RESHAPE  ### 
### We here need the dimensions of the image plus a channel, e.g. for RGB images one have 3 channels ###
x_train = x_train.reshape(-1, 28, 28, 1)
x_test = x_test.reshape(-1, 28, 28, 1)

# convert to float
x_train = x_train.astype(np.float32)
x_test = x_test.astype(np.float32)

# normalize to a scale between 0 and 1
x_train /= 255
x_test /= 255

print(x_train.shape[0], 'train samples')
print(x_test.shape[0], 'test samples')

# convert class vectors to binary class matrices (one-hot notation)
num_classes = 10
y_train_one_hot = tf.keras.utils.to_categorical(y_train, num_classes)
y_test_one_hot = tf.keras.utils.to_categorical(y_test, num_classes)


60000 train samples
10000 test samples

In [4]:
i = 31
plt.imshow(x_train[i].reshape(28, 28)) #np.sqrt(784) = 28
plt.title("Label for image %i is: %s" % (i, np.argmax(y_train[i])))


Out[4]:
Text(0.5,1,'Label for image 31 is: 0')

GPU and CPU settings

If GPU is not available, comment out the bottom block.


In [5]:
# If GPU is not available: 
# GPU_USE = '/cpu:0'
# config = tf.ConfigProto(device_count = {"GPU": 0})


# If GPU is available: 
config = tf.ConfigProto()
config.log_device_placement = True
config.allow_soft_placement = True
config.gpu_options.allocator_type = 'BFC'

# Limit the maximum memory used
config.gpu_options.per_process_gpu_memory_fraction = 0.1

# set session config
tf.keras.backend.set_session(tf.Session(config=config))

In [6]:
########## HYPER PARAMETERS
batch_size = 128
epochs = 10
optimizer = tf.keras.optimizers.RMSprop()
########## HYPER PARAMETERS

########## MODEL ARCHITECTURE
model = tf.keras.Sequential()

### OLD ARCHITECTURE START
#model.add(tf.keras.layers.Dense(5, activation='relu', input_shape=(784,)))
### OLD ARCHITECTURE END

### NEW CNN ARCHITECTURE
model.add(tf.keras.layers.Conv2D(5, kernel_size=(3, 3), activation='relu', input_shape=(28,28,1)))
model.add(tf.keras.layers.Flatten())
### NEW CNN ARCHITECTURE

model.add(tf.keras.layers.Dense(num_classes, activation='softmax'))
########## MODEL ARCHITECTURE

# Print summary
model.summary()

# compile model for training
model.compile(loss='categorical_crossentropy',
              optimizer=optimizer,
              metrics=['accuracy'])

history = model.fit(x_train, y_train_one_hot,
                    batch_size=batch_size,
                    epochs=epochs,
                    verbose=1,
                    validation_data=(x_test, y_test_one_hot))


_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv2d_1 (Conv2D)            (None, 26, 26, 5)         50        
_________________________________________________________________
flatten_1 (Flatten)          (None, 3380)              0         
_________________________________________________________________
dense_1 (Dense)              (None, 10)                33810     
=================================================================
Total params: 33,860
Trainable params: 33,860
Non-trainable params: 0
_________________________________________________________________
WARNING:tensorflow:From /usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/_impl/keras/backend.py:3086: calling reduce_sum (from tensorflow.python.ops.math_ops) with keep_dims is deprecated and will be removed in a future version.
Instructions for updating:
keep_dims is deprecated, use keepdims instead
WARNING:tensorflow:From /usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/_impl/keras/backend.py:1557: calling reduce_mean (from tensorflow.python.ops.math_ops) with keep_dims is deprecated and will be removed in a future version.
Instructions for updating:
keep_dims is deprecated, use keepdims instead
Train on 60000 samples, validate on 10000 samples
Epoch 1/10
60000/60000 [==============================]60000/60000 [==============================] - 4s 74us/step - loss: 0.4256 - acc: 0.8893 - val_loss: 0.2530 - val_acc: 0.9284

Epoch 2/10
60000/60000 [==============================]60000/60000 [==============================] - 3s 43us/step - loss: 0.2210 - acc: 0.9368 - val_loss: 0.1785 - val_acc: 0.9538

Epoch 3/10
60000/60000 [==============================]60000/60000 [==============================] - 3s 44us/step - loss: 0.1500 - acc: 0.9581 - val_loss: 0.1331 - val_acc: 0.9625

Epoch 4/10
60000/60000 [==============================]60000/60000 [==============================] - 3s 44us/step - loss: 0.1137 - acc: 0.9689 - val_loss: 0.1072 - val_acc: 0.9702

Epoch 5/10
60000/60000 [==============================]60000/60000 [==============================] - 3s 44us/step - loss: 0.0940 - acc: 0.9736 - val_loss: 0.0935 - val_acc: 0.9724

Epoch 6/10
60000/60000 [==============================]60000/60000 [==============================] - 3s 44us/step - loss: 0.0816 - acc: 0.9770 - val_loss: 0.0849 - val_acc: 0.9742

Epoch 7/10
60000/60000 [==============================]60000/60000 [==============================] - 3s 44us/step - loss: 0.0725 - acc: 0.9797 - val_loss: 0.0803 - val_acc: 0.9759

Epoch 8/10
60000/60000 [==============================]60000/60000 [==============================] - 3s 44us/step - loss: 0.0657 - acc: 0.9812 - val_loss: 0.0748 - val_acc: 0.9763

Epoch 9/10
60000/60000 [==============================]60000/60000 [==============================] - 3s 44us/step - loss: 0.0606 - acc: 0.9826 - val_loss: 0.0701 - val_acc: 0.9775

Epoch 10/10
60000/60000 [==============================]60000/60000 [==============================] - 3s 44us/step - loss: 0.0558 - acc: 0.9844 - val_loss: 0.0689 - val_acc: 0.9772

Plot training and test accuracy


In [7]:
# use model for inference to get test accuracy
y_test_pred = model.predict(x_test)
y_test_pred = np.argmax(y_test_pred, axis=1)

print ('\n Summary of the precision, recall, F1 score for each class:')
print (sklearn.metrics.classification_report(y_test, y_test_pred))

print ('\n Confusion matrix: ')
print (sklearn.metrics.confusion_matrix(y_test, y_test_pred))


 Summary of the precision, recall, F1 score for each class:
             precision    recall  f1-score   support

          0       0.98      0.98      0.98       980
          1       0.99      1.00      0.99      1135
          2       0.97      0.97      0.97      1032
          3       0.98      0.98      0.98      1010
          4       0.98      0.98      0.98       982
          5       0.99      0.97      0.98       892
          6       0.98      0.98      0.98       958
          7       0.98      0.96      0.97      1028
          8       0.96      0.97      0.96       974
          9       0.97      0.97      0.97      1009

avg / total       0.98      0.98      0.98     10000


 Confusion matrix: 
[[ 965    0    1    0    0    1    6    3    4    0]
 [   0 1130    4    0    0    0    1    0    0    0]
 [   2    5 1001    2    2    0    1    7    9    3]
 [   0    0    2  988    0    4    0    4   11    1]
 [   1    1    2    0  963    0    1    0    3   11]
 [   2    1    2   11    0  867    5    1    3    0]
 [   5    2    1    1    5    2  938    0    4    0]
 [   1    3   13    3    0    0    0  992    5   11]
 [   5    0    4    2    3    0    2    4  946    8]
 [   3    5    1    0    6    2    0    5    5  982]]

In [8]:
import matplotlib.pyplot as plt
plt.plot(history.history['val_acc'], label="Test Accuracy")
plt.plot(history.history['acc'], label="Training Accuracy")
plt.legend()


Out[8]:
<matplotlib.legend.Legend at 0x7fe81c071b38>

In [9]:
# save model
model.save("myModel.h5")