0

I have searched through stackoverflow and read through documentation but somehow still my trained model is not being loaded! I have checked following links and many more so please do not mark as duplicate straight away. thank you

  1. How to save final model using keras?
  2. https://www.tensorflow.org/guide/keras/save_and_serialize
  3. https://www.tensorflow.org/tutorials/distribute/save_and_load
  4. https://www.tensorflow.org/guide/keras/functional
  5. How to load a model from an HDF5 file in Keras?

here is my model:

def get_model(train=True):
    
    set_seed(33)
    
    pre_process = Lambda(preprocess_input)
    vgg = VGG16(weights = 'imagenet', include_top = True, input_shape = SHAPE)
    vgg = Model(vgg.input, vgg.layers[-3].output)
    vgg.trainable = False
    
    inp = Input(SHAPE)
    vgg_16_process = pre_process(GaussianNoise(0.1)(inp))
    vgg_out = vgg(vgg_16_process)
    
    noise = Lambda(tf.zeros_like)(vgg_out)
    noise = GaussianNoise(0.1)(noise)

    if train:
        x = Lambda(lambda z: tf.concat(z, axis=0))([vgg_out,noise])
        x = Activation('relu')(x)
    else:
        x = vgg_out
        
    x = Dense(512, activation='relu')(x)
    x = Dense(128, activation='relu')(x)
    out = Dense(2, activation='softmax')(x)

    model = Model(inp, out)
    model.compile(Adam(learning_rate=1e-4), loss='binary_crossentropy')
    
    return model

And After that I have some test and train generator as follows, The dataset is classical dog-vs-cat dataset and I'm trying to achieve one-class classification task.


train_datagen = ImageDataGenerator()
test_datagen = ImageDataGenerator()

train_generator = train_datagen.flow_from_directory(
            base_path + 'training_set/training_set/',
            target_size = (SHAPE[0], SHAPE[1]),
            batch_size = batch_size,
            class_mode = 'categorical',
            shuffle = True,
            seed = 33,
            classes = ['cats']
    )

test_generator = test_datagen.flow_from_directory(
            base_path + 'test_set/test_set/',
            target_size = (SHAPE[0], SHAPE[1]),
            batch_size = batch_size,
            class_mode = 'categorical',
            shuffle = True,
            seed = 33,
            classes = ['dogs','cats']
)

Then finally, I do compile the model

model = get_model()
model.fit(wrap_generator(train_generator), steps_per_epoch=train_generator.samples/train_generator.batch_size, epochs=1)

Then I do save model as follow

model.save('my_custom_model')

Either I do save in that format or 'my_custom_model.h5' it saves perfectly without any error. If I use just save, then a folder is created with 'assets, variables, .pb files' that is expected as mentioned in posts of stackoverflow.

** Then here comes the problem **

from keras.models import load_model
loaded_model = load_model('my_custom_model.h5')
#or 
loaded_model = tf.keras.models.load_model('my_custom_model.h5')
#or 
loaded_model = load_model('my_custom_model') # as from folder

All throw same error

TypeError: 'module' object is not callable

I know I'm doing some mistake or model is bit different, please guide me to the right direction where I can look for solutions.

Python: 3.7.2 Tensorflow: 2.6.0 Keras: 2.6.0

Full Stack Trace

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
~\AppData\Roaming\Python\Python37\site-packages\tensorflow\python\ops\array_ops.py in wrapper(*args, **kwargs)
    205     try:
--> 206       return target(*args, **kwargs)
    207     except (TypeError, ValueError):

TypeError: 'str' object is not callable

During handling of the above exception, another exception occurred:

TypeError                                 Traceback (most recent call last)
<ipython-input-10-cd6655ece7c5> in <module>
      7 # loaded_model = tf.keras.models.load_model("my_custom_model2")
      8 
----> 9 loaded_model = tf.keras.models.load_model('model_notebook.h5')
     10 # print(loaded_model)
     11 # print("------------")

~\AppData\Roaming\Python\Python37\site-packages\keras\saving\save.py in load_model(filepath, custom_objects, compile, options)
    199             (isinstance(filepath, h5py.File) or h5py.is_hdf5(filepath))):
    200           return hdf5_format.load_model_from_hdf5(filepath, custom_objects,
--> 201                                                   compile)
    202 
    203         filepath = path_to_string(filepath)

~\AppData\Roaming\Python\Python37\site-packages\keras\saving\hdf5_format.py in load_model_from_hdf5(filepath, custom_objects, compile)
    179     model_config = json_utils.decode(model_config)
    180     model = model_config_lib.model_from_config(model_config,
--> 181                                                custom_objects=custom_objects)
    182 
    183     # set weights

~\AppData\Roaming\Python\Python37\site-packages\keras\saving\model_config.py in model_from_config(config, custom_objects)
     50                     '`Sequential.from_config(config)`?')
     51   from keras.layers import deserialize  # pylint: disable=g-import-not-at-top
---> 52   return deserialize(config, custom_objects=custom_objects)
     53 
     54 

~\AppData\Roaming\Python\Python37\site-packages\keras\layers\serialization.py in deserialize(config, custom_objects)
    210       module_objects=LOCAL.ALL_OBJECTS,
    211       custom_objects=custom_objects,
--> 212       printable_module_name='layer')

~\AppData\Roaming\Python\Python37\site-packages\keras\utils\generic_utils.py in deserialize_keras_object(identifier, module_objects, custom_objects, printable_module_name)
    676             custom_objects=dict(
    677                 list(_GLOBAL_CUSTOM_OBJECTS.items()) +
--> 678                 list(custom_objects.items())))
    679       else:
    680         with CustomObjectScope(custom_objects):

~\AppData\Roaming\Python\Python37\site-packages\keras\engine\functional.py in from_config(cls, config, custom_objects)
    661     with generic_utils.SharedObjectLoadingScope():
    662       input_tensors, output_tensors, created_layers = reconstruct_from_config(
--> 663           config, custom_objects)
    664       model = cls(inputs=input_tensors, outputs=output_tensors,
    665                   name=config.get('name'))

~\AppData\Roaming\Python\Python37\site-packages\keras\engine\functional.py in reconstruct_from_config(config, custom_objects, created_layers)
   1281       if layer in unprocessed_nodes:
   1282         for node_data in unprocessed_nodes.pop(layer):
-> 1283           process_node(layer, node_data)
   1284 
   1285   input_tensors = []

~\AppData\Roaming\Python\Python37\site-packages\keras\engine\functional.py in process_node(layer, node_data)
   1229         input_tensors = (
   1230             base_layer_utils.unnest_if_single_tensor(input_tensors))
-> 1231       output_tensors = layer(input_tensors, **kwargs)
   1232 
   1233       # Update node index map.

~\AppData\Roaming\Python\Python37\site-packages\keras\engine\base_layer.py in __call__(self, *args, **kwargs)
    975     if _in_functional_construction_mode(self, inputs, args, kwargs, input_list):
    976       return self._functional_construction_call(inputs, args, kwargs,
--> 977                                                 input_list)
    978 
    979     # Maintains info about the `Layer.call` stack.

~\AppData\Roaming\Python\Python37\site-packages\keras\engine\base_layer.py in _functional_construction_call(self, inputs, args, kwargs, input_list)
   1113       # Check input assumptions set after layer building, e.g. input shape.
   1114       outputs = self._keras_tensor_symbolic_call(
-> 1115           inputs, input_masks, args, kwargs)
   1116 
   1117       if outputs is None:

~\AppData\Roaming\Python\Python37\site-packages\keras\engine\base_layer.py in _keras_tensor_symbolic_call(self, inputs, input_masks, args, kwargs)
    846       return tf.nest.map_structure(keras_tensor.KerasTensor, output_signature)
    847     else:
--> 848       return self._infer_output_signature(inputs, args, kwargs, input_masks)
    849 
    850   def _infer_output_signature(self, inputs, args, kwargs, input_masks):

~\AppData\Roaming\Python\Python37\site-packages\keras\engine\base_layer.py in _infer_output_signature(self, inputs, args, kwargs, input_masks)
    886           self._maybe_build(inputs)
    887           inputs = self._maybe_cast_inputs(inputs)
--> 888           outputs = call_fn(inputs, *args, **kwargs)
    889 
    890         self._handle_activity_regularization(inputs, outputs)

~\AppData\Roaming\Python\Python37\site-packages\keras\layers\core.py in call(self, inputs, mask, training)
    901     with tf.GradientTape(watch_accessed_variables=True) as tape,\
    902         tf.variable_creator_scope(_variable_creator):
--> 903       result = self.function(inputs, **kwargs)
    904     self._check_variables(created_variables, tape.watched_variables())
    905     return result

~\AppData\Roaming\Python\Python37\site-packages\tensorflow\python\ops\array_ops.py in wrapper(*args, **kwargs)
    208       # Note: convert_to_eager_tensor currently raises a ValueError, not a
    209       # TypeError, when given unexpected types.  So we need to catch both.
--> 210       result = dispatch(wrapper, args, kwargs)
    211       if result is not OpDispatcher.NOT_SUPPORTED:
    212         return result

TypeError: 'module' object is not callable

1 Answers1

0

The dataset is classical dog-vs-cat dataset and I'm trying to achieve one-class classification task.

Then the model should have only one output node because this is an example of Binary Classification. Your model has the last Dense layer with two output units and the softmax as an activation function, which is a possible solution, but for this kind of problem my suggestion is to specify on the last Dense layer only one output unit and the sigmoid as the activation function.

It seems you forgot to add the string dog in the classes list on the train_generator.

train_generator = train_datagen.flow_from_directory(
            base_path + 'training_set/training_set/',
            target_size = (SHAPE[0], SHAPE[1]),
            batch_size = batch_size,
            class_mode = 'categorical',
            shuffle = True,
            seed = 33,
            classes = ['cats']
    )

Now, regards on the main topic of your question.

from keras.models import load_model
loaded_model = load_model('my_custom_model.h5')
#or 
loaded_model = tf.keras.models.load_model('my_custom_model.h5')
#or 
loaded_model = load_model('my_custom_model') # as from folder

I think, but I'm not 100% sure about it, the problem is from this line of code from keras.models import load_model. Starting from Tensorflow 2.x, which includes also the Keras module, every single function, class etc. must be imported by specifying always tensorflow as the first name for import each Keras module. In short, you should write this line of code: from tensorflow.keras.models import load_model and it should work because it calls the function from the Keras module with the Tensorflow as the back engine.

Simone
  • 146
  • 2
  • 13