TensorFlow Build Custom Convolutional Neural Network With MNIST Dataset

TensorFlow Build Custom Convolutional Neural Network With MNIST Dataset

We are going to use TensorFlow and create CNN model step by step. Then we will train the model with training data and evaluate the model with test data.

Import libraries

In [1]:
import tensorflow as tf

Check tensorflow version

In [2]:
tf.__version__
Out[2]:
'2.3.1'

Download MNIST dataset

What is MNIST dataset?

The MNIST database of handwritten digits, has a training set of 60,000 examples, and a test set of 10,000 examples.

It is a good database for people who want to try learning techniques and pattern recognition methods on real-world data while spending minimal efforts on preprocessing and formatting.

Download MNIST dataset

dir(tf.keras.datasets)
In [3]:
(x_train, y_train), (x_test, y_test) = tf.keras.datasets.mnist.load_data()
In [4]:
print(x_train[0])     
[[  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
    0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
    0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
    0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
    0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
    0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0   0   3  18  18  18 126 136
  175  26 166 255 247 127   0   0   0   0]
 [  0   0   0   0   0   0   0   0  30  36  94 154 170 253 253 253 253 253
  225 172 253 242 195  64   0   0   0   0]
 [  0   0   0   0   0   0   0  49 238 253 253 253 253 253 253 253 253 251
   93  82  82  56  39   0   0   0   0   0]
 [  0   0   0   0   0   0   0  18 219 253 253 253 253 253 198 182 247 241
    0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0  80 156 107 253 253 205  11   0  43 154
    0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0  14   1 154 253  90   0   0   0   0
    0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0 139 253 190   2   0   0   0
    0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0  11 190 253  70   0   0   0
    0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0   0  35 241 225 160 108   1
    0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0   0   0  81 240 253 253 119
   25   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0   0   0   0  45 186 253 253
  150  27   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0  16  93 252
  253 187   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0 249
  253 249  64   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0   0   0   0  46 130 183 253
  253 207   2   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0   0  39 148 229 253 253 253
  250 182   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0  24 114 221 253 253 253 253 201
   78   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0  23  66 213 253 253 253 253 198  81   2
    0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0  18 171 219 253 253 253 253 195  80   9   0   0
    0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0  55 172 226 253 253 253 253 244 133  11   0   0   0   0
    0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0 136 253 253 253 212 135 132  16   0   0   0   0   0   0
    0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
    0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
    0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
    0   0   0   0   0   0   0   0   0   0]]
In [5]:
print(x_train.shape)     
(60000, 28, 28)
In [6]:
print(y_train)
[5 0 4 ... 5 6 8]
In [7]:
print(y_train.shape)
(60000,)

Visualization of MNIST dataset

Plot one train_data

In [8]:
import matplotlib.pyplot as plt
In [9]:
plt.imshow(x_train[0], cmap='gray')
plt.title('%i' % y_train[0])
plt.show()

Plot multiple train_data

In [10]:
num = 26
imgs = x_train[:num]
lbls = y_train[:num]
In [11]:
figure = plt.figure(figsize=(10, 8))
cols, rows = 5, 5
for i in range(1, cols * rows + 1):
    figure.add_subplot(rows, cols, i)
    plt.title(lbls[i])
    plt.axis("off")
    plt.imshow(imgs[i], cmap='gray')
plt.show()

Rescale train and test data

In [12]:
x_train, x_test = x_train / 255.0, x_test / 255.0
In [13]:
print(x_train.shape)
(60000, 28, 28)
In [14]:
print(x_test.shape)
(10000, 28, 28)

Add channels

Conv2D expects 4 dimensions (BatchSize, Channel, Width, Height).

Convolutional layers require a number of input channels. For an RBG image, that number is 3 and for greyscale images, the number of channels is 1.

As we are creating a convlution neural network we have to add channels.

In [15]:
# Add a channels dimension
x_train = x_train[..., tf.newaxis].astype("float32")
x_test = x_test[..., tf.newaxis].astype("float32")
In [16]:
print(x_train.shape)
print(x_test.shape)
(60000, 28, 28, 1)
(10000, 28, 28, 1)

To batch suffle the dataset

The tf.data API enables you to build complex input pipelines from simple, reusable pieces. It's makes it possible to handle large amounts of data, read from different data formats, and perform complex transformations.

The tf.data API introduces a tf.data.Dataset abstraction that represents a sequence of elements, in which each element consists of one or more components.

To create an input pipeline, you must start with a data source. For example, to construct a Dataset from data in memory, you can use tf.data.Dataset.from_tensors() or tf.data.Dataset.from_tensor_slices().

from_tensor_slices can be used to combine different elements into one dataset, e.g., combine x_train, y_train into one dataset.

In [17]:
train_ds = tf.data.Dataset.from_tensor_slices(
    (x_train, y_train)).shuffle(10000).batch(32)

test_ds = tf.data.Dataset.from_tensor_slices((x_test, y_test)).batch(32)
In [18]:
print(train_ds)
<BatchDataset shapes: ((None, 28, 28, 1), (None,)), types: (tf.float32, tf.uint8)>
In [19]:
print(test_ds)
<BatchDataset shapes: ((None, 28, 28, 1), (None,)), types: (tf.float32, tf.uint8)>

Create a Convolutional Neural Network model

A Convolutional Neural Network is type of neural network that is used mainly in image processing applications.

As input, a CNN takes tensors of shape (image_height, image_width, color_channels), ignoring the batch size. If you are new to these dimensions, color_channels refers to (R,G,B). In this example, you will configure our CNN to process inputs of shape (28, 28, 1), which is the format of MNIST images. You can do this by passing the argument input_shape to our first layer.

tf.keras.Model:

Model groups layers into an object with training and inference features.

There are two ways to instantiate a Model:

1) With the "Functional API", where we start from Input, you chain layer calls to specify the model's forward pass, and finally you create your model from inputs and outputs:

2) By subclassing the Model class: in that case, you have to define layers in __init__ and we have to implement the model's forward pass in call. 

We are using second opttion.

tf.keras.layers.Layer:

This is the class from which all layers inherit.
In [20]:
from tensorflow.keras.layers import Dense, Flatten, Conv2D
from tensorflow.keras import Model

Layers

In [21]:
class CNN(Model):
    def __init__(self):
        super(CNN, self).__init__()
        self.conv1 = Conv2D(32, 3, activation='relu')
        self.flatten = Flatten()
        self.d1 = Dense(128, activation='relu')
        self.d2 = Dense(10)

    def call(self, x):
        x = self.conv1(x)
        x = self.flatten(x)
        x = self.d1(x)
        return self.d2(x)
In [22]:
# Create an instance of the model
cnn = CNN()
print(cnn) 
<__main__.CNN object at 0x7effbf00f190>

Define loss function

In [23]:
loss_func = tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True)
loss_func
Out[23]:
<tensorflow.python.keras.losses.SparseCategoricalCrossentropy at 0x7effbeff0cd0>

Define a Optimization Function

lr(Learning Rate): Rate at which our model updates the weights in the cells each time back-propagation is done.

In [24]:
optimizer = tf.keras.optimizers.Adam()
optimizer
Out[24]:
<tensorflow.python.keras.optimizer_v2.adam.Adam at 0x7effbeff0fd0>
In [25]:
train_loss = tf.keras.metrics.Mean(name='train_loss')
train_accuracy = tf.keras.metrics.SparseCategoricalAccuracy(name='train_accuracy')

test_loss = tf.keras.metrics.Mean(name='test_loss')
test_accuracy = tf.keras.metrics.SparseCategoricalAccuracy(name='test_accuracy')

Train the model

Create a function called train() and pass images and labels as inputs.

num_epochs: Number of times our model will go through the entire training dataset

In [26]:
num_epochs = 10
In [27]:
def train(images, labels):
    with tf.GradientTape() as tape:
        # training=True is only needed if there are layers with different
        # behavior during training versus inference (e.g. Dropout).
        predictions = cnn(images, training=True)
        loss = loss_func(labels, predictions)
    
    gradients = tape.gradient(loss, cnn.trainable_variables)
    optimizer.apply_gradients(zip(gradients, cnn.trainable_variables))

    train_loss(loss)
    train_accuracy(labels, predictions)
    pass
In [28]:
for epoch in range(num_epochs):
    # Reset the metrics at the start of the next epoch
    train_loss.reset_states()
    train_accuracy.reset_states()
    
    for images, labels in train_ds:
        train(images, labels)

    print(
        f'Epoch {epoch + 1}, '
        f'Loss: {train_loss.result()}, '
        f'Accuracy: {train_accuracy.result() * 100}, '
    )
    
Epoch 1, Loss: 0.13159561157226562, Accuracy: 95.99833679199219, 
Epoch 2, Loss: 0.041581232100725174, Accuracy: 98.7249984741211, 
Epoch 3, Loss: 0.022383809089660645, Accuracy: 99.25833129882812, 
Epoch 4, Loss: 0.01387712825089693, Accuracy: 99.5233383178711, 
Epoch 5, Loss: 0.00990136619657278, Accuracy: 99.65666198730469, 
Epoch 6, Loss: 0.006534255109727383, Accuracy: 99.77999877929688, 
Epoch 7, Loss: 0.006566525902599096, Accuracy: 99.7683334350586, 
Epoch 8, Loss: 0.0051782019436359406, Accuracy: 99.82167053222656, 
Epoch 9, Loss: 0.003846332896500826, Accuracy: 99.88999938964844, 
Epoch 10, Loss: 0.004074879456311464, Accuracy: 99.86499786376953, 

Evaluate the model on test data

In [29]:
def test(images, labels):
    # training=False is only needed if there are layers with different
    # behavior during training versus inference (e.g. Dropout).
    predictions = cnn(images, training=False)
    t_loss = loss_func(labels, predictions)

    test_loss(t_loss)
    test_accuracy(labels, predictions)

    pass
In [30]:
for epoch in range(num_epochs):
   
    test_loss.reset_states()
    test_accuracy.reset_states()

    for test_images, test_labels in test_ds:
        test(test_images, test_labels)

    print(
        f'Epoch {epoch + 1}, '
        f'Test Loss: {test_loss.result()}, '
        f'Test Accuracy: {test_accuracy.result() * 100}'
    )
    
Epoch 1, Test Loss: 0.07723814249038696, Test Accuracy: 98.61000061035156
Epoch 2, Test Loss: 0.07723814249038696, Test Accuracy: 98.61000061035156
Epoch 3, Test Loss: 0.07723814249038696, Test Accuracy: 98.61000061035156
Epoch 4, Test Loss: 0.07723814249038696, Test Accuracy: 98.61000061035156
Epoch 5, Test Loss: 0.07723814249038696, Test Accuracy: 98.61000061035156
Epoch 6, Test Loss: 0.07723814249038696, Test Accuracy: 98.61000061035156
Epoch 7, Test Loss: 0.07723814249038696, Test Accuracy: 98.61000061035156
Epoch 8, Test Loss: 0.07723814249038696, Test Accuracy: 98.61000061035156
Epoch 9, Test Loss: 0.07723814249038696, Test Accuracy: 98.61000061035156
Epoch 10, Test Loss: 0.07723814249038696, Test Accuracy: 98.61000061035156

Machine Learning

  1. Deal Banking Marketing Campaign Dataset With Machine Learning

TensorFlow

  1. Difference Between Scalar, Vector, Matrix and Tensor
  2. TensorFlow Deep Learning Model With IRIS Dataset
  3. Sequence to Sequence Learning With Neural Networks To Perform Number Addition
  4. Image Classification Model MobileNet V2 from TensorFlow Hub
  5. Step by Step Intent Recognition With BERT
  6. Sentiment Analysis for Hotel Reviews With NLTK and Keras
  7. Simple Sequence Prediction With LSTM
  8. Image Classification With ResNet50 Model
  9. Predict Amazon Inc Stock Price with Machine Learning
  10. Predict Diabetes With Machine Learning Algorithms
  11. TensorFlow Build Custom Convolutional Neural Network With MNIST Dataset
  12. Deal Banking Marketing Campaign Dataset With Machine Learning

PySpark

  1. How to Parallelize and Distribute Collection in PySpark
  2. Role of StringIndexer and Pipelines in PySpark ML Feature - Part 1
  3. Role of OneHotEncoder and Pipelines in PySpark ML Feature - Part 2
  4. Feature Transformer VectorAssembler in PySpark ML Feature - Part 3
  5. Logistic Regression in PySpark (ML Feature) with Breast Cancer Data Set

PyTorch

  1. Build the Neural Network with PyTorch
  2. Image Classification with PyTorch
  3. Twitter Sentiment Classification In PyTorch
  4. Training an Image Classifier in Pytorch

Natural Language Processing

  1. Spelling Correction Of The Text Data In Natural Language Processing
  2. Handling Text For Machine Learning
  3. Extracting Text From PDF File in Python Using PyPDF2
  4. How to Collect Data Using Twitter API V2 For Natural Language Processing
  5. Converting Text to Features in Natural Language Processing
  6. Extract A Noun Phrase For A Sentence In Natural Language Processing