scai scai - 10 months ago 185
C++ Question

In Tensorflow's C++ TensorShape API, what is the equivalent of Python's None?

Suppose I have a tensor created with the Python API of Tensorflow, as follows,

x = tf.placeholder("float", shape=[None, inputLen])

I would like to create a tensorflow::Tensor equivalent of that in C++, so that I can run a trained graph that takes x as the input. What should I do with the first dimension of the input shape, which in C++ is of type tensorflow::TensorShape?

If I do:

tensorflow::TensorShape inputShape;

it doesn't seem to work, because num_elements becomes 0, which is not the value of inputLen that I expect.

Answer Source

Update: There is now a tensorflow::PartialTensorShape class that can represent shapes with unknown dimensions or an unknown rank. The value -1 is used to represent an unknown value (i.e. what None represents in Python). It is used in the C++ shape inference code, and can be specified in a shape-typed attr or a tf.TensorShape proto.

TL;DR: There is no equivalent in C++ because the C++ part of TensorFlow only checks shapes at runtime, when they are fully defined; whereas the Python part checks shapes at graph-construction time, when they might not be fully defined.

There is no equivalent of tf.Dimension(None) (i.e., an unknown dimension) in the C++ tensorflow::TensorShape class. This is because the (C++) tensorflow::TensorShape class describes the shape of a (C++) tensorflow::Tensor, which represents a concrete value for a tensor, and therefore must have a fully defined shape. The Python tf.Tensor class represents a symbolic tensor—representing the output of an operation that has yet to be run—and so it can have a shape that is unknown in one or more dimensions.

If you are using the C++ API to feed a placeholder, you should simply create a new tensorflow::Tensor with a fully defined shape for each different value that you feed to the placeholder (in a Session::Run() call). Note however that the C++ API does not check shapes of placeholders, so you should manually ensure that the shape matches the expected shape for the placeholder.

If you are building a graph using the C++ API, and you want to define a placeholder with an unknown size in one or more dimensions, you should define a placeholder node with its shape attr set to tensorflow::TensorShape({}). Although this is equivalent to a scalar, for historical reasons this is treated as the shape being completely unconstrained.