tensorflow
placeholder
shape attribute
deep learning
machine learning

tensorflow placeholder - understanding shapeNone,

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

In TensorFlow 1 style graph code, shape=[None, 784] means the tensor rank and some dimensions are known, but the first dimension is intentionally left flexible. None is not a literal numeric size. It is a placeholder for "any size at runtime", which is why it is commonly used for batch dimensions.

What None Means in a Placeholder Shape

With placeholders, the shape argument is a static shape constraint. TensorFlow uses it to validate what may be fed into the graph later.

For example:

python
1import tensorflow as tf
2
3tf.compat.v1.disable_eager_execution()
4
5x = tf.compat.v1.placeholder(tf.float32, shape=[None, 784], name="x")
6print(x.shape)

This does not mean the tensor currently contains an unknown number of rows. It means TensorFlow will accept any runtime batch size, as long as every example still has 784 features.

Valid runtime feeds include:

  • '(1, 784)'
  • '(32, 784)'
  • '(1000, 784)'

Invalid feeds include:

  • '(32, 100) because the second dimension is wrong'
  • '(784,) because the rank is wrong'

Why the First Dimension Is Often None

The first dimension usually represents batch size. Hard-coding it to one number makes the graph less reusable.

python
x = tf.compat.v1.placeholder(tf.float32, shape=[None, 10])
w = tf.Variable(tf.ones([10, 1]))
y = tf.matmul(x, w)

The same graph can now process one example, a mini-batch of 64, or a full evaluation batch of 1000 rows without being rebuilt.

That is the main point of None here: flexible feeding with fixed structure where it matters.

shape=None Is Different from [None, ...]

This distinction matters a lot.

python
x = tf.compat.v1.placeholder(tf.float32, shape=None)

This means TensorFlow places almost no static shape restriction on the placeholder. Rank and dimensions are all unknown until runtime.

By contrast:

python
x = tf.compat.v1.placeholder(tf.float32, shape=[None, 784])

means rank two is required, and only the first dimension is flexible.

The more precisely you declare shape, the more helpful TensorFlow can be when catching mistakes early.

Multiple None Dimensions

You can use None in more than one place when several dimensions are dynamic.

python
images = tf.compat.v1.placeholder(tf.float32, shape=[None, None, None, 3])

This could represent a batch of RGB images where batch size, height, and width are variable but the channel count is fixed at 3.

That flexibility is useful, but it can also reduce static shape information for later layers. Only keep dimensions dynamic when they truly need to be dynamic.

Runtime Example

The placeholder accepts any batch size that fits the declared shape.

python
1import numpy as np
2import tensorflow as tf
3
4tf.compat.v1.disable_eager_execution()
5
6x = tf.compat.v1.placeholder(tf.float32, shape=[None, 2])
7y = x * 2
8
9with tf.compat.v1.Session() as sess:
10    batch = np.array([[1.0, 2.0], [3.0, 4.0]], dtype="float32")
11    print(sess.run(y, feed_dict={x: batch}))

If you feed a (2, 2) array, the graph runs. If you feed a one-dimensional vector, TensorFlow raises a shape error.

How This Maps to TensorFlow 2

Current TensorFlow guidance treats placeholders as a TensorFlow 1 compatibility API. In TensorFlow 2, eager execution is standard, and placeholders are usually replaced by:

  • direct tensor arguments
  • 'tf.keras.Input'
  • 'tf.TensorSpec in tf.function'

So if you are reading old code, None still means a flexible dimension. But in new code, you will usually express the same idea through input specs rather than through tf.compat.v1.placeholder.

Common Pitfalls

A common mistake is thinking None means the dimension can be missing entirely. It does not. It means the size is unknown until runtime, but the dimension still exists.

Another mistake is using shape=None when only one dimension needs flexibility. That throws away useful validation and makes shape bugs harder to catch.

People also often assume placeholder-based code is idiomatic TensorFlow 2. It is not. In current TensorFlow, placeholders belong mainly to compatibility mode.

Finally, do not confuse static shape declarations with actual runtime tensor values. None is a graph constraint placeholder, not a runtime data value.

Summary

  • In placeholder shapes, None means a dimension can vary at runtime.
  • 'shape=[None, 784] fixes rank and feature size while leaving batch size flexible.'
  • 'shape=None is much looser and removes most static shape checking.'
  • Multiple None dimensions are allowed when several axes are dynamic.
  • In TensorFlow 2, the same idea is usually expressed with tf.keras.Input or tf.TensorSpec instead of placeholders.

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.