TensorFlow
Tensor Manipulation
Padding Tensors
Machine Learning
Data Preprocessing

TensorFlow - Pad unknown size tensor to a specific size?

Master System Design with Codemia

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

Introduction

Padding a tensor of unknown runtime size to a fixed target size is a common TensorFlow task in preprocessing and batching. The core idea is to compute the current shape dynamically with tf.shape, compare it to the desired size, and then build the paddings tensor that tf.pad expects.

Use Dynamic Shape Information

Static shapes such as tensor.shape are often incomplete when dimensions are unknown at graph build time. For padding logic, use tf.shape(tensor) so the code works with runtime sizes.

Here is a simple example that pads a 2D tensor to a target height and width.

python
1import tensorflow as tf
2
3
4def pad_to_size(x, target_rows, target_cols, pad_value=0):
5    current_shape = tf.shape(x)
6    row_pad = tf.maximum(target_rows - current_shape[0], 0)
7    col_pad = tf.maximum(target_cols - current_shape[1], 0)
8
9    paddings = [
10        [0, row_pad],
11        [0, col_pad],
12    ]
13
14    return tf.pad(x, paddings, constant_values=pad_value)
15
16
17x = tf.constant([[1, 2, 3], [4, 5, 6]], dtype=tf.int32)
18y = pad_to_size(x, 4, 5)
19print(y)

The call to tf.maximum is important because tf.pad does not accept negative padding.

Padding Only Works When the Tensor Is Smaller

tf.pad can extend a tensor, but it cannot shrink one. If the input may be larger than the target size, you must decide on a policy:

  • raise an error
  • crop first, then pad
  • clip to the target dimensions

A common helper combines cropping with padding so the output size is always fixed.

python
1import tensorflow as tf
2
3
4def crop_or_pad_2d(x, target_rows, target_cols, pad_value=0):
5    x = x[:target_rows, :target_cols]
6    current_shape = tf.shape(x)
7
8    paddings = [
9        [0, tf.maximum(target_rows - current_shape[0], 0)],
10        [0, tf.maximum(target_cols - current_shape[1], 0)],
11    ]
12
13    return tf.pad(x, paddings, constant_values=pad_value)
14
15
16x = tf.constant([[1, 2, 3], [4, 5, 6]], dtype=tf.int32)
17print(crop_or_pad_2d(x, 3, 5))

This is often the real requirement in ML pipelines: normalize every item to the same output shape no matter whether the input is too short or too long.

Build the paddings Tensor Carefully

tf.pad expects one [before, after] pair per dimension. For a rank-3 tensor shaped like (time, height, width), the padding description would have three rows.

python
1import tensorflow as tf
2
3
4def pad_time_height_width(x, target_time, target_height, target_width):
5    shape = tf.shape(x)
6    paddings = [
7        [0, tf.maximum(target_time - shape[0], 0)],
8        [0, tf.maximum(target_height - shape[1], 0)],
9        [0, tf.maximum(target_width - shape[2], 0)],
10    ]
11    return tf.pad(x, paddings)

The rule is simple but easy to get wrong: the paddings structure must match the rank exactly.

Use Dataset Pipelines When Shapes Vary Per Example

If this operation happens as part of a tf.data pipeline, put the padding logic inside map so every element is normalized before batching.

python
1import tensorflow as tf
2
3
4def preprocess(x):
5    x = crop_or_pad_2d(x, 8, 8)
6    return tf.cast(x, tf.float32)
7
8
9dataset = tf.data.Dataset.from_generator(
10    lambda: [tf.ones((2, 3)), tf.ones((5, 6))],
11    output_signature=tf.TensorSpec(shape=(None, None), dtype=tf.float32),
12)
13
14dataset = dataset.map(preprocess)
15for item in dataset:
16    print(item.shape)

This pattern keeps the rest of the training code simple because every downstream tensor has a consistent shape.

Prefer Specialized Helpers When They Exist

For some common image cases, TensorFlow already provides helpers such as tf.image.resize_with_pad or tf.image.resize_with_crop_or_pad. Those can be simpler than writing raw tf.pad logic yourself.

Use manual padding when:

  • the tensor is not an image
  • the padding policy is custom
  • you need direct control over dimensions and fill value

Otherwise, the specialized helper is often clearer.

Shape Debugging Tips

When padding fails, print both the dynamic shape and the generated paddings tensor. Most bugs come from rank mismatch or from assuming a dimension is known when it is actually None.

That is why tf.shape belongs in the main logic rather than as an afterthought.

Common Pitfalls

A common mistake is using tensor.shape for unknown dimensions. That may return None, which does not work for runtime arithmetic.

Another mistake is passing negative padding values because the input is larger than the target. tf.pad only grows tensors.

Developers also mis-specify the rank by giving the wrong number of padding rows.

Finally, avoid writing generic padding code without deciding what should happen when the input is already too large. Padding and cropping are different operations and should be handled explicitly.

Summary

  • Use tf.shape to get dynamic tensor sizes at runtime.
  • Compute padding amounts with tf.maximum(target - current, 0).
  • Build one padding pair per tensor dimension.
  • Crop first if the tensor may be larger than the target size.
  • Put the normalization step into tf.data pipelines when variable-sized inputs are batched.

Course illustration
Course illustration

All Rights Reserved.