# The MNIST database of handwritten digits

Description from the official website:

The MNIST database of handwritten digits, available from this page, has a training set of 60,000 examples, and a test set of 10,000 examples. It is a subset of a larger set available from NIST. The digits have been size-normalized and centered in a fixed-size image.

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.

## Overview

The MLDatasets.MNIST sub-module provides a programmatic interface to download, load, and work with the MNIST dataset of handwritten digits.

using MLDatasets

train_x, train_y = MNIST.traindata()

test_x,  test_y  = MNIST.testdata()

The provided functions also allow for optional arguments, such as the directory dir where the dataset is located, or the specific observation indices that one wants to work with. For more information on the interface take a look at the documentation (e.g. ?MNIST.traindata).

FunctionDescription
download([dir])Trigger (interactive) download of the dataset
traintensor([T], [indices]; [dir])Load the training images as an array of eltype T
trainlabels([indices]; [dir])Load the labels for the training images
testtensor([T], [indices]; [dir])Load the test images as an array of eltype T
testlabels([indices]; [dir])Load the labels for the test images
traindata([T], [indices]; [dir])Load images and labels of the training data
testdata([T], [indices]; [dir])Load images and labels of the test data

This module also provides utility functions to make working with the MNIST dataset in Julia more convenient.

FunctionDescription
convert2image(array)Convert the MNIST tensor/matrix to a colorant array

To visualize an image or a prediction we provide the function convert2image to convert the given MNIST horizontal-major tensor (or feature matrix) to a vertical-major Colorant array. The values are also color corrected according to the website's description, which means that the digits are black on a white background.

julia> MNIST.convert2image(MNIST.traintensor(1)) # first training image
28×28 Array{Gray{N0f8},2}:
[...]

## API Documentation

MLDatasets.MNISTModule

The MNIST database of handwritten digits

• Authors: Yann LeCun, Corinna Cortes, Christopher J.C. Burges
• Website: http://yann.lecun.com/exdb/mnist/

MNIST is a classic image-classification dataset that is often used in small-scale machine learning experiments. It contains 70,000 images of handwritten digits. Each observation is a 28x28 pixel gray-scale image that depicts a handwritten version of 1 of the 10 possible digits (0-9).

Interface

Utilities

### Trainingset

MLDatasets.MNIST.traintensorFunction
traintensor([T = N0f8], [indices]; [dir]) -> Array{T}

Returns the MNIST training images corresponding to the given indices as a multi-dimensional array of eltype T.

The image(s) is/are returned in the horizontal-major memory layout as a single numeric array. If T <: Integer, then all values will be within 0 and 255, otherwise the values are scaled to be between 0 and 1.

If the parameter indices is omitted or an AbstractVector, the images are returned as a 3D array (i.e. a Array{T,3}), in WHN format (width, height, #images). For integer indices instead, a 2D array in WH format is returned.

julia> MNIST.traintensor() # load all training images
28×28×60000 Array{N0f8,3}:
[...]

julia> MNIST.traintensor(Float32, 1:3) # first three images as Float32
28×28×3 Array{Float32,3}:
[...]

If indices is an Integer, the single image is returned as Matrix{T}.

julia> MNIST.traintensor(1) # load first training image
28×28 Array{N0f8,2}:
[...]

You can use the utility function convert2image to convert an MNIST array into a vertical-major Julia image with the corrected color values.

julia> MNIST.convert2image(MNIST.traintensor(1)) # convert to column-major colorant array
28×28 Array{Gray{N0f8},2}:
[...]

The corresponding resource file(s) of the dataset is/are expected to be located in the specified directory dir. If dir is omitted the directories in DataDeps.default_loadpath will be searched for an existing MNIST subfolder. In case no such subfolder is found, dir will default to ~/.julia/datadeps/MNIST. In the case that dir does not yet exist, a download prompt will be triggered. You can also use MNIST.download([dir]) explicitly for pre-downloading (or re-downloading) the dataset. Please take a look at the documentation of the package DataDeps.jl for more detail and configuration options.

MLDatasets.MNIST.trainlabelsFunction
trainlabels([indices]; [dir])

Returns the MNIST trainset labels corresponding to the given indices as an Int or Vector{Int}. The values of the labels denote the digit that they represent. If indices is omitted, all labels are returned.

julia> MNIST.trainlabels() # full training set
60000-element Array{Int64,1}:
5
0
⋮
6
8

julia> MNIST.trainlabels(1:3) # first three labels
3-element Array{Int64,1}:
5
0
4

julia> MNIST.trainlabels(1) # first label
5

The corresponding resource file(s) of the dataset is/are expected to be located in the specified directory dir. If dir is omitted the directories in DataDeps.default_loadpath will be searched for an existing MNIST subfolder. In case no such subfolder is found, dir will default to ~/.julia/datadeps/MNIST. In the case that dir does not yet exist, a download prompt will be triggered. You can also use MNIST.download([dir]) explicitly for pre-downloading (or re-downloading) the dataset. Please take a look at the documentation of the package DataDeps.jl for more detail and configuration options.

MLDatasets.MNIST.traindataFunction
traindata([T = N0f8], [indices]; [dir]) -> Tuple

Returns the MNIST trainingset corresponding to the given indices as a two-element tuple. If indices is omitted the full trainingset is returned. The first element of three return values will be the images as a multi-dimensional array, and the second element the corresponding labels as integers.

The image(s) is/are returned in the horizontal-major memory layout as a single numeric array of eltype T. If T <: Integer, then all values will be within 0 and 255, otherwise the values are scaled to be between 0 and 1. The integer values of the labels correspond 1-to-1 the digit that they represent.

train_x, train_y = MNIST.traindata() # full datatset
train_x, train_y = MNIST.traindata(2) # only second observation
train_x, train_y = MNIST.traindata(dir="./MNIST") # custom folder

The corresponding resource file(s) of the dataset is/are expected to be located in the specified directory dir. If dir is omitted the directories in DataDeps.default_loadpath will be searched for an existing MNIST subfolder. In case no such subfolder is found, dir will default to ~/.julia/datadeps/MNIST. In the case that dir does not yet exist, a download prompt will be triggered. You can also use MNIST.download([dir]) explicitly for pre-downloading (or re-downloading) the dataset. Please take a look at the documentation of the package DataDeps.jl for more detail and configuration options.

Take a look at MNIST.traintensor and MNIST.trainlabels for more information.

### Testset

MLDatasets.MNIST.testtensorFunction
testtensor([T = N0f8], [indices]; [dir]) -> Array{T}

Returns the MNIST test images corresponding to the given indices as a multi-dimensional array of eltype T.

The image(s) is/are returned in the horizontal-major memory layout as a single numeric array. If T <: Integer, then all values will be within 0 and 255, otherwise the values are scaled to be between 0 and 1.

If the parameter indices is omitted or an AbstractVector, the images are returned as a 3D array (i.e. a Array{T,3}), in WHN format (width, height, #images). For integer indices instead, a 2D array in WH format is returned.

julia> MNIST.testtensor() # load all test images
28×28×10000 Array{N0f8,3}:
[...]

julia> MNIST.testtensor(Float32, 1:3) # first three images as Float32
28×28×3 Array{Float32,3}:
[...]

If indices is an Integer, the single image is returned as Matrix{T}.

julia> MNIST.testtensor(1) # load first test image
28×28 Array{N0f8,2}:
[...]

You can use the utility function convert2image to convert an MNIST array into a vertical-major Julia image with the corrected color values.

julia> MNIST.convert2image(MNIST.testtensor(1)) # convert to column-major colorant array
28×28 Array{Gray{N0f8},2}:
[...]

The corresponding resource file(s) of the dataset is/are expected to be located in the specified directory dir. If dir is omitted the directories in DataDeps.default_loadpath will be searched for an existing MNIST subfolder. In case no such subfolder is found, dir will default to ~/.julia/datadeps/MNIST. In the case that dir does not yet exist, a download prompt will be triggered. You can also use MNIST.download([dir]) explicitly for pre-downloading (or re-downloading) the dataset. Please take a look at the documentation of the package DataDeps.jl for more detail and configuration options.

MLDatasets.MNIST.testlabelsFunction
testlabels([indices]; [dir])

Returns the MNIST testset labels corresponding to the given indices as an Int or Vector{Int}. The values of the labels denote the digit that they represent. If indices is omitted, all labels are returned.

julia> MNIST.testlabels() # full test set
10000-element Array{Int64,1}:
7
2
⋮
5
6

julia> MNIST.testlabels(1:3) # first three labels
3-element Array{Int64,1}:
7
2
1

julia> MNIST.testlabels(1) # first label
7

The corresponding resource file(s) of the dataset is/are expected to be located in the specified directory dir. If dir is omitted the directories in DataDeps.default_loadpath will be searched for an existing MNIST subfolder. In case no such subfolder is found, dir will default to ~/.julia/datadeps/MNIST. In the case that dir does not yet exist, a download prompt will be triggered. You can also use MNIST.download([dir]) explicitly for pre-downloading (or re-downloading) the dataset. Please take a look at the documentation of the package DataDeps.jl for more detail and configuration options.

MLDatasets.MNIST.testdataFunction
testdata([T = N0f8], [indices]; [dir]) -> Tuple

Returns the MNIST testset corresponding to the given indices as a two-element tuple. If indices is omitted the full testset is returned. The first element of three return values will be the images as a multi-dimensional array, and the second element the corresponding labels as integers.

The image(s) is/are returned in the horizontal-major memory layout as a single numeric array of eltype T. If T <: Integer, then all values will be within 0 and 255, otherwise the values are scaled to be between 0 and 1. The integer values of the labels correspond 1-to-1 the digit that they represent.

test_x, test_y = MNIST.testdata() # full datatset
test_x, test_y = MNIST.testdata(2) # only second observation
test_x, test_y = MNIST.testdata(dir="./MNIST") # custom folder

The corresponding resource file(s) of the dataset is/are expected to be located in the specified directory dir. If dir is omitted the directories in DataDeps.default_loadpath will be searched for an existing MNIST subfolder. In case no such subfolder is found, dir will default to ~/.julia/datadeps/MNIST. In the case that dir does not yet exist, a download prompt will be triggered. You can also use MNIST.download([dir]) explicitly for pre-downloading (or re-downloading) the dataset. Please take a look at the documentation of the package DataDeps.jl for more detail and configuration options.

Take a look at MNIST.testtensor and MNIST.testlabels for more information.

### Utilities

MLDatasets.MNIST.downloadFunction
download([dir]; [i_accept_the_terms_of_use])

Trigger the (interactive) download of the full dataset into "dir". If no dir is provided the dataset will be downloaded into "~/.julia/datadeps/MNIST".

This function will display an interactive dialog unless either the keyword parameter i_accept_the_terms_of_use or the environment variable DATADEPS_ALWAYS_ACCEPT is set to true. Note that using the data responsibly and respecting copyright/terms-of-use remains your responsibility.

MLDatasets.MNIST.convert2imageFunction
convert2image(array) -> Array{Gray}

Convert the given MNIST horizontal-major tensor (or feature matrix) to a vertical-major Colorant array. The values are also color corrected according to the website's description, which means that the digits are black on a white background.

julia> MNIST.convert2image(MNIST.traintensor()) # full training dataset
28×28×60000 Array{Gray{N0f8},3}:
[...]

julia> MNIST.convert2image(MNIST.traintensor(1)) # first training image
28×28 Array{Gray{N0f8},2}:
[...]

MLDatasets.MNIST.Reader.readimagesMethod
readimages(io::IO, indices::AbstractVector, nrows::Integer, ncols::Integer)

Reads the first nrows * ncols bytes for each image index in indices and stores them in a Array{UInt8,3} of size (nrows, ncols, length(indices)) in the same order as denoted by indices.

MLDatasets.MNIST.Reader.readimagesMethod
readimages(file, [indices])

Reads the images denoted by indices from file. The given file can either be specified using an IO-stream or a string that denotes the fully qualified path. The conent of file is assumed to be in the MNIST image-file format, as it is described on the official homepage at http://yann.lecun.com/exdb/mnist/

• if indices is an Integer, the single image is returned as Matrix{UInt8} in horizontal major layout, which means that the first dimension denotes the pixel rows (x), and the second dimension denotes the pixel columns (y) of the image.

• if indices is a AbstractVector, the images are returned as a 3D array (i.e. a Array{UInt8,3}), in which the first dimension corresponds to the pixel rows (x) of the image, the second dimension to the pixel columns (y) of the image, and the third dimension denotes the index of the image.

• if indices is ommited all images are returned (as 3D array described above)

MLDatasets.MNIST.Reader.readimagesMethod
readimages(io::IO, index::Integer, nrows::Integer, ncols::Integer)

Jumps to the position of io where the bytes for the index'th image are located and reads the next nrows * ncols bytes. The read bytes are returned as a Matrix{UInt8} of size (nrows, ncols).

MLDatasets.MNIST.Reader.readlabelsMethod
readlabels(file::AbstractString, [indices])

Reads the label denoted by indices from file. The given file is assumed to be in the MNIST label-file format, as it is described on the official homepage at http://yann.lecun.com/exdb/mnist/

• if indices is an Integer, the single label is returned as UInt8.

• if indices is a AbstractVector, the labels are returned as a Vector{UInt8}, length length(indices) in the same order as denoted by indices.

• if indices is ommited all all are returned (as Vector{UInt8} as described above)

MLDatasets.MNIST.Reader.readlabelsMethod
readlabels(io::IO, indices::AbstractVector)

Reads the byte for each label-index in indices and stores them in a Vector{UInt8} of length length(indices) in the same order as denoted by indices.

MLDatasets.MNIST.Reader.readlabelsMethod
readlabels(io::IO, index::Integer)

Jumps to the position of io where the byte for the index'th label is located and returns the byte at that position as UInt8

MLDatasets.MNIST.Reader.readimageheaderMethod
readimageheader(io::IO)

Reads four 32 bit integers at the current position of io and interprets them as a MNIST-image-file header, which is described in detail in the table below

        ║     First    │  Second  │  Third  │   Fourth
════════╬══════════════╪══════════╪═════════╪════════════
offset  ║         0000 │     0004 │    0008 │       0012
descr   ║ magic number │ # images │  # rows │  # columns

These four numbers are returned as a Tuple in the same storage order

MLDatasets.MNIST.Reader.readlabelheaderMethod
readlabelheader(io::IO)

Reads two 32 bit integers at the current position of io and interprets them as a MNIST-label-file header, which consists of a magic number and the total number of labels stored in the file. These two numbers are returned as a Tuple in the same storage order.

## References

• Authors: Yann LeCun, Corinna Cortes, Christopher J.C. Burges

• Website: http://yann.lecun.com/exdb/mnist/

• [LeCun et al., 1998a] Y. LeCun, L. Bottou, Y. Bengio, and P. Haffner. "Gradient-based learning applied to document recognition." Proceedings of the IEEE, 86(11):2278-2324, November 1998