tensorflow: Model cannot be saved because the input shapes have not been set.

Hello, I’m following save_and_serialize subclass model . When I run the following code,

class CustomModel(tf.keras.Model):
    def __init__(self, hidden_units):
        super(CustomModel, self).__init__()
        self.dense_layers = [
            tf.keras.layers.Dense(u) for u in hidden_units]
    def call(self, inputs):
        x = inputs
        for layer in self.dense_layers:
            x = layer(x)
        return x

model = CustomModel([16, 16, 10])
# Build the model by calling it
input_arr = tf.random.uniform((1, 5))
outputs = model(input_arr)
model.save('my_custom_model')

I get the this error, ValueError: Model <__main__.CustomModel object at 0x7f96797a2c10> cannot be saved because the input shapes have not been set. Usually, input shapes are automatically determined from calling .fit() or .predict(). To manually set the shapes, call model._set_inputs(inputs).

But when I change code as following,

model = CustomModel([16, 16, 10])
input_arr = tf.random.uniform((1, 5))
outputs = model(input_arr)
model._set_inputs(input_arr) # add this line
model.save('my_custom_model')

It runs without any error. What could be the possible cause. Do I need to add model._set_inputs(input_arr) explicitly ?

I’m using, Ubuntu 20.04 LTS conda environment TensorFlow 2.1.1

Thanks

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Comments: 21 (1 by maintainers)

Most upvoted comments

I am also facing the same problem in 2.3. And I used “model.compute_output_shape(input_shape=(None, 1080,1920,3))”,can also solve this problem when saving a subclassed model. But why does it work?

Bug seems to be back in 2.3

Hi all,

I recently came across a similar problem where I had 2 models. One text encoder, and one classification head. I needed to implement some custom logic inside the train_step. The subclassed model looked as follows:

class TestModel(keras.Model):
    
    def __init__(self, first, second, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.first = first
        self.second = second
        
    def call(self, inputs):
        return self.second(self.first(inputs))
        
    def train_step(self, data):
        # Here some custom logic requiring both first and second model
        pass

When calling model.save() on the instance, it cannot save the model because of the ValueError described above. One can only save the model if you have made a forward pass on the model. I was using KerasTuner for hyperparameter tuning and noticed that it does not return a correctly built model. So one solution was to pass some data through the model to make it save. That worked but I didn’t like it. Then I came across the following solution:

class TestModel(keras.Model):
    
    def __init__(self, first, second, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.first = first
        self.second = second
        
        self._set_inputs(inputs=self.first.inputs, outputs=self(self.first.inputs))
        
    def call(self, inputs):
        return self.second(self.first(inputs))

    def train_step(self, data):
        # Here some custom logic requiring both first and second model
        pass

This basically allows you to lazily specify the inputs and outputs as normal. So far it works properly. I hope this might help others out as well.

I am facing the same issue in 2.4.0, with jupyter lab python 3.8. For testing i downloaded the notebook from https://www.tensorflow.org/tutorials/generative/cvae Both, tf.keras.models.save_model(model, path) and model.save(path) return the same ValueError Is there any workarround?

Hi all! Thanks @boogalooYison , your solution worked with TensorFlow 2.6.0 👍 . About the reason why it works, I can only say that the input shape is set in the call to model.compute_output_shape(input_shape), as it is required to compute the actual output shape.

In my opinion, this is a cleaner and more elegant solution than having to call the network with dummy input data.

Cheers!

@menon92 Thanks! That works for basic examples, but not for the CVAE model in the TF documentation.

I figured out how to save the CVAE by replacing this line:

eps = tf.random.normal(shape=mean.shape)

with:

eps = tf.random.normal(shape=tf.shape(mean))

And adding the @tf.function decorator to all of CVAE’s methods so they are reconstructed when loading from disk.

(And calling .predict() before saving as the earlier comments note.)

Are you satisfied with the resolution of your issue? Yes No

no

I ran into the same issue as @lmielke. If I used a different VAE example, I could save the model. However, using the example from https://www.tensorflow.org/tutorials/generative/cvae just does not work. The code there is really nice.

It would be very nice if an updated version of TensorFlow can solve the issue.

My bad, the problem is not with 2.3, it is when trying to save a subclassed model.

@menon92 Yes this bug exists in 2.1.0 but has been fixed in tensorflow 2.2.0. image