tensorflow
tensor
unspecified dimension
machine learning
deep learning

Tensor with unspecified dimension in tensorflow

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, an unspecified dimension usually appears as None in a shape. It means TensorFlow knows the rank and most dimensions, but one dimension will be determined later at runtime. This is common for batch size, sequence length, or any axis whose exact length is not fixed when the graph or model is defined.

What None Means in a Tensor Shape

When you see a shape such as (None, 128), TensorFlow is saying:

  • this tensor has rank 2
  • the second dimension is always 128
  • the first dimension is unknown at definition time

The most common unknown dimension is the batch axis. A model can accept batches of size 1, 16, or 64 without redefining the computation graph.

In Keras, this is normal:

python
1import tensorflow as tf
2
3inputs = tf.keras.Input(shape=(128,))
4model = tf.keras.Model(inputs, inputs)
5
6print(model.input_shape)

The printed input shape is typically (None, 128). Keras leaves the batch dimension unspecified by default.

Use Unspecified Dimensions in TensorSpec

tf.TensorSpec is often used in tf.function signatures and dataset pipelines. It can describe a tensor whose size is partially known.

python
1import tensorflow as tf
2
3spec = tf.TensorSpec(shape=(None, 4), dtype=tf.float32)
4print(spec)

That specification accepts any two-dimensional float tensor whose second dimension is 4.

You can use it in a traced function:

python
1import tensorflow as tf
2
3@tf.function(input_signature=[tf.TensorSpec(shape=(None, 4), dtype=tf.float32)])
4def row_sums(x):
5    return tf.reduce_sum(x, axis=1)
6
7value = tf.constant([[1.0, 2.0, 3.0, 4.0]])
8print(row_sums(value))

This works for any number of rows, as long as each row has length 4.

Unspecified Does Not Mean Arbitrary Structure

An unspecified dimension is still a single dense dimension. It does not mean each row can have a different length. For example, (None, 4) allows many rows, but each row must still have four values.

If you need variable-length rows, you are dealing with ragged data, not just an unspecified dense dimension. That is where tf.RaggedTensor or padded batches become relevant.

python
1import tensorflow as tf
2
3ragged = tf.ragged.constant([
4    [1, 2, 3],
5    [4, 5],
6])
7
8print(ragged)

That solves a different problem from a dense tensor with one unknown axis size.

Common Places You See None

You will most often encounter unspecified dimensions in these situations:

  • model input shapes where batch size is not fixed
  • sequence models where time length varies
  • dataset signatures defined with TensorSpec
  • functions traced with tf.function

Example with a variable-length time axis:

python
1import tensorflow as tf
2
3inputs = tf.keras.Input(shape=(None, 16))
4x = tf.keras.layers.Masking()(inputs)
5x = tf.keras.layers.LSTM(32)(x)
6model = tf.keras.Model(inputs, x)
7
8print(model.input_shape)

Here the batch dimension is unspecified, and the sequence-length dimension is also unspecified. The feature size, 16, stays fixed.

Static Shape Versus Runtime Shape

TensorFlow tracks both a static shape and a runtime shape. Static shape is what TensorFlow can infer when building the graph. Runtime shape is what the tensor actually has when real data flows through the computation.

You can inspect the runtime shape like this:

python
1import tensorflow as tf
2
3x = tf.ones((3, 4))
4print(x.shape)
5print(tf.shape(x))

x.shape is the static shape metadata visible in Python. tf.shape(x) is a TensorFlow operation that produces the runtime dimensions.

Refine Shape Information When Needed

Sometimes TensorFlow knows less than you do. If a transformation preserves a dimension that TensorFlow cannot infer, you can refine the metadata with set_shape.

python
1import tensorflow as tf
2
3x = tf.constant([1, 2, 3, 4], dtype=tf.int32)
4x = tf.reshape(x, (-1, 2))
5x.set_shape((None, 2))
6
7print(x.shape)

Use this carefully. If you assert the wrong shape, later operations can fail in harder-to-debug ways.

Common Pitfalls

One common mistake is thinking None means completely unconstrained data. It only marks a dimension whose exact size is deferred. Another is confusing an unspecified dense dimension with truly variable inner lengths, which requires ragged tensors or padding. Developers also rely on tensor.shape for runtime decisions inside graph code, even though tf.shape is often the correct tool there. Finally, manually forcing shape metadata with set_shape can create misleading assumptions if the underlying data does not actually match.

Summary

  • In TensorFlow, None in a shape means the dimension is unknown at definition time.
  • The most common unspecified dimension is batch size.
  • 'TensorSpec and Keras input shapes frequently use unspecified dimensions.'
  • An unspecified dense dimension is different from ragged variable-length inner data.
  • Use tf.shape to inspect runtime dimensions when needed.
  • Refine shape metadata carefully and only when you know the true shape constraints.

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.