TensorFlow
asymmetric padding
machine learning
neural networks
deep learning

Tensorflow's asymmetric padding assumptions

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

TensorFlow's padding="SAME" does not always mean perfectly symmetric padding. When the required total padding is odd, TensorFlow must put the extra element on one side, which makes the padding asymmetric.

That detail matters when you are trying to match another framework, reproduce a paper, or convert a model from one runtime to another. If you assume "same" always means equal padding on both sides, shape math and output values can drift.

What SAME Actually Means

For convolution and pooling, SAME means TensorFlow chooses padding so that the output size follows the standard ceil(input / stride) rule. With stride 1, that usually preserves spatial dimensions. With larger strides, the output can still shrink even though the mode is called SAME.

The total padding per dimension is computed from:

  • input size
  • filter size
  • stride

If the total padding is even, TensorFlow can split it evenly. If it is odd, the split becomes asymmetric.

Where the Extra Padding Goes

In TensorFlow's default behavior for spatial operations, the extra padding element goes to the bottom or right side when an odd amount is required. So the split is effectively:

  • top gets floor(total_pad / 2)
  • bottom gets the remainder
  • left gets floor(total_pad / 2)
  • right gets the remainder

That convention is easy to miss because many high-level APIs only expose "SAME" and "VALID" rather than the exact padding numbers.

Reproducing SAME Manually

If you need explicit control, pad the tensor yourself and then run a VALID convolution. The following example mirrors TensorFlow's asymmetric behavior for a 3 x 3 kernel on a 4 x 4 input with stride 2.

python
1import tensorflow as tf
2
3x = tf.reshape(tf.range(1, 17, dtype=tf.float32), [1, 4, 4, 1])
4kernel = tf.ones([3, 3, 1, 1], dtype=tf.float32)
5
6same_result = tf.nn.conv2d(x, kernel, strides=[1, 2, 2, 1], padding="SAME")
7
8padded = tf.pad(x, [[0, 0], [0, 1], [0, 1], [0, 0]])
9valid_result = tf.nn.conv2d(padded, kernel, strides=[1, 2, 2, 1], padding="VALID")
10
11print(tf.reduce_all(tf.equal(same_result, valid_result)).numpy())
12print(same_result.numpy())

The important part is the manual padding matrix. In this case the extra row and column are added after the existing data, not before it.

Why This Matters in Practice

This shows up in several real situations:

  • porting models from libraries that center padding differently
  • writing custom CUDA or inference kernels
  • debugging off-by-one shape mismatches in encoder-decoder networks
  • converting between NHWC and NCHW pipelines with explicit padding layers

It also matters when you are matching pretrained weights. A one-pixel shift at several layers can materially change the final prediction.

Prefer Explicit Padding When Exactness Matters

If model equivalence is important, use tf.pad with known values instead of relying on implicit SAME. That makes the code self-documenting and avoids ambiguity during export or framework conversion.

Example with explicit asymmetric padding before a Keras layer:

python
1import tensorflow as tf
2
3inputs = tf.keras.Input(shape=(4, 4, 1))
4x = tf.keras.layers.Lambda(
5    lambda t: tf.pad(t, [[0, 0], [1, 0], [2, 1], [0, 0]])
6)(inputs)
7x = tf.keras.layers.Conv2D(8, kernel_size=3, padding="valid")(x)
8model = tf.keras.Model(inputs, x)
9
10print(model.output_shape)

This removes guesswork. Anyone reading the model can see exactly where the padding goes.

Common Pitfalls

  • Assuming padding="SAME" always means identical padding on both sides.
  • Forgetting that stride greater than 1 can still reduce output size under SAME.
  • Trying to match another framework without checking its padding convention.
  • Debugging only tensor shapes and not the spatial shift introduced by asymmetric padding.
  • Hiding critical padding behavior inside implicit layer defaults when explicit tf.pad would be clearer.

Summary

  • TensorFlow SAME padding can be asymmetric when total padding is odd.
  • The extra padding element is placed on the bottom or right side.
  • 'SAME preserves dimensions only in the stride-1 sense; larger strides still shrink output.'
  • Use explicit tf.pad plus VALID convolution when exact padding layout matters.
  • Padding conventions are important when reproducing models across frameworks.

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.