TensorFlow
convolution filters
visualization
deep learning
neural networks

How can visualize tensorflow convolution filters?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Visualizing convolution filters is a useful way to inspect what a CNN has learned, especially in the first layer where filters often resemble edge or texture detectors. In TensorFlow and Keras, the basic workflow is to access a convolution layer's weight tensor, normalize each filter, and render the channels as images.

Start with the Filter Weights

For a Conv2D layer, the kernel weights usually have shape:

text
(kernel_height, kernel_width, input_channels, output_channels)

That means each output channel corresponds to one learned filter bank across the input channels.

Example model:

python
1import tensorflow as tf
2from tensorflow import keras
3
4model = keras.Sequential([
5    keras.layers.Input(shape=(28, 28, 1)),
6    keras.layers.Conv2D(8, (3, 3), activation="relu"),
7    keras.layers.Conv2D(16, (3, 3), activation="relu"),
8])
9
10weights, biases = model.layers[0].get_weights()
11print(weights.shape)

For the first layer with grayscale input, the input-channel dimension is often 1, which makes visualization simpler.

Normalize Before Plotting

Raw filter weights are not guaranteed to sit in a display-friendly range. Normalize them before plotting.

python
1import numpy as np
2
3
4def normalize_filter(x):
5    x = x - x.min()
6    if x.max() != 0:
7        x = x / x.max()
8    return x

Without normalization, the filters may render as nearly black or nearly white images even though the learned structure is meaningful.

Plot First-Layer Filters

python
1import matplotlib.pyplot as plt
2
3weights, _ = model.layers[0].get_weights()
4
5num_filters = weights.shape[-1]
6fig, axes = plt.subplots(1, num_filters, figsize=(2 * num_filters, 2))
7
8for i in range(num_filters):
9    filt = weights[:, :, 0, i]
10    axes[i].imshow(normalize_filter(filt), cmap="gray")
11    axes[i].axis("off")
12    axes[i].set_title(f"F{i}")
13
14plt.tight_layout()
15plt.show()

This works well for grayscale input because each filter has one input channel.

RGB Filters Need Channel-Aware Display

If the input has three channels, each filter has RGB-like slices. You can visualize them as color images.

python
1rgb_model = keras.Sequential([
2    keras.layers.Input(shape=(32, 32, 3)),
3    keras.layers.Conv2D(4, (3, 3), activation="relu"),
4])
5
6weights, _ = rgb_model.layers[0].get_weights()
7
8fig, axes = plt.subplots(1, weights.shape[-1], figsize=(8, 2))
9for i in range(weights.shape[-1]):
10    filt = normalize_filter(weights[:, :, :, i])
11    axes[i].imshow(filt)
12    axes[i].axis("off")
13    axes[i].set_title(f"F{i}")
14
15plt.tight_layout()
16plt.show()

For later layers, direct interpretation becomes much harder because the filters are acting on learned feature maps rather than raw pixels.

Filters Versus Activations

Do not confuse filter visualization with activation visualization.

  • filters are the learned kernel weights
  • activations are the outputs produced when an input image passes through the network

If your real question is "what pattern does this layer respond to on a given image," then activation maps are usually more informative than the kernel images themselves.

First Layers Are the Most Interpretable

The first convolution layer often learns:

  • edge detectors
  • orientation-sensitive filters
  • simple texture detectors

Deeper filters are still important, but their raw weights are often less human-readable because they operate on abstract intermediate features.

So if you are using visualization for debugging or explanation, start with layer one.

Common Pitfalls

The biggest mistake is plotting raw weights without normalization. That usually produces unreadable images and makes the filters look meaningless.

Another issue is assuming later-layer filters should look like understandable edge kernels. Deep filters often are not visually interpretable in that direct way.

A third problem is confusing filters with feature maps and then drawing the wrong conclusion about what the network learned.

Summary

  • Get convolution weights with layer.get_weights().
  • Remember the kernel shape is height, width, input channels, output channels.
  • Normalize each filter before rendering it as an image.
  • First-layer filters are usually the easiest to interpret visually.
  • If the real goal is model response analysis, consider visualizing activations as well as filters.

Course illustration
Course illustration

All Rights Reserved.