Representing the learned weights of MNIST using Tensorflow graphically
ML System Design practice on Codemia
Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.
Introduction
Visualizing learned weights is one of the simplest ways to inspect what a neural network has actually stored during training. With MNIST, this works especially well because each input image is small, grayscale, and has a fixed 28 x 28 structure. For some layers, you can turn the weights back into images and inspect which pixel patterns a neuron is responding to.
The most important detail is that not every layer can be visualized the same way. A dense layer connected directly to pixels can often be reshaped into an image. A convolutional layer already stores spatial kernels, so you visualize filters instead. Once you know which tensor you are looking at, the plots become much easier to interpret.
Start with a Simple Dense Model
The cleanest example is a small fully connected model that receives flattened MNIST images. In that setup, each neuron in the first hidden layer has one weight per input pixel.
After training, the first dense layer has a kernel of shape 784 x 16. That means:
784input pixels per neuron16hidden neurons
Each column of that matrix is one neuron's learned view of the input image.
Extract the Learned Weights
Keras exposes layer weights through get_weights(). For a dense layer, the result is usually:
- the kernel matrix
- the bias vector
If you want to visualize neuron i, select column i from the kernel and reshape it back into the original image size:
That gives a 28 x 28 array that can be plotted with matplotlib.
Plot Weight Maps as Images
The following example shows all 16 hidden neurons in a 4 x 4 grid:
A diverging colormap such as seismic, coolwarm, or bwr is usually better than a grayscale map for weights. Positive and negative values matter in different ways, so it helps to show both directions clearly.
What you often see are blurry stroke-like templates rather than whole digits. That is expected. Early hidden units usually learn fragments such as vertical bars, loops, edge regions, or diagonal strokes.
What These Images Actually Mean
This is where people often over-interpret the plots. A dense neuron's weight image is not the same thing as "the digit the neuron likes." It is more accurate to think of it as a learned linear pattern over the input pixels before the activation function is applied.
For example:
- bright positive areas mean those pixels push the neuron upward
- dark negative areas mean those pixels suppress the neuron
- near-zero areas contribute little
So if a neuron has a bright vertical band in the center, it may respond strongly to digits containing a central stroke. But the final behavior still depends on the rest of the network, not just that one image.
It is also worth noting that the output layer is different. Its weights connect hidden activations to class scores, not raw pixels, so reshaping those weights into 28 x 28 images usually does not make sense.
Convolutional Models Should Be Visualized Differently
If you train a convolutional network on MNIST, the first layer does not store a 784 x N matrix. Instead, it stores small filters such as 3 x 3 x 1 x 8, which means:
- kernel height
3 - kernel width
3 - one input channel
- eight output filters
Here is a small convolutional example:
To plot those filters, select each output channel:
In a convolutional model, these filter plots are usually more meaningful than trying to force everything into full-image weight maps.
Common Pitfalls
The most common mistake is reshaping the wrong tensor. Only layers directly connected to flattened pixel inputs have weights that naturally reshape back to 28 x 28.
Another issue is plotting untrained weights and expecting structure. Before training, the images mostly show random initialization noise.
A third mistake is ignoring scaling. If the colormap range changes from plot to plot, visual comparisons become misleading. When comparing neurons, it can help to fix vmin and vmax across all subplots.
Finally, weight visualization is not the same as activation visualization. Weights tell you what was learned in the parameters. Activations tell you how a specific input image excites the network. Both are useful, but they answer different questions.
Summary
- For a dense MNIST model, first-layer weights can often be reshaped into
28 x 28images. get_weights()returns the kernel matrix and bias vector for a layer.- Each dense neuron corresponds to one column of the kernel matrix.
- Convolutional models should usually be visualized through their learned filters instead.
- Weight plots are a helpful inspection tool, but they should be interpreted as parameter patterns, not literal digit templates.
Related reading
- Reproducible results in Tensorflow with tf.set_random_seed
- Reproducible results using Keras with TensorFlow backend
- Requiring tensorflow with Python 2.7.11 occurs ImportError
- Reset all weights of Keras model
- Reproduce Fisher linear discriminant figure
- Request for example Recurrent neural network for predicting next value in a sequence
- Rescaling after feature scaling, linear regression
- Reshape a Table to Convert Rows to Columns
.png&w=3840&q=75)
Tackling System Design Interview Problems
A short course that equips you with the skills to approach system design interviews methodically.
Start the free courseTrack 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.