Cainvas
Model Files
mnist.zip
TensorFlow
Model
deepSea Compiled Models
mnist.exe
deepSea
Ubuntu

Quick Start

Credit: AITS Cainvas Community

Photo by Sandipan Dey on SandipanWeb

  1. Use MNIST Dataset,
  2. To Train NN model with TensorFlow-Keras and
  3. Compile NN model with deepC

To run a Code Cell you can click on the ⏯ Run button in the Navigation Bar above or type Shift + Enter

In [1]:
# TensorFlow and tf.keras
import tensorflow as tf
from tensorflow import keras

# Helper libraries
import numpy as np
import matplotlib.pyplot as plt

# Get some knowledge about current environment 
print("TensorFlow version {}".format(tf.__version__))
print("Eager mode: ", tf.executing_eagerly())
print("Is GPU available: ",tf.config.list_physical_devices('GPU'))
TensorFlow version 2.2.0
Eager mode:  True
Is GPU available:  []

Load MNIST dataset:

In [2]:
mnist = tf.keras.datasets.mnist
(images_train, labels_train),(images_test, labels_test) = mnist.load_data()
class_names = ["zero","one","two","three","four","five","six","seven","eight","nine"]

What is our training data?

Training images

In [3]:
print("Data type:", type(images_train))
print("Dataset shape:", (images_train.shape))
Data type: <class 'numpy.ndarray'>
Dataset shape: (60000, 28, 28)

It means that we get array of 60000 images for training, 28x28 pixels each.

Labels

In [4]:
print("Labels:", len(labels_train))
print("Possible values:", np.unique(labels_train))
Labels: 60000
Possible values: [0 1 2 3 4 5 6 7 8 9]

Example image

In [5]:
plt.figure()
plt.imshow(images_train[0])
plt.colorbar()
plt.grid(False)
plt.xlabel("Classification label: {}".format(labels_train[0]))
plt.show()

Normalization

Each cell (pixel) can have value from 0 to 255 like it's presented above. Let's scale it to float value between 0 and 1:

In [6]:
images_train = images_train / 255.0
images_test = images_test / 255.0
In [7]:
plt.figure()
plt.imshow(images_train[0])
plt.colorbar()
plt.grid(False)
plt.xlabel("Classification label: {}".format(labels_train[0]))
plt.show()

Note

It is worth mentioning that input images are inverted (white number on black background). MNIST data is prepared in a way where the smaller pixel's value is, the whiter it is (0 means 100% white, 255 means 100% black).

It's important because when you plug in model to an Android app, you will need to prepare input image in the same way (scale down and inverse colors).

In [8]:
plt.figure(figsize=(10, 10))

plt.subplot(3, 6, 1)
plt.xticks([])
plt.yticks([])
plt.xlabel("Inverse")
plt.imshow(images_train[0], cmap=plt.cm.binary)

plt.subplot(3, 6, 2)
plt.xticks([])
plt.yticks([])
plt.xlabel("Original")
plt.imshow(images_train[0], cmap=plt.cm.gray)
Out[8]:
<matplotlib.image.AxesImage at 0x7f2db6946f60>

NN Model Creation

In [9]:
model = keras.models.Sequential([
  keras.layers.Flatten(input_shape=(28,28), name="flat_1"),
  keras.layers.Dense(100, activation=tf.nn.relu, name="dense_1"),
  keras.layers.Dropout(0.2, name="dropout_1"),
  keras.layers.Dense(10, activation=tf.nn.softmax, name="dense_2")
])

model.compile(optimizer='adam',
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy'])

Display NN Model Architecture

In [10]:
model.summary()
Model: "sequential"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
flat_1 (Flatten)             (None, 784)               0         
_________________________________________________________________
dense_1 (Dense)              (None, 100)               78500     
_________________________________________________________________
dropout_1 (Dropout)          (None, 100)               0         
_________________________________________________________________
dense_2 (Dense)              (None, 10)                1010      
=================================================================
Total params: 79,510
Trainable params: 79,510
Non-trainable params: 0
_________________________________________________________________
In [11]:
tf.keras.utils.plot_model(
    model, to_file='model.png', show_shapes=False, show_layer_names=True,
    rankdir='TB', expand_nested=False, dpi=96
)
Failed to import pydot. You must install pydot and graphviz for `pydotprint` to work.

Model training

In [12]:
model.fit(images_train, labels_train, epochs=16)
Epoch 1/16
1875/1875 [==============================] - 3s 2ms/step - loss: 0.3163 - accuracy: 0.9079
Epoch 2/16
1875/1875 [==============================] - 3s 2ms/step - loss: 0.1572 - accuracy: 0.9540
Epoch 3/16
1875/1875 [==============================] - 3s 2ms/step - loss: 0.1202 - accuracy: 0.9639
Epoch 4/16
1875/1875 [==============================] - 3s 2ms/step - loss: 0.1002 - accuracy: 0.9683
Epoch 5/16
1875/1875 [==============================] - 3s 2ms/step - loss: 0.0871 - accuracy: 0.9726
Epoch 6/16
1875/1875 [==============================] - 3s 2ms/step - loss: 0.0789 - accuracy: 0.9751
Epoch 7/16
1875/1875 [==============================] - 3s 2ms/step - loss: 0.0704 - accuracy: 0.9769
Epoch 8/16
1875/1875 [==============================] - 3s 2ms/step - loss: 0.0647 - accuracy: 0.9789
Epoch 9/16
1875/1875 [==============================] - 3s 2ms/step - loss: 0.0599 - accuracy: 0.9803
Epoch 10/16
1875/1875 [==============================] - 3s 2ms/step - loss: 0.0562 - accuracy: 0.9822
Epoch 11/16
1875/1875 [==============================] - 4s 2ms/step - loss: 0.0516 - accuracy: 0.9828
Epoch 12/16
1875/1875 [==============================] - 4s 2ms/step - loss: 0.0486 - accuracy: 0.9834
Epoch 13/16
1875/1875 [==============================] - 4s 2ms/step - loss: 0.0457 - accuracy: 0.9854
Epoch 14/16
1875/1875 [==============================] - 4s 2ms/step - loss: 0.0428 - accuracy: 0.9852
Epoch 15/16
1875/1875 [==============================] - 4s 2ms/step - loss: 0.0424 - accuracy: 0.9857
Epoch 16/16
1875/1875 [==============================] - 4s 2ms/step - loss: 0.0396 - accuracy: 0.9866
Out[12]:
<tensorflow.python.keras.callbacks.History at 0x7f2db37c8f60>
In [13]:
test_loss, test_acc = model.evaluate(images_test, labels_test)
print('Test accuracy:', test_acc)
313/313 [==============================] - 0s 1ms/step - loss: 0.0827 - accuracy: 0.9786
Test accuracy: 0.978600025177002

Model evaluation

Let's take one image from the test set:

In [14]:
example_img = images_test[0]
np.savetxt('img.data', example_img.flatten())
In [15]:
plt.grid(False)
plt.xticks([])
plt.yticks([])
plt.imshow(example_img, cmap=plt.cm.binary)
Out[15]:
<matplotlib.image.AxesImage at 0x7f2db690e278>

Prediction

What does our prediction say?

In [16]:
example_img_as_input = (np.expand_dims(example_img,0))
print("Image data shape:", example_img_as_input.shape)

img_prediction = model.predict(example_img_as_input)
print("Prediction results:", img_prediction)
print("Predicted value:", np.argmax(img_prediction))
Image data shape: (1, 28, 28)
Prediction results: [[6.0636310e-14 3.3449077e-14 1.3840585e-09 8.1805888e-07 6.1923621e-17
  7.8311892e-11 4.4201749e-21 9.9999917e-01 7.1050221e-10 1.2801432e-08]]
Predicted value: 7

Visualise more predictions. Plot the first X test images, their predicted label, and the true label. Color correct predictions in blue, incorrect predictions in red.

In [17]:
# Helper functions

import matplotlib.pyplot as plt
import numpy as np


def plot_image(i, predictions_array, true_label, img, class_names):
    predictions_array, true_label, img = predictions_array[i], true_label[i], img[i]
    plt.grid(False)
    plt.xticks([])
    plt.yticks([])

    plt.imshow(img, cmap=plt.cm.binary)

    predicted_label = np.argmax(predictions_array)
    if predicted_label == true_label:
        color = 'blue'
    else:
        color = 'red'

    plt.xlabel("{} {:2.0f}% ({})".format(class_names[predicted_label],
                                         100 * np.max(predictions_array),
                                         class_names[true_label]),
               color=color)


def plot_value_array(i, predictions_array, true_label):
    predictions_array, true_label = predictions_array[i], true_label[i]
    plt.grid(False)
    plt.xticks([])
    plt.yticks([])
    thisplot = plt.bar(range(10), predictions_array, color="#777777")
    plt.ylim([0, 1])
    predicted_label = np.argmax(predictions_array)

    thisplot[predicted_label].set_color('red')
    thisplot[true_label].set_color('blue')
In [18]:
predictions = model.predict(images_test)

num_rows = 5
num_cols = 3
num_images = num_rows*num_cols
plt.figure(figsize=(2  *2*num_cols, 2*num_rows))
for i in range(num_images):
  plt.subplot(num_rows, 2*num_cols, 2*i+1)
  plot_image(i, predictions, labels_test, images_test, class_names)
  # plt.subplot(num_rows, 2*num_cols, 2*i+2)
  # plot_value_array(i, predictions, labels_test)

Test Accuracy

In [19]:
loss, acc = model.evaluate(images_test, labels_test)
print("Restored model, accuracy: {:5.2f}%".format(100*acc))
print("Restored model, loss: {}".format(loss))
313/313 [==============================] - 0s 1ms/step - loss: 0.0827 - accuracy: 0.9786
Restored model, accuracy: 97.86%
Restored model, loss: 0.08273264020681381

Save Model

  1. TF PB format
  2. TF Lite format
  3. TF Lite Quantized
In [20]:
saved_model_dir = 'mnist_model.TF'
model.save(saved_model_dir)
WARNING:tensorflow:From /opt/tljh/user/lib/python3.7/site-packages/tensorflow/python/ops/resource_variable_ops.py:1817: calling BaseResourceVariable.__init__ (from tensorflow.python.ops.resource_variable_ops) with constraint is deprecated and will be removed in a future version.
Instructions for updating:
If using Keras pass *_constraint arguments to layers.
INFO:tensorflow:Assets written to: mnist_model.TF/assets
In [21]:
tflite_model_file = "converted_model.tflite"
converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir)
tflite_model = converter.convert()
open(tflite_model_file, "wb").write(tflite_model)
Out[21]:
319904
In [22]:
tflite_quantized_model_file = "converted_quantized_model.tflite"
converter.optimizations = [tf.lite.Optimize.DEFAULT]
tflite_quantized_model = converter.convert()
open(tflite_quantized_model_file, "wb").write(tflite_quantized_model)
Out[22]:
84880
In [23]:
!deepCC mnist_model.TF --format=tensorflow
reading [tensorflow model] from 'mnist_model.TF'
Saved 'mnist_model.TF.onnx'
reading onnx model from file  mnist_model.TF.onnx
Model info:
  ir_vesion :  4 
  doc       : 
WARN (ONNX): terminal (input/output) flat_1_input_0's shape is less than 1.
             changing it to 1.
WARN (ONNX): terminal (input/output) Identity_0's shape is less than 1.
             changing it to 1.
running DNNC graph sanity check ... passed.
Writing C++ file  mnist_model.TF_deepC/mnist_model.TF.cpp
INFO (ONNX): model files are ready in dir mnist_model.TF_deepC
g++ -O3 -I. -I/opt/tljh/user/lib/python3.7/site-packages/deepC-0.13-py3.7-linux-x86_64.egg/deepC/include -isystem /opt/tljh/user/lib/python3.7/site-packages/deepC-0.13-py3.7-linux-x86_64.egg/deepC/packages/eigen-eigen-323c052e1731 mnist_model.TF_deepC/mnist_model.TF.cpp -o mnist_model.TF_deepC/mnist_model.TF.exe
Model executable  mnist_model.TF_deepC/mnist_model.TF.exe
In [24]:
!./mnist_model.TF_deepC/mnist_model.TF.exe img.data
reading file img.data.
writing file Identity_0.out.
In [25]:
nn_out = np.loadtxt('Identity_0.out')
print ("Model prediction is DIGIT : ", np.argmax(nn_out))
Model prediction is DIGIT :  7