tensorflow: TypeError: '_UserObject' object is not callable, why tf.saved_model.load() failed?

System information

  • TensorFlow installed from (source or binary): - TensorFlow version (use command below): 2.1.0
  • Python version: 3.7.4

Describe the current behavior

Traceback (most recent call last):
  File "C:/Pyfile/tensorflow2.X/load_model.py", line 12, in <module>
    print(model(tf.random.normal((1, 3))))
TypeError: '_UserObject' object is not callable

Describe the expected behavior

Standalone code to reproduce the issue Provide a reproducible test case that is the bare minimum necessary to generate the problem. If possible, please share a link to Colab/Jupyter/any notebook.

import os
import tensorflow as tf

os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'

class Model(tf.keras.Model):
    def __init__(self):
        super(Model, self).__init__()
        self.d = tf.keras.layers.Dense(2)

    def call(self, x, training=True, mask=None):
        return self.d(x)

model = Model()

# high-level api
# model.predict(tf.random.normal((2, 3)))
# model.save("save/high", save_format="tf")

# low-level api
tf.saved_model.save(model, 'save/low')

---------------------------------------------

import os
import tensorflow as tf

# high-level api
# model = tf.keras.models.load_model('save/high')

# low-level api
model = tf.saved_model.load('save/low')

print(model(tf.random.normal((1, 3))))   #  error!!!

If I user the high-level api to save and load, it runs successfully. If I use tf.saved_mode.save(),it can save successfully with warning ‘’’ WARNING:tensorflow:Skipping full serialization of Keras model <main.Model object at 0x0000028C0515F6D8>, because its inputs are not defined. 2020-03-09 18:20:37.304479: W tensorflow/python/util/util.cc:319] Sets are not currently considered sequences, but this may change in the future, so consider avoiding using them. WARNING:tensorflow:Skipping full serialization of Keras layer <tensorflow.python.keras.layers.core.Dense object at 0x0000028C1CB87CC0>, because it is not built. ‘’’ then load failed, So what does ‘_UserObject’ object is not callable mean? How can I fix this, thanks for any help

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Comments: 15 (3 by maintainers)

Most upvoted comments

build model

import os
import tensorflow as tf

os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'


class Model(tf.keras.Model):
    def __init__(self, **kwargs):
        super(Model, self).__init__(**kwargs)
        self.d = tf.keras.layers.Dense(1, kernel_initializer=tf.keras.initializers.ones())

    def call(self, x, training=True, mask=None):
        return self.d(x)

model = Model()
optimizer = tf.keras.optimizers.SGD()
with tf.GradientTape() as tape:
    out = model(tf.ones((2, 3)))
    grads = tape.gradient(out, model.trainable_weights)
    optimizer.apply_gradients(zip(grads, model.trainable_weights))

print(model(tf.ones((2, 3))))

save and load model

Approach 1

https://www.tensorflow.org/guide/keras/save_and_serialize#approach_1

model.save_weights('save/')
model_load = Model()
model_load.load_weights('save/')
print(model_load(tf.ones((2, 3))))

It works well.

Approach2

https://www.tensorflow.org/guide/keras/save_and_serialize#approach_2

model.save('save')
model_load = tf.keras.models.load_model('save/')
print(model_load(tf.ones((2, 3))))

ValueError: Model <main.Model object at 0x4441057d0> 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).

Approach3

https://www.tensorflow.org/guide/keras/save_and_serialize#approach_3

tf.saved_model.save(model,'save')
model_load = tf.keras.models.load_model('save')
print(model_load(tf.ones((2, 3))))

AttributeError: ‘_UserObject’ object has no attribute ‘call_and_return_conditional_losses’

In the eager mode, just Approach 1 save_weights can work well. But if model is trained by using model.fit(), These methods all work well . I think this might be a bug. But if not,I think these methods of saving and loading models should be distinguished in the docs. @amahendrakar

The tensorflow2.0 use dynamic graphs. the model can auto infer the input shape by your input. But in your “low-level api” code, the Dense layer has not been inputed, so it can’t auto infer the shape of input to build model. So, you need input some data like your ''high-level api" code, then save model.

I suggest you follow the code behind like keras, to let the model know the shape of your inputs.

import os
import tensorflow as tf

os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'

class Model(tf.keras.Model):
    def __init__(self):
        super(Model, self).__init__()
        self.d = tf.keras.layers.Dense(2)

    def call(self, x, training=True, mask=None):
        return self.d(x)


mymodel = Model()
input = tf.keras.layers.Input(shape=(3,))
out = mymodel(input)
model=tf.keras.models.Model(inputs=input, outputs=out)

Yeah, this does work. But In my real project, I use tf.saved_model.save() to save the model in checkpoint_interval, I think after running serveral batch_sizes, the input_shape should be configured, but when I use tf.saved_model.load() to load the model and call the input, TypeError: ‘_UserObject’ object is not callable arises. I wonder why ?

@xiaoyangnihao That’s actually a rather easy fix which is more related to Python than to TF:

The method in Model must be named __call__ rather than call for the model to be callable (i.e. you can do model(x)). As it is right now you would have to do model.call(x).

Apparently this was wrong in the documentation at some point because we also had this problem in some places. It’s correct now though.

The tensorflow2.0 use dynamic graphs. the model can auto infer the input shape by your input. But in your “low-level api” code, the Dense layer has not been inputed, so it can’t auto infer the shape of input to build model. So, you need input some data like your ''high-level api" code, then save model.

I suggest you follow the code behind like keras, to let the model know the shape of your inputs.

import os
import tensorflow as tf

os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'

class Model(tf.keras.Model):
    def __init__(self):
        super(Model, self).__init__()
        self.d = tf.keras.layers.Dense(2)

    def call(self, x, training=True, mask=None):
        return self.d(x)


mymodel = Model()
input = tf.keras.layers.Input(shape=(3,))
out = mymodel(input)
model=tf.keras.models.Model(inputs=input, outputs=out)