The Real Thing

Test the binary classification code on MNIST.

We'll cover the following...

Test MNIST

It’s time to reach for our binary classification code (from Classification in Action) and run it on MNIST. We have to adapt it a bit, but the changes are minimal. We can use the exact same functions that we used in the previous chapter, as long as we update the main code:

# An MNIST loader.

import numpy as np
import gzip
import struct


def load_images(filename):
    # Open and unzip the file of images:
    with gzip.open(filename, 'rb') as f:
        # Read the header information into a bunch of variables
        _ignored, n_images, columns, rows = struct.unpack('>IIII', f.read(16))
        # Read all the pixels into a NumPy array of bytes:
        all_pixels = np.frombuffer(f.read(), dtype=np.uint8)
        # Reshape the pixels into a matrix where each line is an image:
        return all_pixels.reshape(n_images, columns * rows)


def prepend_bias(X):
    # Insert a column of 1s in the position 0 of X.
    # (“axis=1” stands for: “insert a column, not a row”)
    return np.insert(X, 0, 1, axis=1)


# 60000 images, each 785 elements (1 bias + 28 * 28 pixels)
X_train = prepend_bias(load_images("../programming-machine-learning/data/mnist/train-images-idx3-ubyte.gz"))

# 10000 images, each 785 elements, with the same structure as X_train
X_test = prepend_bias(load_images("../programming-machine-learning/data/mnist/t10k-images-idx3-ubyte.gz"))


def load_labels(filename):
    # Open and unzip the file of images:
    with gzip.open(filename, 'rb') as f:
        # Skip the header bytes:
        f.read(8)
        # Read all the labels into a list:
        all_labels = f.read()
        # Reshape the list of labels into a one-column matrix:
        return np.frombuffer(all_labels, dtype=np.uint8).reshape(-1, 1)


def encode_fives(Y):
    # Convert all 5s to 1, and everything else to 0
    return (Y == 5).astype(int)


# 60K labels, each with value 1 if the digit is a five, and 0 otherwise
Y_train = encode_fives(load_labels("../programming-machine-learning/data/mnist/train-labels-idx1-ubyte.gz"))

# 10000 labels, with the same encoding as Y_train
Y_test = encode_fives(load_labels("../programming-machine-learning/data/mnist/t10k-labels-idx1-ubyte.gz"))
digit_classifier.py
digit_classifier.py

We use one line for training, one for testing. We don’t need to load and prepare the data, because our MNIST library already takes care of that.

And here’s the output of our first image classifier:

Iteration 0 => Loss: 0.69314718055994528623
Iteration 1 => Loss: 0.80042530259490185518
Iteration 2 => Loss: 0.60370180008019158624

Iteration 99 => Loss: 0.11895658384798543650

Success: 9637/10000 (96.37%)

The result shows that over 96% of the program’s forecasts are proved accurate. Our program recognizes images!

While 96% might seem great, it does not necessarily mean that our program is very accurate. Think about it: only 10% of the digits in the MNIST test set are 5s. This means that a naive program that always forecasts 0 ...