The Real Thing

Test the binary classification code on MNIST.

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

Code explanation

This Python code implements a complete logistic regression model from scratch to perform binary classification on the MNIST dataset. It’s a foundational example that shows the core components of a simple machine learning system.

  1. sigmoid(z): This function is the model’s activation function. It takes a numerical input (z) and transforms it into a value between 0 and 1. In logistic regression, this output represents the probability of the input belonging to the positive class (e.g., being the digit ‘5’).

  2. forward(X, w): ...