Keras
CNN
variable input size
deep learning
neural networks

How to handle variable sized input in CNN with Keras?

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

Keras can handle variable-sized inputs in a CNN, but only if the architecture avoids layers that require a fixed flattened size too early. Convolution layers themselves can work with variable spatial dimensions. The constraint usually appears when you add Flatten and dense layers that expect a known number of features. The standard solution is to keep the network fully convolutional until a global pooling layer reduces the spatial dimensions to a fixed-size vector.

What "Variable Sized" Really Means

For images, variable size usually means height and width can differ between examples. In Keras, you can express that with None for the spatial dimensions.

python
1from tensorflow import keras
2from tensorflow.keras import layers
3
4inputs = keras.Input(shape=(None, None, 3))
5x = layers.Conv2D(32, 3, activation="relu")(inputs)
6x = layers.Conv2D(64, 3, activation="relu")(x)
7x = layers.GlobalAveragePooling2D()(x)
8outputs = layers.Dense(10, activation="softmax")(x)
9
10model = keras.Model(inputs, outputs)
11model.summary()

This works because the convolution layers operate locally, and GlobalAveragePooling2D converts any final feature map size into one fixed-length vector per channel.

Why Flatten Usually Breaks It

A model like this does not support variable image sizes cleanly:

python
1inputs = keras.Input(shape=(None, None, 3))
2x = layers.Conv2D(32, 3, activation="relu")(inputs)
3x = layers.Flatten()(x)
4outputs = layers.Dense(10, activation="softmax")(x)

Flatten turns the entire spatial map into one long vector. If the image size changes, the vector length changes, and the dense layer no longer knows how many input units it should expect.

That is why global pooling is the usual replacement.

Batching Still Needs a Strategy

Even if the model accepts variable sizes in principle, a normal tensor batch still needs samples of the same shape within that batch. You have three common options:

  • resize all images to one fixed size
  • pad images to a common size within each batch
  • bucket images by similar shapes and batch them together

A padded tf.data pipeline is often the practical middle ground.

python
1import tensorflow as tf
2
3images = [tf.random.uniform((32, 40, 3)), tf.random.uniform((28, 50, 3))]
4labels = [1, 0]
5
6def generator():
7    for image, label in zip(images, labels):
8        yield image, label
9
10dataset = tf.data.Dataset.from_generator(
11    generator,
12    output_signature=(
13        tf.TensorSpec(shape=(None, None, 3), dtype=tf.float32),
14        tf.TensorSpec(shape=(), dtype=tf.int32),
15    ),
16)
17
18dataset = dataset.padded_batch(
19    2,
20    padded_shapes=([None, None, 3], []),
21)

The model still sees valid tensors, but padding lets examples with different sizes live in the same batch.

When Resizing Is the Better Choice

For many image-classification problems, resizing inputs to a standard resolution is still the best engineering choice. It simplifies batching, improves throughput, and makes pretrained backbones easier to reuse.

Variable-size support is most valuable when resizing would distort the signal too much, such as in document images, medical scans, or detection-style pipelines.

In other words, do not use variable-sized input just because it is possible. Use it when it preserves important information.

Common Pitfalls

  • Declaring Input(shape=(None, None, 3)) and then adding Flatten before global pooling.
  • Forgetting that batches still need compatible tensor shapes unless you pad or bucket them.
  • Assuming pretrained models always support arbitrary input sizes for every use case.
  • Mixing variable-size inputs with augmentation code that expects one fixed resolution.
  • Choosing variable-sized training when simple resizing would be faster and good enough.

Summary

  • Convolution layers can handle variable spatial dimensions.
  • The usual blocker is Flatten plus dense layers that require a fixed vector length.
  • Use GlobalAveragePooling2D or GlobalMaxPooling2D to convert variable feature maps into fixed-size outputs.
  • Plan batching explicitly with resizing, padding, or bucketing.
  • Variable-sized input is a design choice, not a default requirement.

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.