In TensorFlow FAQ, it says:
In TensorFlow, a tensor has both a static (inferred) shape and a dynamic (true) shape. The static shape can be read using the tf.Tensor.get_shape() method: this shape is inferred from the operations that were used to create the tensor, and may be partially complete. If the static shape is not fully defined, the dynamic shape of a Tensor t can be determined by evaluating tf.shape(t).
But I still cannot fully understand the relationship between static shape and dynamic shape. Are there any examples showing their differences? Thanks.
To get the shape of a tensor, you can easily use the tf. shape() function. This method will help the user to return the shape of the given tensor.
A tensor is a vector or matrix of n-dimensions that represents all types of data. All values in a tensor hold identical data type with a known (or partially known) shape. The shape of the data is the dimensionality of the matrix or array. A tensor can be originated from the input data or the result of a computation.
Dynamic shapes derive their sizes and coordinates from their enclosing frames. When you resize a frame in the canvas, all derived shapes are resized/moved around, too. To suppress this behavior, hold down the COMMAND key while resizing the frame.
tf. shape returns a 1-D integer tensor representing the shape of input . For a scalar input, the tensor returned has a shape of (0,) and its value is the empty vector (i.e. []).
Sometimes the shape of a tensor depends on a value that is computed at runtime. Let's take the following example, where x
is defined as a tf.placeholder()
vector with four elements:
x = tf.placeholder(tf.int32, shape=[4]) print x.get_shape() # ==> '(4,)'
The value of x.get_shape()
is the static shape of x
, and the (4,
) means that it is a vector of length 4. Now let's apply the tf.unique()
op to x
y, _ = tf.unique(x) print y.get_shape() # ==> '(?,)'
The (?,)
means that y
is a vector of unknown length. Why is it unknown? tf.unique(x)
returns the unique values from x
, and the values of x
are unknown because it is a tf.placeholder()
, so it doesn't have a value until you feed it. Let's see what happens if you feed two different values:
sess = tf.Session() print sess.run(y, feed_dict={x: [0, 1, 2, 3]}).shape # ==> '(4,)' print sess.run(y, feed_dict={x: [0, 0, 0, 0]}).shape # ==> '(1,)'
Hopefully this makes it clear that a tensor can have a different static and dynamic shape. The dynamic shape is always fully defined—it has no ?
dimensions—but the static shape can be less specific. This is what allows TensorFlow to support operations like tf.unique()
and tf.dynamic_partition()
, which can have variable-sized outputs, and are used in advanced applications.
Finally, the tf.shape()
op can be used to get the dynamic shape of a tensor and use it in a TensorFlow computation:
z = tf.shape(y) print sess.run(z, feed_dict={x: [0, 1, 2, 3]}) # ==> [4] print sess.run(z, feed_dict={x: [0, 0, 0, 0]}) # ==> [1]
Here's a schematic image showing both:
Tensorflow 2.0 Compatible Answer: Mentioning the Code which mrry has specified in his Answer, in Tensorflow Version 2.x (> 2.0)
, for the benefit of the Community.
# Installing the Tensorflow Version 2.1 !pip install tensorflow==2.1 # If we don't Disable the Eager Execution, usage of Placeholder results in RunTimeError tf.compat.v1.disable_eager_execution() x = tf.compat.v1.placeholder(tf.int32, shape=[4]) print(x.get_shape()) # ==> 4 y, _ = tf.unique(x) print(y.get_shape()) # ==> (None,) sess = tf.compat.v1.Session() print(sess.run(y, feed_dict={x: [0, 1, 2, 3]}).shape) # ==> '(4,)' print(sess.run(y, feed_dict={x: [0, 0, 0, 0]}).shape) # ==> '(1,)' z = tf.shape(y) print(sess.run(z, feed_dict={x: [0, 1, 2, 3]})) # ==> [4] print(sess.run(z, feed_dict={x: [0, 0, 0, 0]})) # ==> [1]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With