classification

Basic ML Classification: Classify Images with Tensorflow and Python

YouTube video here .

The problem

We have 10000 images and 10 classes [ 'T-shirt/top' , 'Trouser' , 'Pullover' , 'Dress' , 'Coat' , 'Sandal' , 'Shirt' , 'Sneaker' , 'Bag' , 'Ankle boot' ].

Our model needs to classify the images based on the classes.

Needed Libraries

Python
# Used for building our Neural Network
import tensorflow as tf
from tensorflow import keras

import numpy as np # Used for advanced maths
import matplotlib.pyplot as plt # Used for drawing charts

Our dataset

The MNIST dataset is composed by: 

  • TRAIN set: 60000 images + 60000 labels (train_images + train_labels)
  • TEST set: 10000 images + 10000 labels (test_images + test_labels)
Train Set explanation: train_images, train_labels, class_names

We download those datasets, and store them in variables.

Python
# download datasets
fashion_mnist = keras.datasets.fashion_mnist

# load datasets into variables
(train_images, train_labels), (test_images, test_labels) = fashion_mnist.load_data()

Now we have the images! Check the train_images shape!

Python
train_images.shape # (60'000, 28, 28)

train_images contains 60'000 images made by 28x28 pixels. Let's print the first image!

Python
plt.figure() # create an empty box
plt.imshow(train_images[0]) # add the first image from the dataset
plt.colorbar() # add the color bar
plt.grid(False) # do not display the grid
plt.show() # show everything

# print its class name, in this case 'Ankle boot'
class_names[ train_labels[0] ]
28x28 matrix vs image

We scale the values 0-255 to 0-1. Doing so can make the model converge faster.

Python
train_images = train_images / 255.0

test_images = test_images / 255.0

Building The Model

Let's draw our Neural Network! "Sequential()" draws the Neural Network's Layers in the order we declare them!

Python
model = keras.Sequential([
    keras.layers.Flatten(input_shape=(28, 28)), # Input Layer
    keras.layers.Dense(128, activation='relu'), # Hidden Layer
    keras.layers.Dense(10) # Output Layer
])

The Input Layer gets a "flattened" image of (28x28)pixels. This means that the image 28x28 gets translated into a vector of 784, and then passed as input to our Neural Network.

Flattening operation

We create 128 neurons which will be Densely-Connected (or Fully-Connected) to our  previous Input Layer, using Dense(). We apply the Relu Activation Function.

We create another Layer that will have 10 neurons, Fully-Connected to our previous Hidden Layer. This will be our Output Layer, since it is the last.
This is made by 10 neurons since the classes are 10 and at the end the Neural Network gives out a vote: how much an image belongs to a class.

Compile The Model

In this step, some settings are added: the optimizer, the loss function, the metrics.

Python
model.compile(optimizer='adam',
              loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
              metrics=['accuracy'])

Train Your Model

Oh yes! We can now train our model!
For each train_images, there is a train_labels!
The model observes those associations for 10 epochs (It will go through the entire train dataset for 10 times).
In this way the model understands that "This it's called that", it is training itself!

Python
model.fit(train_images, train_labels, epochs=10)

Evalute Your Model on New Observations

During the training, you can see in the console how the accuracy of the model is growing. The more you train, the stronger you are!
Let's see how does our model perform on new observations

Python
test_loss, test_acc = model.evaluate(test_images,  test_labels, verbose=2)

print('\nTest accuracy:', test_acc)

The accuracy on new observations is a little bit less.

This means that our model overfitted the training set.

It's like if you solve a maze and you get used to it until you know it, but on a new one, you kind of get lost.

Predict the Cloth's Class Name

We trained our model, we evaluated its accuracy.
Let's make a prediction on a new observation: we have an image but the model doesn't know its class.

Our model has a 10 neurons ouput. Those neurons' outputs are logits.
Logits are a vector of raw (non-normalized) predictions that a classification model generates. 

We apply a softmax function which generates a vector of (normalized) probabilities with one value for each possible class.

Python
# apply softmax function to model
probability_model = tf.keras.Sequential([model, tf.keras.layers.Softmax()])

Let's predict the labels for each test_images and what the model predicted for the first image:

Python
# predict labels for every image in test_images
predictions = probability_model.predict(test_images)
# print the model's first prediction
print(predictions[0])
np.argmax(predictions[0])
class_names[np.argmax(predictions[0])]

We compare our prediction with what REALLY the value is:

Python
# if np.argmax(predictions[0]) is the same as this, the model is correct
test_labels[0]

Graph The First 15 Predictions

Python
def plot_image(i, predictions_array, true_label, img):
  predictions_array, true_label, img = predictions_array, true_label[i], img[i]
  plt.grid(False)
  plt.xticks([])
  plt.yticks([]) # remove x,y ticks

  plt.imshow(img, cmap=plt.cm.binary) # show image in black and white

  predicted_label = np.argmax(predictions_array)
  if predicted_label == true_label:
    color = 'blue' # if correct prediction, print blue
  else:
    color = 'red' # if wrong prediction, print red
    
  # label on x axes format: predicted label % (real label)
  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, true_label[i]
  plt.grid(False)
  plt.xticks(range(10)) # add ticks from 0 to 9
  plt.yticks([]) # no ticks on y axes
  thisplot = plt.bar(range(10), predictions_array, color="#777777")
  plt.ylim([0, 1]) # set limits of current axes (bottom,top)
  predicted_label = np.argmax(predictions_array)

  thisplot[predicted_label].set_color('red')
  thisplot[true_label].set_color('blue') # overwrites red
  
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[i], test_labels, test_images)
  plt.subplot(num_rows, 2*num_cols, 2*i+2)
  plot_value_array(i, predictions[i], test_labels)
plt.tight_layout() # extra padding around the figure border and between subplots
plt.show()

Make a Single Prediction and Plot it

Let's take image index 1 from test_images, change its shape before inputting into our Neural Network because of format necessity: the model expects an array of matrixes.

Python
img = test_images[1]
print(img.shape) # (28,28)

img = (np.expand_dims(img,0))
print(img.shape) # (1,28,28)

# make a single prediction
predictions_single = probability_model.predict(img)
print(predictions_single)

We print the model probabilities.

Python
# run those together, otherwise you'll encounter problems!

plot_value_array(1, predictions_single[0], test_labels)
_ = plt.xticks(range(10), class_names, rotation=45)
Single Image Prediction

Python
# https://www.tensorflow.org/tutorials/keras/classification

# Copyright (c) 2017 François Chollet
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.
python spyder tensorflow mnist dataset keras 10 classes multiple classes image