Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

stough 202-

Preview: [MNIST](https://en.wikipedia.org/wiki/MNIST_database) Digit Recognition Through Averages

In this notebook we’ll define a simple linear scheme for recognizing hand-written digits. Every image we train on and ever test against is a 28×2828\times28 single-channel thumbnail. Look through mnist_explore.ipynb for more.

Our approach for recognizing the digit in a single image is simple: compare each pixel in the image against a template for each digit class. We’ll do this through simple correlation: a dot-product of the image with the digit template. The higher the correlation, the higher the likelihood that the image is example of that template digit.

Loading and Formatting the MNIST Data

0. Play around with all the data being provided.

As you see above, each row of x_train (or x_test) is a 784-dimensional vector, just a flattened version of some 28×2828\times28 MNIST image in either the training or test data. Further, y_train (or y_test) contains the digit class. Explore these structures that have been provided, so that you will have some idea what in the world is happenning below.

  • Visualize a corresponding row and element from x_train and y_train.

    • What are the shapes of x_train and y_train? What about x_test and y_test?

    • Print out y_train[1234]

    • Try to visualize the corresponding hand-written digit image in x_train, that is x_train[1234] or x_train[1234,:]. Of course you cannot imshow a 1D row, so use np.reshape.

Hopefully this exploration should convince you that we have training x_train and test x_test datasets, and these sets are also labeled through the arrays y_train and y_test. We’re going to use the training data to formulate MNIST image templates for each digit, and then use the test data to see how well those templates generalize to data that we didn’t use in training.

1. Vector-normalize the x_train and x_test data.

Normalize each row so that every image has a magnitude of 1. We want to do this so that when we do correlations/dot-products, the possible outcomes are all values in the range normalized range [−1,1][-1,1]. Use norm and divide to pretty easily perform this normalization. If you’re writing your own for loop, you haven’t looked closely enough at the documentation for these powerfull numpy functions.

  • You may run into an issue with broadcast rules on division. For example, if we just look at the shapes (10,3)(10,3) and (10,1)(10,1), divide would know how to divide these two matrices: it would virtually make three vertical copies of the second so that the two shapes matched at (10,3)(10,3). However divide doesn’t know what to do with (10,3)(10,3) and (10,)(10,) for example, because the number of dimensions isn’t even the same. Read the documentation and work with small examples to solve your issues.

2. Compute a 10×78410\times784 matrix of template digits.

See mnist_explore.ipynb, where we compute the average seven for example. Do this for every digit using the x_train (and y_train) data. I call the resulting matrix A in the test cells.

3. Correlate x_test against the template matrix.

Use matmul to compute the dot-product of every test case against every digit template. Given that there are 10K test images, our result should be 10000×1010000\times10.

4. Compute the classification accuracy of this scheme.

Use argmax to determine for each test case which template digit yielded the best score. Then compute the number that matched the correct labels from y_test.

5. Show some examples of the incorrectly-classified digit images from x_test

Remember you can use where to get the indices at which your argmax result above do not match the y_test labels.