Python Data Foundations Documentation

A plain documentation-style guide for Python, data handling, visualization, and machine learning basics.

Neural Networks with Fashion MNIST

This page explains a basic dense neural network workflow with Fashion MNIST: loading images, preparing labels, building a Sequential model, training, predicting, and evaluating classification quality.

What you should be able to do
  • Load and inspect Fashion MNIST image and label arrays.
  • Normalize pixel values and create a validation split.
  • Build a dense neural network with Flatten, Dense, ReLU, and softmax layers.
  • Train, evaluate, predict classes, and read a classification report and confusion matrix.
Reusable patterns
  • Neural network inputs should be scaled; image pixels are commonly divided by 255.
  • A softmax output layer returns one probability per class.
  • np.argmax converts class probabilities into the predicted class index.

Setup and Dataset

Listing 1. Import TensorFlow and Keras

This step supports the workflow shown in the surrounding listings.

import tensorflow as tf
from tensorflow import keras

Listing 2. Check the TensorFlow version

This step supports the workflow shown in the surrounding listings.

tf.__version__
Expected text output or note
'2.15.0'

Listing 3. Load Fashion MNIST from Keras datasets

This prepares the data or pretrained resource used by the following examples.

dataset = keras.datasets.fashion_mnist
(X_train,y_train), (X_test,y_test)=dataset.load_data()
Expected text output or note
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/train-labels-idx1-ubyte.gz
29515/29515 [==============================] - 0s 0us/step
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/train-images-idx3-ubyte.gz
26421880/26421880 [==============================] - 0s 0us/step
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/t10k-labels-idx1-ubyte.gz
5148/5148 [==============================] - 0s 0us/step
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/t10k-images-idx3-ubyte.gz
4422102/4422102 [==============================] - 0s 0us/step

Listing 4. Check the training image array shape

Training updates model weights and stores the learning history for later inspection.

X_train.shape
Expected text output or note
(60000, 28, 28)

Listing 5. Inspect the raw training labels

Training updates model weights and stores the learning history for later inspection.

y_train
Expected text output or note
array([9, 0, 0, ..., 3, 0, 5], dtype=uint8)

Listing 6. Define readable Fashion MNIST class names

This step supports the workflow shown in the surrounding listings.

class_names=["T-shirt/top", "Trouser", "Pullover","Dress", "Coat", "Sandal", "Shirt", "Sneaker", "Bag", "Ankle boot"]

Listing 7. Inspect the first training label

Training updates model weights and stores the learning history for later inspection.

y_train[0]
Expected text output or note
9

Listing 8. Convert the first training label to its class name

Training updates model weights and stores the learning history for later inspection.

class_names[y_train[0]]
Expected text output or note
'Ankle boot'

Listing 9. Check one image shape

This step supports the workflow shown in the surrounding listings.

X_train[0].shape
Expected text output or note
(28, 28)

Listing 10. Display one grayscale Fashion MNIST image

This visualization step helps verify what the data or model output looks like.

import matplotlib.pyplot as plt
plt.imshow(X_train[0], cmap='gray')
Expected text output or note
<matplotlib.image.AxesImage at 0x7a15769d0910>
<Figure size 640x480 with 1 Axes>

[visual output omitted; run the code to display the image or chart]

Listing 11. Normalize pixel values to the 0 to 1 range

This transforms the raw input into the numeric scale or shape expected by the model.

X_train=X_train/255

Listing 12. Create validation data from the first 5,000 training examples

Training updates model weights and stores the learning history for later inspection.

X_valid=X_train[:5000]
X_train=X_train[5000:]
y_valid=y_train[:5000]
y_train=y_train[5000:]

Listing 13. Preview validation images with their class names

This step supports the workflow shown in the surrounding listings.

for i in range(0,5):
  plt.subplot(151+i)
  plt.imshow(X_valid[i], cmap='gray')
  plt.title(class_names[y_valid[i]])
plt.show()
Expected text output or note
<Figure size 640x480 with 5 Axes>

[visual output omitted; run the code to display the image or chart]

Model Architecture

Listing 14. Create an empty Sequential model

This defines or inspects part of the neural network architecture.

model=keras.models.Sequential()

Listing 15. Flatten 28 by 28 images into vectors

This step supports the workflow shown in the surrounding listings.

model.add(keras.layers.Flatten(input_shape=[28,28]))

Listing 16. Add the first hidden dense layer

This defines or inspects part of the neural network architecture.

model.add(keras.layers.Dense(300, activation="relu"))

Listing 17. Add the second hidden dense layer

This defines or inspects part of the neural network architecture.

model.add(keras.layers.Dense(100, activation="relu"))

Listing 18. Add the softmax output layer for 10 classes

This defines or inspects part of the neural network architecture.

model.add(keras.layers.Dense(10, activation="softmax"))

Listing 19. List the model layers

This defines or inspects part of the neural network architecture.

model.layers
Expected text output or note
[<keras.src.layers.reshaping.flatten.Flatten at 0x7a1576856290>,
 <keras.src.layers.core.dense.Dense at 0x7a1576857a00>,
 <keras.src.layers.core.dense.Dense at 0x7a1576798580>,
 <keras.src.layers.core.dense.Dense at 0x7a1576798be0>]

Listing 20. Print the model architecture summary

This defines or inspects part of the neural network architecture.

model.summary()
Expected text output or note
Model: "sequential"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 flatten (Flatten)           (None, 784)               0         
                                                                 
 dense (Dense)               (None, 300)               235500    
                                                                 
 dense_1 (Dense)             (None, 100)               30100     
                                                                 
 dense_2 (Dense)             (None, 10)                1010      
                                                                 
=================================================================
Total params: 266610 (1.02 MB)
Trainable params: 266610 (1.02 MB)
Non-trainable params: 0 (0.00 Byte)
_________________________________________________________________

Listing 21. Draw the model graph with tensor shapes

This defines or inspects part of the neural network architecture.

keras.utils.plot_model(model, show_shapes=True)
Expected text output or note
<IPython.core.display.Image object>

[visual output omitted; run the code to display the image or chart]

Listing 22. Select the first hidden layer

This defines or inspects part of the neural network architecture.

hidden1=model.layers[1]

Listing 23. Read weights and bias values from the hidden layer

This defines or inspects part of the neural network architecture.

weights, bias= hidden1.get_weights()

Listing 24. Inspect the hidden-layer weight matrix

This defines or inspects part of the neural network architecture.

weights
Expected text output or note
array([[-0.06094005,  0.02962055, -0.02309486, ..., -0.06288422,
        -0.01324312, -0.0500589 ],
       [ 0.070352  , -0.03515274, -0.04809655, ..., -0.04971475,
         0.04923429,  0.01798429],
       [-0.05490538,  0.02042819, -0.02559312, ..., -0.01840512,
         0.0332567 , -0.0607585 ],
       ...,
       [ 0.06727193,  0.05644499, -0.03700116, ...,  0.02343841,
         0.07261452,  0.03050473],
       [-0.05256438, -0.06475436, -0.03320796, ...,  0.017466  ,
        -0.05396302,  0.07283223],
       [ 0.017487  , -0.02869108,  0.05089015, ...,  0.04649328,
        -0.06772804,  0.01935725]], dtype=float32)

Training

Listing 25. Compile the classifier with sparse categorical crossentropy

Compilation chooses the loss function, optimizer, and metrics used during training.

model.compile(loss="sparse_categorical_crossentropy",
              optimizer="sgd",
              metrics=["accuracy"]) # more metrics can be listed here

Listing 26. Train the dense neural network

Training updates model weights and stores the learning history for later inspection.

history=model.fit(X_train,y_train,batch_size=32, epochs=20, validation_data=(X_valid, y_valid))
#history=model.fit(X_train,y_train,batch_size=256, epochs=20, validation_split=0.2)
Expected text output or note
Epoch 1/20
1719/1719 [==============================] - 14s 6ms/step - loss: 0.7172 - accuracy: 0.7635 - val_loss: 0.5121 - val_accuracy: 0.8246
Epoch 2/20
1719/1719 [==============================] - 6s 3ms/step - loss: 0.4911 - accuracy: 0.8294 - val_loss: 0.4867 - val_accuracy: 0.8204
Epoch 3/20
1719/1719 [==============================] - 5s 3ms/step - loss: 0.4473 - accuracy: 0.8433 - val_loss: 0.4261 - val_accuracy: 0.8530
Epoch 4/20
1719/1719 [==============================] - 6s 4ms/step - loss: 0.4184 - accuracy: 0.8545 - val_loss: 0.4224 - val_accuracy: 0.8552
Epoch 5/20
1719/1719 [==============================] - 5s 3ms/step - loss: 0.3992 - accuracy: 0.8588 - val_loss: 0.3741 - val_accuracy: 0.8718
Epoch 6/20
1719/1719 [==============================] - 6s 4ms/step - loss: 0.3831 - accuracy: 0.8651 - val_loss: 0.3749 - val_accuracy: 0.8678
Epoch 7/20
1719/1719 [==============================] - 6s 3ms/step - loss: 0.3689 - accuracy: 0.8702 - val_loss: 0.3631 - val_accuracy: 0.8756
Epoch 8/20
1719/1719 [==============================] - 6s 3ms/step - loss: 0.3556 - accuracy: 0.8747 - val_loss: 0.3483 - val_accuracy: 0.8800
Epoch 9/20
1719/1719 [==============================] - 5s 3ms/step - loss: 0.3452 - accuracy: 0.8786 - val_loss: 0.3641 - val_accuracy: 0.8728
Epoch 10/20
1719/1719 [==============================] - 6s 4ms/step - loss: 0.3358 - accuracy: 0.8797 - val_loss: 0.3379 - val_accuracy: 0.8818
Epoch 11/20
1719/1719 [==============================] - 5s 3ms/step - loss: 0.3273 - accuracy: 0.8831 - val_loss: 0.3397 - val_accuracy: 0.8794
Epoch 12/20
1719/1719 [==============================] - 6s 3ms/step - loss: 0.3194 - accuracy: 0.8855 - val_loss: 0.3276 - val_accuracy: 0.8862
Epoch 13/20
1719/1719 [==============================] - 6s 3ms/step - loss: 0.3104 - accuracy: 0.8887 - val_loss: 0.3331 - val_accuracy: 0.8804
Epoch 14/20
1719/1719 [==============================] - 5s 3ms/step - loss: 0.3039 - accuracy: 0.8912 - val_loss: 0.3253 - val_accuracy: 0.8876
Epoch 15/20
1719/1719 [==============================] - 6s 3ms/step - loss: 0.2979 - accuracy: 0.8927 - val_loss: 0.3202 - val_accuracy: 0.8870
Epoch 16/20
1719/1719 [==============================] - 5s 3ms/step - loss: 0.2911 - accuracy: 0.8947 - val_loss: 0.3279 - val_accuracy: 0.8842
Epoch 17/20
1719/1719 [==============================] - 6s 4ms/step - loss: 0.2858 - ac

[output shortened for documentation readability]

Listing 27. Inspect the metrics stored in the training history

Training updates model weights and stores the learning history for later inspection.

history.history.keys()
Expected text output or note
dict_keys(['loss', 'accuracy', 'val_loss', 'val_accuracy'])

Listing 28. Plot training and validation curves

Training updates model weights and stores the learning history for later inspection.

import pandas as pd
pd.DataFrame(history.history).plot(figsize=(8, 5))
plt.grid(True)
plt.ylim(0,1)
plt.show()
Expected text output or note
<Figure size 800x500 with 1 Axes>

[visual output omitted; run the code to display the image or chart]

Evaluation and Predictions

Listing 29. Evaluate the model on the test set

This defines or inspects part of the neural network architecture.

model.evaluate(X_test,y_test)
Expected text output or note
313/313 [==============================] - 1s 2ms/step - loss: 69.8466 - accuracy: 0.8355
[69.84664154052734, 0.8355000019073486]

Listing 30. Predict class probabilities for test images

Prediction applies the trained model to new data and returns probabilities or labels.

predictions=model.predict(X_test)
Expected text output or note
313/313 [==============================] - 1s 2ms/step

Listing 31. Inspect the raw probability matrix

This step supports the workflow shown in the surrounding listings.

predictions
Expected text output or note
array([[0., 0., 0., ..., 0., 0., 1.],
       [0., 0., 1., ..., 0., 0., 0.],
       [0., 1., 0., ..., 0., 0., 0.],
       ...,
       [0., 0., 0., ..., 0., 1., 0.],
       [0., 1., 0., ..., 0., 0., 0.],
       [0., 0., 0., ..., 0., 0., 0.]], dtype=float32)

Listing 32. Convert probabilities to predicted class indexes

Prediction applies the trained model to new data and returns probabilities or labels.

import numpy as np
y_pred=np.argmax(predictions,axis=-1)

Listing 33. Inspect predicted class indexes

Prediction applies the trained model to new data and returns probabilities or labels.

y_pred
Expected text output or note
array([9, 2, 1, ..., 8, 1, 5])

Listing 34. Convert predicted class indexes to readable class names

Prediction applies the trained model to new data and returns probabilities or labels.

np.array(class_names)[y_pred]
Expected text output or note
array(['Ankle boot', 'Pullover', 'Trouser', ..., 'Bag', 'Trouser',
       'Sandal'], dtype='<U11')

Listing 35. Display the first five test predictions

Prediction applies the trained model to new data and returns probabilities or labels.

for i in range(0,5):
  plt.subplot(151+i)
  plt.imshow(X_test[i], cmap='gray')
  plt.title(class_names[y_pred[i]])   # predicted class
plt.show()
Expected text output or note
<Figure size 640x480 with 5 Axes>

[visual output omitted; run the code to display the image or chart]

Listing 36. Print precision, recall, and F1-score for each fashion class

This step supports the workflow shown in the surrounding listings.

from sklearn.metrics import classification_report
print(classification_report(y_test,y_pred, target_names=class_names))
Expected text output or note
precision    recall  f1-score   support

 T-shirt/top       0.76      0.90      0.82      1000
     Trouser       0.92      0.98      0.95      1000
    Pullover       0.81      0.70      0.75      1000
       Dress       0.92      0.79      0.85      1000
        Coat       0.62      0.93      0.74      1000
      Sandal       0.98      0.91      0.94      1000
       Shirt       0.87      0.41      0.55      1000
     Sneaker       0.98      0.76      0.86      1000
         Bag       0.91      0.98      0.94      1000
  Ankle boot       0.79      1.00      0.88      1000

    accuracy                           0.84     10000
   macro avg       0.85      0.84      0.83     10000
weighted avg       0.85      0.84      0.83     10000

Listing 37. Build and display the confusion matrix

This evaluation step compares predicted classes with the true labels.

from sklearn import metrics
confusion_matrix_values = metrics.confusion_matrix(y_test, y_pred)

cm_display = metrics.ConfusionMatrixDisplay(confusion_matrix = confusion_matrix_values, display_labels = class_names)
fig, ax = plt.subplots(figsize=(10,10))
cm_display.plot(ax=ax)
plt.show()
Expected text output or note
<Figure size 1000x1000 with 2 Axes>

[visual output omitted; run the code to display the image or chart]

Back to overview