Keras
TensorFlow
Subsample
Machine Learning
Deep Learning

How can implement subsample like keras in tensorflow?

Master System Design with Codemia

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

Introduction

In older Keras code, convolution examples sometimes used the term subsample for spatial downsampling. In modern TensorFlow and Keras, the equivalent idea is usually expressed with strides on convolution layers or with explicit pooling layers. The right replacement depends on whether you want the downsampling to be part of the convolution itself or handled by a separate layer.

What subsample meant historically

In legacy Keras APIs, subsample controlled the step size of a convolution over height and width. In current APIs, that behavior maps to strides.

So a legacy idea like “subsample by 2” usually becomes:

python
strides=(2, 2)

inside a Conv2D layer.

Modern Keras replacement with strides

python
1import tensorflow as tf
2from tensorflow.keras import layers, models
3
4model = models.Sequential([
5    layers.Input(shape=(128, 128, 3)),
6    layers.Conv2D(32, kernel_size=3, strides=(2, 2), padding='same', activation='relu'),
7    layers.Conv2D(64, kernel_size=3, strides=(2, 2), padding='same', activation='relu'),
8    layers.GlobalAveragePooling2D(),
9    layers.Dense(10, activation='softmax')
10])
11
12model.summary()

This is the most direct equivalent when the old model used subsampling as part of convolution.

Low-level TensorFlow equivalent

If you are working below Keras layers, use explicit stride values in tf.nn.conv2d.

python
1import tensorflow as tf
2
3x = tf.random.normal([1, 64, 64, 3])
4filters = tf.random.normal([3, 3, 3, 16])
5
6y = tf.nn.conv2d(
7    input=x,
8    filters=filters,
9    strides=[1, 2, 2, 1],
10    padding='SAME'
11)
12
13print(y.shape)

The stride format includes batch and channel dimensions, so the spatial stride sits in the middle.

Pooling as an alternative

Not every old “subsample” use case should become strided convolution. Sometimes the better modern equivalent is an explicit pooling layer.

python
1import tensorflow as tf
2
3model = tf.keras.Sequential([
4    tf.keras.layers.Input(shape=(128, 128, 3)),
5    tf.keras.layers.Conv2D(32, 3, padding='same', activation='relu'),
6    tf.keras.layers.MaxPooling2D(pool_size=(2, 2)),
7    tf.keras.layers.Conv2D(64, 3, padding='same', activation='relu'),
8    tf.keras.layers.MaxPooling2D(pool_size=(2, 2)),
9])

Use pooling when you want a non-learned downsampling step rather than convolutional subsampling.

When to use strided convolution versus pooling

Use strided convolution when:

This choice is architectural, not just syntactic. Two models can have the same output shape and still behave differently depending on whether downsampling happened through learned convolution weights or fixed pooling behavior.

  • you want the downsampling to be learned
  • you are following an architecture that reduces spatial size through convolutional steps
  • you want fewer separate layers

Use pooling when:

  • you want explicit feature aggregation
  • you are following a classic conv-plus-pool architecture
  • you want a non-learned reduction step

Both reduce spatial resolution, but they are not interchangeable in model behavior.

Validate shapes during migration

When replacing legacy subsample code, check layer output shapes carefully.

Many migrations look syntactically correct while silently changing tensor shapes, receptive field behavior, or feature statistics. Running a small sample forward pass is a cheap way to catch those mistakes early.

python
sample = tf.random.normal([1, 128, 128, 3])
output = model(sample)
print(output.shape)

Migration bugs often come from shape mismatches, not just syntax problems.

Common Pitfalls

A common mistake is trying to use the old subsample argument directly in modern TensorFlow/Keras code.

Another migration risk is assuming every old example meant pooling-like behavior when in fact the original model relied on learned downsampling inside the convolution.

Another mistake is replacing subsampling blindly with pooling when the original architecture intended strided convolution.

A third mistake is forgetting that stride definitions differ between high-level Keras layers and low-level TensorFlow ops.

Summary

  • Legacy Keras subsample behavior usually maps to modern strides.
  • Use strides=(2, 2) in Conv2D for convolutional downsampling.
  • Use pooling layers when you want explicit non-learned spatial reduction.
  • Check output shapes during migration.
  • Treat migration as a semantic change review, not just a keyword replacement.
  • Confirm that the replacement preserves the intended downsampling behavior.

Course illustration
Course illustration

All Rights Reserved.