I'm trying to reshape some of my data with Dataset API. In particular, I have created a dataset like this:
dataset = tf.data.TFRecordDataset(filenames)
dataset = dataset.map(parse).filter(filter_empty).batch(batch_size)
After this if I print my shape within map function I get the following:
def print_shape(x):
print(x.shape)
dataset.map(print_shape)
>>> (?, ?, ?)
So the shape of the batch is not clear and hence if I want to reshape some of my variables by accessing them via x.shape
, it fails with an error:
TypeError: Failed to convert object of type <class 'list'> to Tensor. Contents: [1, 1, Dimension(None)]. Consider casting elements to a supported type.
How can I access shape within dataset creation so that I cam reshape some of my variables?
Another detail: I use eager mode.
Solved via using tf.shape
instead.
Solved via using
tf.shape
instead.
How did you use tf.shape to solve this issue?
I have been facing similar issues ,try using tf.expand_dims.
x=tf.expand_dims(x, -1)
This helped me sorting the issue.
Solved via using
tf.shape
instead.
How did you use tf.shape to solve this issue? could you please give more details about the solution?
@Liusandian @Shruthi-Sampathkumar
Let's assume x
is a Tensor of shape [10, ?, ?]. It can be a tensor with a undetermined size when it is TF 1.x, running non-eagerly on TF 2.x (e.g. using tf.function
+ autograph), or running inside tf.Dataset
(as in @nd7141's case).
x.shape
will give you [10, None, None]
. You cannot reshape it because you do not know the dimension statically. For example, some tensor manipulations tf.reshape(x, [-1, x.shape[1], x.shape[0]])
will fail.
However, h = tf.shape(x)[1]; w = tf.shape(x)[2]
will let h
, w
be symbolic or graph-mode tensors (integer) that will contain a dimension of x
. The value will be determined runtime. In such a case, tf.reshape(x, [-1, w, h])
will produce a (symbolic) tensor of shape [?, ?, ?]
(still unknown) whose tensor shape will be known on runtime.
TL;DR) tf.shape(x)
gives a tf.Tensor
of integer dtype whose elements are not None
(it is just undetermined), where as x.shape
gives a static value as a list/tuple. But if any shape dimension is unknown, it will be None
.
Most helpful comment
@Liusandian @Shruthi-Sampathkumar
Let's assume
x
is a Tensor of shape [10, ?, ?]. It can be a tensor with a undetermined size when it is TF 1.x, running non-eagerly on TF 2.x (e.g. usingtf.function
+ autograph), or running insidetf.Dataset
(as in @nd7141's case).x.shape
will give you[10, None, None]
. You cannot reshape it because you do not know the dimension statically. For example, some tensor manipulationstf.reshape(x, [-1, x.shape[1], x.shape[0]])
will fail.However,
h = tf.shape(x)[1]; w = tf.shape(x)[2]
will leth
,w
be symbolic or graph-mode tensors (integer) that will contain a dimension ofx
. The value will be determined runtime. In such a case,tf.reshape(x, [-1, w, h])
will produce a (symbolic) tensor of shape[?, ?, ?]
(still unknown) whose tensor shape will be known on runtime.TL;DR)
tf.shape(x)
gives atf.Tensor
of integer dtype whose elements are notNone
(it is just undetermined), where asx.shape
gives a static value as a list/tuple. But if any shape dimension is unknown, it will beNone
.