MNIST
TensorFlow
image processing
machine learning
data loading

Read mnist images into Tensorflow

ML System Design practice on Codemia

Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.

Practice ML system design

Introduction

Reading MNIST into TensorFlow is easy because the dataset is already built into common TensorFlow APIs. The main job is not downloading the images, but loading them in the right shape, normalizing pixel values, and preparing a dataset pipeline that the model can train on efficiently.

Use tf.keras.datasets.mnist

The simplest way to load MNIST is through the Keras datasets helper.

python
1import tensorflow as tf
2
3(x_train, y_train), (x_test, y_test) = tf.keras.datasets.mnist.load_data()
4
5print(x_train.shape)
6print(y_train.shape)

This returns NumPy arrays:

  • training images shaped (60000, 28, 28)
  • training labels shaped (60000,)
  • test images shaped (10000, 28, 28)

Each image is grayscale and stored as integer pixel values from 0 to 255.

Normalize and Add a Channel Dimension

Most TensorFlow image models expect floating-point inputs and often expect an explicit channel dimension.

python
1x_train = x_train.astype("float32") / 255.0
2x_test = x_test.astype("float32") / 255.0
3
4x_train = x_train[..., tf.newaxis]
5x_test = x_test[..., tf.newaxis]
6
7print(x_train.shape)

After this step, each image shape becomes (28, 28, 1), which fits convolutional models more naturally.

Build a tf.data Pipeline

TensorFlow training works best when the data is wrapped in a dataset pipeline.

python
1batch_size = 64
2
3train_ds = tf.data.Dataset.from_tensor_slices((x_train, y_train))
4train_ds = train_ds.shuffle(10000).batch(batch_size).prefetch(tf.data.AUTOTUNE)
5
6test_ds = tf.data.Dataset.from_tensor_slices((x_test, y_test))
7test_ds = test_ds.batch(batch_size).prefetch(tf.data.AUTOTUNE)

This gives you efficient batching and input pipelining with minimal code.

Train a Small Model

python
1model = tf.keras.Sequential([
2    tf.keras.layers.Input(shape=(28, 28, 1)),
3    tf.keras.layers.Conv2D(32, 3, activation="relu"),
4    tf.keras.layers.MaxPooling2D(),
5    tf.keras.layers.Flatten(),
6    tf.keras.layers.Dense(64, activation="relu"),
7    tf.keras.layers.Dense(10, activation="softmax")
8])
9
10model.compile(
11    optimizer="adam",
12    loss="sparse_categorical_crossentropy",
13    metrics=["accuracy"]
14)
15
16model.fit(train_ds, epochs=3, validation_data=test_ds)

This example uses sparse_categorical_crossentropy because the labels are integer class IDs from 0 to 9, not one-hot vectors.

Alternative: TensorFlow Datasets

If you want metadata, standardized splits, or broader dataset tooling, tensorflow_datasets is another option.

python
1import tensorflow_datasets as tfds
2
3train_ds = tfds.load("mnist", split="train", as_supervised=True)
4for image, label in train_ds.take(1):
5    print(image.shape, label.numpy())

This is especially useful when you want a consistent pipeline style across many datasets, not just MNIST.

Inspect One Image Before Training

A quick shape and value check helps catch preprocessing mistakes early.

python
print(x_train[0].shape)
print(x_train[0].dtype)
print(y_train[0])

If you want to visualize one digit, a small Matplotlib snippet is enough:

python
1import matplotlib.pyplot as plt
2
3plt.imshow(x_train[0].squeeze(), cmap=\"gray\")
4plt.title(f\"Label: {y_train[0]}\")
5plt.show()

That quick inspection is often the fastest way to confirm that normalization and channel handling are correct before a longer training run.

Common Pitfalls

  • Feeding raw integer pixel values directly into a model often makes training less stable than using normalized floats. Scale the images to a sensible range such as 0 to 1.
  • Forgetting the channel dimension can break convolutional models that expect (height, width, channels). Add the last dimension for grayscale images when needed.
  • Using the wrong loss for the label format causes confusion. Integer labels pair naturally with sparse_categorical_crossentropy.
  • Skipping batching and prefetching leaves the training pipeline less efficient than it needs to be. Use tf.data when moving beyond the smallest demos.
  • Treating the dataset loader as the whole task misses the preprocessing step. Reading MNIST is easy; preparing it correctly is what makes the training example work.

Summary

  • The easiest way to read MNIST into TensorFlow is tf.keras.datasets.mnist.load_data().
  • The loaded images should usually be normalized and, for CNNs, expanded to include a channel dimension.
  • 'tf.data.Dataset makes batching and prefetching straightforward.'
  • Use sparse_categorical_crossentropy when labels remain integer class IDs.
  • TensorFlow Datasets is a good alternative when you want a more general dataset pipeline API.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

ML System Design practice on Codemia

Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.

Practice ML system design

All Rights Reserved.