7

I have a neural network, from a tf.data data generator and a tf.keras model, as follows (a simplified version-because it would be too long):

dataset = ...

A tf.data.Dataset object that with the next_x method calls the get_next for the x_train iterator and for the next_y method calls the get_next for the y_train iterator. Each label is a (1, 67) array in one-hot form.

Layers:

input_tensor = tf.keras.layers.Input(shape=(240, 240, 3))  # dim of x
output = tf.keras.layers.Flatten()(input_tensor)
output= tf.keras.Dense(67, activation='softmax')(output)  # 67 is the number of classes

Model:

model = tf.keras.models.Model(inputs=input_tensor, outputs=prediction)
model.compile(optimizer=tf.train.AdamOptimizer(), loss=tf.losses.softmax_cross_entropy, metrics=['accuracy'])
model.fit_generator(gen(dataset.next_x(), dataset.next_y()), steps_per_epochs=100)

gen is defined like this:

def gen(x, y):
    while True:
        yield(x, y)

My problem is that when I try to run it, I get an error in the model.fit part:

ValueError: Cannot take the length of Shape with unknown rank.

Any ideas are appreciated!

Mihai Chelaru
  • 7,614
  • 14
  • 45
  • 51
Cna
  • 147
  • 2
  • 9
  • I have the same error. I am reading the tfrecords through the dataset api and pass the result to the model.fit method but it gives the same error as above. Did you figure out how to resolve this? – user238607 Dec 19 '18 at 08:11
  • @user238607, what are the types and shapes of the records yielded by the dataset? – Daniel Möller Dec 19 '18 at 12:19
  • Would you share the functions that generate the data? – Daniel Möller Dec 19 '18 at 12:25
  • have you tried calling `next_x()` and `next_y()` inside your generator instead of calling it through arguments? – pouyan Dec 19 '18 at 12:34
  • @DanielMöller : I have asked my question separately here : https://stackoverflow.com/questions/53851793/valueerror-cannot-take-the-length-of-shape-with-unknown-rank Could you take a look ? – user238607 Dec 19 '18 at 13:00

3 Answers3

2

Could you post a longer stack-trace? I think your problem might be related to this recent tensorflow issue:

https://github.com/tensorflow/tensorflow/issues/24520

There's also a simple PR that fixes it (not yet merged). Maybe try it out yourself?

EDIT

Here is the PR: open tensorflow/python/keras/engine/training_utils.py

replace the following (line 232 at the moment):

  if (x.shape is not None
      and len(x.shape) == 1

with this:

  if tensor_util.is_tensor(x):
    x_shape_ndims = x.shape.ndims if x.shape is not None else None
  else:
    x_shape_ndims = len(x.shape)

  if (x_shape_ndims == 1
H4CKY
  • 564
  • 4
  • 12
  • 2
    While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. - [From Review](/review/low-quality-posts/21777204) – Bsquare ℬℬ Dec 26 '18 at 08:56
  • Edited to include the PR changes – H4CKY Dec 26 '18 at 09:05
1

I found out what was wrong. Actually I have to run next batch in a tf.Session before yielding it. Here is how it works (I don't write the rest of the code, since it stays the same):

model.fit_generator(gen(), steps_per_epochs=100)

def gen():
    with tf.Session() as sess:
        next_x = dataset.next_x()
        next_y = dataset.next_y()
        while True:
            x_batch = sess.run(next_x)
            y_batch = sess.run(next_y)
            yield x_batch, y_batch
Cna
  • 147
  • 2
  • 9
1

For the issue Cannot take the length of Shape with unknown rank, Thanks to above answer, I solved by add output_shape to from_generator according to this issue comment.

In my case, I was using Dataset.from_generator for dataset pipeline.

Before:

Dataset.from_generator(_generator_factory, 
                       output_types=(tf.float32, tf.int8))

Working code for me:

Dataset.from_generator(_generator_factory, 
                       output_types = (tf.float32, tf.int8),
                       output_shapes = (
                           tf.TensorShape([2, 224, 224, 3]), 
                           tf.TensorShape([1,])
                       ))
                                        

Also found this dataset official guide from tensorflow indicates that:

...

The output_shapes argument is not required but is highly recomended as many tensorflow operations do not support tensors with unknown rank. If the length of a particular axis is unknown or variable, set it as None in the output_shapes.

...

Community
  • 1
  • 1
Max
  • 463
  • 4
  • 11