Probably typo.
@keras.saving.register_keras_serializable()
class DummyModel(keras.Model):
def __init__(
self,
*,
input_shape=(28, 28, 1),
filters=[16, 32],
activation='relu',
**kwargs,
):
input_spec = keras.layers.Input(shape=input_shape)
x = input_spec
x = layers.Conv2D(filters[0], 3, activation=activation)(x)
x = layers.Conv2D(filters[1], 3, activation=activation)(x)
x = layers.MaxPooling2D(3)(x)
x = layers.Conv2D(filters[1], 3, activation=activation)(x)
x = layers.Conv2D(filters[0], 3, activation=activation)(x)
x = layers.GlobalMaxPooling2D()(x)
super().__init__(inputs=input_spec, outputs=x, **kwargs)
self.filters = filters
self.activation = activation
def get_config(self):
config = super().get_config()
config.update(
{
"input_shape": self.input_shape[1:],
"filters": self.filters,
"activation": self.activation,
}
)
return config
a = np.ones((1, 28, 28, 1), dtype=np.float32); print(a.shape)
model = DummyModel()
output = model(a)
print(output.shape)
(1, 28, 28, 1)
(1, 16)
model.save('new.keras') # ok
loaded_model = keras.saving.load_model("new.keras")
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
/usr/local/lib/python3.10/dist-packages/keras/src/saving/serialization_lib.py in deserialize_keras_object(config, custom_objects, safe_mode, **kwargs)
710 try:
--> 711 instance = cls.from_config(inner_config)
712 except TypeError as e:
/usr/local/lib/python3.10/dist-packages/keras/src/models/model.py in from_config(cls, config, custom_objects)
491
--> 492 return functional_from_config(
493 cls, config, custom_objects=custom_objects
/usr/local/lib/python3.10/dist-packages/keras/src/models/functional.py in functional_from_config(cls, config, custom_objects)
555 output_tensors = map_tensors(config["output_layers"])
--> 556 return cls(
557 inputs=input_tensors,
<ipython-input-17-242e47f47517> in __init__(self, input_shape, filters, activation, **kwargs)
33 x = layers.GlobalMaxPooling2D()(x)
---> 34 super().__init__(inputs=input_spec, outputs=x, **kwargs)
35
TypeError: keras.src.models.functional.Functional.__init__() got multiple values for keyword argument 'inputs'
During handling of the above exception, another exception occurred:
TypeError Traceback (most recent call last)
<ipython-input-20-9e5a9738bac0> in <cell line: 1>()
----> 1 loaded_model = keras.saving.load_model("new.keras")
/usr/local/lib/python3.10/dist-packages/keras/src/saving/saving_api.py in load_model(filepath, custom_objects, compile, safe_mode)
174
175 if is_keras_zip:
--> 176 return saving_lib.load_model(
177 filepath,
178 custom_objects=custom_objects,
/usr/local/lib/python3.10/dist-packages/keras/src/saving/saving_lib.py in load_model(filepath, custom_objects, compile, safe_mode)
153 # Construct the model from the configuration file in the archive.
154 with ObjectSharingScope():
--> 155 model = deserialize_keras_object(
156 config_dict, custom_objects, safe_mode=safe_mode
157 )
/usr/local/lib/python3.10/dist-packages/keras/src/saving/serialization_lib.py in deserialize_keras_object(config, custom_objects, safe_mode, **kwargs)
711 instance = cls.from_config(inner_config)
712 except TypeError as e:
--> 713 raise TypeError(
714 f"{cls} could not be deserialized properly. Please"
715 " ensure that components that are Python object"
TypeError: <class '__main__.DummyModel'> could not be deserialized properly. Please ensure that components that are Python object instances (layers, models, etc.) returned by `get_config()` are explicitly deserialized in the model's `from_config()` method.
config={'module': None, 'class_name': 'DummyModel', 'config': {'name': 'dummy_model_3', 'trainable': True, 'layers': [{'module': 'keras.layers', 'class_name': 'InputLayer', 'config': {'batch_shape': [None, 28, 28, 1], 'dtype': 'float32', 'sparse': False, 'name': 'input_layer_2'}, 'registered_name': None, 'name': 'input_layer_2', 'inbound_nodes': []}, {'module': 'keras.layers', 'class_name': 'Conv2D', 'config': {'name': 'conv2d_24', 'trainable': True, 'dtype': 'float32', 'filters': 16, 'kernel_size': [3, 3], 'strides': [1, 1], 'padding': 'valid', 'data_format': 'channels_last', 'dilation_rate': [1, 1], 'groups': 1, 'activation': 'relu', 'use_bias': True, 'kernel_initializer': {'module': 'keras.initializers', 'class_name': 'GlorotUniform', 'config': {'seed': None}, 'registered_name': None}, 'bias_initializer': {'module': 'keras.initializers', 'class_name': 'Zeros', 'config': {}, 'registered_name': None}, 'kernel_regularizer': None, 'bias_regularizer': None, 'activity_regularizer': None, 'kernel_constraint': None, 'bias_constraint': None}, 'registered_name': None, 'build_config': {'input_shape': [None, 28, 28, 1]}, 'name': 'conv2d_24', 'inbound_nodes': [{'args': [{'class_name': '__keras_tensor__', 'config': {'shape': [None, 28, 28, 1], 'dtype': 'float32', 'keras_history': ['input_layer_2', 0, 0]}}], 'kwargs': {}}]}, {'module': 'keras.layers', 'class_name': 'Conv2D', 'config': {'name': 'conv2d_25', 'trainable': True, 'dtype': 'float32', 'filters': 32, 'kernel_size': [3, 3], 'strides': [1, 1], 'padding': 'valid', 'data_format': 'channels_last', 'dilation_rate': [1, 1], 'groups': 1, 'activation': 'relu', 'use_bias': True, 'kernel_initializer': {'module': 'keras.initializers', 'class_name': 'GlorotUniform', 'config': {'seed': None}, 'registered_name': None}, 'bias_initializer': {'module': 'keras.initializers', 'class_name': 'Zeros', 'config': {}, 'registered_name': None}, 'kernel_regularizer': None, 'bias_regularizer': None, 'activity_regularizer': None, 'kernel_constraint': None, 'bias_constraint': None}, 'registered_name': None, 'build_config': {'input_shape': [None, 26, 26, 16]}, 'name': 'conv2d_25', 'inbound_nodes': [{'args': [{'class_name': '__keras_tensor__', 'config': {'shape': [None, 26, 26, 16], 'dtype': 'float32', 'keras_history': ['conv2d_24', 0, 0]}}], 'kwargs': {}}]}, {'module': 'keras.layers', 'class_name': 'MaxPooling2D', 'config': {'name': 'max_pooling2d_6', 'trainable': True, 'dtype': 'float32', 'pool_size': [3, 3], 'padding': 'valid', 'strides': [3, 3], 'data_format': 'channels_last'}, 'registered_name': None, 'build_config': {'input_shape': [None, 24, 24, 32]}, 'name': 'max_pooling2d_6', 'inbound_nodes': [{'args': [{'class_name': '__keras_tensor__', 'config': {'shape': [None, 24, 24, 32], 'dtype': 'float32', 'keras_history': ['conv2d_25', 0, 0]}}], 'kwargs': {}}]}, {'module': 'keras.layers', 'class_name': 'Conv2D', 'config': {'name': 'conv2d_26', 'trainable': True, 'dtype': 'float32', 'filters': 32, 'kernel_size': [3, 3], 'strides': [1, 1], 'padding': 'valid', 'data_format': 'channels_last', 'dilation_rate': [1, 1], 'groups': 1, 'activation': 'relu', 'use_bias': True, 'kernel_initializer': {'module': 'keras.initializers', 'class_name': 'GlorotUniform', 'config': {'seed': None}, 'registered_name': None}, 'bias_initializer': {'module': 'keras.initializers', 'class_name': 'Zeros', 'config': {}, 'registered_name': None}, 'kernel_regularizer': None, 'bias_regularizer': None, 'activity_regularizer': None, 'kernel_constraint': None, 'bias_constraint': None}, 'registered_name': None, 'build_config': {'input_shape': [None, 8, 8, 32]}, 'name': 'conv2d_26', 'inbound_nodes': [{'args': [{'class_name': '__keras_tensor__', 'config': {'shape': [None, 8, 8, 32], 'dtype': 'float32', 'keras_history': ['max_pooling2d_6', 0, 0]}}], 'kwargs': {}}]}, {'module': 'keras.layers', 'class_name': 'Conv2D', 'config': {'name': 'conv2d_27', 'trainable': True, 'dtype': 'float32', 'filters': 16, 'kernel_size': [3, 3], 'strides': [1, 1], 'padding': 'valid', 'data_format': 'channels_last', 'dilation_rate': [1, 1], 'groups': 1, 'activation': 'relu', 'use_bias': True, 'kernel_initializer': {'module': 'keras.initializers', 'class_name': 'GlorotUniform', 'config': {'seed': None}, 'registered_name': None}, 'bias_initializer': {'module': 'keras.initializers', 'class_name': 'Zeros', 'config': {}, 'registered_name': None}, 'kernel_regularizer': None, 'bias_regularizer': None, 'activity_regularizer': None, 'kernel_constraint': None, 'bias_constraint': None}, 'registered_name': None, 'build_config': {'input_shape': [None, 6, 6, 32]}, 'name': 'conv2d_27', 'inbound_nodes': [{'args': [{'class_name': '__keras_tensor__', 'config': {'shape': [None, 6, 6, 32], 'dtype': 'float32', 'keras_history': ['conv2d_26', 0, 0]}}], 'kwargs': {}}]}, {'module': 'keras.layers', 'class_name': 'GlobalMaxPooling2D', 'config': {'name': 'global_max_pooling2d_6', 'trainable': True, 'dtype': 'float32', 'data_format': 'channels_last', 'keepdims': False}, 'registered_name': None, 'build_config': {'input_shape': [None, 4, 4, 16]}, 'name': 'global_max_pooling2d_6', 'inbound_nodes': [{'args': [{'class_name': '__keras_tensor__', 'config': {'shape': [None, 4, 4, 16], 'dtype': 'float32', 'keras_history': ['conv2d_27', 0, 0]}}], 'kwargs': {}}]}], 'input_layers': [['input_layer_2', 0, 0]], 'output_layers': [['global_max_pooling2d_6', 0, 0]], 'input_shape': [28, 28, 1], 'filters': [16, 32], 'activation': 'relu'}, 'registered_name': 'Custom>DummyModel', 'build_config': {'input_shape': None}}.
Exception encountered: keras.src.models.functional.Functional.__init__() got multiple values for keyword argument 'inputs'
Comment From: sonali-kumari1
Hi @innat -
The error you are getting is due to your custom model not being deserialized properly. To resolve this error, you must explicitly deserialize your custom components in the from_config()
class method like this:
@keras.saving.register_keras_serializable()
class DummyModel(keras.Model):
def __init__(
self,
*,
input_shape=(28, 28, 1),
filters=[16, 32],
activation='relu',
**kwargs,
):
input_spec = keras.layers.Input(shape=input_shape)
x = input_spec
x = layers.Conv2D(filters[0], 3, activation=activation)(x)
x = layers.Conv2D(filters[1], 3, activation=activation)(x)
x = layers.MaxPooling2D(3)(x)
x = layers.Conv2D(filters[1], 3, activation=activation)(x)
x = layers.Conv2D(filters[0], 3, activation=activation)(x)
x = layers.GlobalMaxPooling2D()(x)
super().__init__(inputs=input_spec, outputs=x, **kwargs)
self.filters = filters
self.activation = activation
def get_config(self):
config = super().get_config()
config.update(
{
"input_shape": self.input_shape[1:],
"filters": self.filters,
"activation": self.activation,
}
)
return config
@classmethod
def from_config(cls, config):
return cls(**config)
a = np.ones((1, 28, 28, 1), dtype=np.float32); print(a.shape)
model = DummyModel()
output = model(a)
print(output.shape)
(1, 28, 28, 1)
(1, 16)
model.save('new.keras') # ok
loaded_model = keras.saving.load_model("new.keras")
Please refer to this documentation on custom objects for more details. Thanks!
Comment From: innat
@sonali-kumari1
By adding from config should work, right?
@keras.saving.register_keras_serializable()
class DummyModel(keras.Model):
def __init__(
self,
*,
input_shape=(28, 28, 1),
filters=[16, 32],
activation='relu',
**kwargs,
):
...
super().__init__(inputs=input_spec, outputs=x, **kwargs)
self.filters = filters
self.activation = activation
def get_config(self):
config = super().get_config()
config.update(
{
"input_shape": self.input_shape[1:],
"filters": self.filters,
"activation": self.activation,
}
)
return config
@classmethod
def from_config(cls, config):
return cls(**config)
a = np.ones((1, 28, 28, 1), dtype=np.float32); print(a.shape)
model = DummyModel()
output = model(a)
print(output.shape)
model.save('new.keras') # ok
loaded_model = keras.saving.load_model("new.keras")
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
/usr/local/lib/python3.10/dist-packages/keras/src/saving/serialization_lib.py in deserialize_keras_object(config, custom_objects, safe_mode, **kwargs)
717 try:
--> 718 instance = cls.from_config(inner_config)
719 except TypeError as e:
<ipython-input-5-8788dfb26b4d> in from_config(cls, config)
36 def from_config(cls, config):
---> 37 return cls(**config)
38
<ipython-input-5-8788dfb26b4d> in __init__(self, input_shape, filters, activation, **kwargs)
18 x = layers.GlobalMaxPooling2D()(x)
---> 19 super().__init__(inputs=input_spec, outputs=x, **kwargs)
20
/usr/local/lib/python3.10/dist-packages/keras/src/utils/tracking.py in wrapper(*args, **kwargs)
25 with DotNotTrackScope():
---> 26 return fn(*args, **kwargs)
27
/usr/local/lib/python3.10/dist-packages/keras/src/models/functional.py in __init__(self, inputs, outputs, name, **kwargs)
134
--> 135 Function.__init__(self, inputs, outputs, name=name, **kwargs)
136
TypeError: Function.__init__() got an unexpected keyword argument 'layers'
During handling of the above exception, another exception occurred:
TypeError Traceback (most recent call last)
<ipython-input-5-8788dfb26b4d> in <cell line: 47>()
45 model.save('new.keras') # ok
46
---> 47 loaded_model = keras.saving.load_model("new.keras")
/usr/local/lib/python3.10/dist-packages/keras/src/saving/saving_api.py in load_model(filepath, custom_objects, compile, safe_mode)
185
186 if is_keras_zip or is_keras_dir:
--> 187 return saving_lib.load_model(
188 filepath,
189 custom_objects=custom_objects,
/usr/local/lib/python3.10/dist-packages/keras/src/saving/saving_lib.py in load_model(filepath, custom_objects, compile, safe_mode)
363 )
364 with open(filepath, "rb") as f:
--> 365 return _load_model_from_fileobj(
366 f, custom_objects, compile, safe_mode
367 )
/usr/local/lib/python3.10/dist-packages/keras/src/saving/saving_lib.py in _load_model_from_fileobj(fileobj, custom_objects, compile, safe_mode)
440 config_json = f.read()
441
--> 442 model = _model_from_config(
443 config_json, custom_objects, compile, safe_mode
444 )
/usr/local/lib/python3.10/dist-packages/keras/src/saving/saving_lib.py in _model_from_config(config_json, custom_objects, compile, safe_mode)
429 # Construct the model from the configuration file in the archive.
430 with ObjectSharingScope():
--> 431 model = deserialize_keras_object(
432 config_dict, custom_objects, safe_mode=safe_mode
433 )
/usr/local/lib/python3.10/dist-packages/keras/src/saving/serialization_lib.py in deserialize_keras_object(config, custom_objects, safe_mode, **kwargs)
718 instance = cls.from_config(inner_config)
719 except TypeError as e:
--> 720 raise TypeError(
721 f"{cls} could not be deserialized properly. Please"
722 " ensure that components that are Python object"
TypeError: <class '__main__.DummyModel'> could not be deserialized properly. Please ensure that components that are Python object instances (layers, models, etc.) returned by `get_config()` are explicitly deserialized in the model's `from_config()` method.
config={'module': None, 'class_name': 'DummyModel', 'config': {'name': 'dummy_model_1', 'trainable': True, 'layers': [{'module': 'keras.layers', 'class_name': 'InputLayer', 'config': {'batch_shape': [None, 28, 28, 1], 'dtype': 'float32', 'sparse': False, 'name': 'input_layer_2'}, 'registered_name': None, 'name': 'input_layer_2', 'inbound_nodes': []}, {'module': 'keras.layers', 'class_name': 'Conv2D', 'config': {'name': 'conv2d_8', 'trainable': True, 'dtype': {'module': 'keras', 'class_name': 'DTypePolicy', 'config': {'name': 'float32'}, 'registered_name': None}, 'filters': 16, 'kernel_size': [3, 3], 'strides': [1, 1], 'padding': 'valid', 'data_format': 'channels_last', 'dilation_rate': [1, 1], 'groups': 1, 'activation': 'relu', 'use_bias': True, 'kernel_initializer': {'module': 'keras.initializers', 'class_name': 'GlorotUniform', 'config': {'seed': None}, 'registered_name': None}, 'bias_initializer': {'module': 'keras.initializers', 'class_name': 'Zeros', 'config': {}, 'registered_name': None}, 'kernel_regularizer': None, 'bias_regularizer': None, 'activity_regularizer': None, 'kernel_constraint': None, 'bias_constraint': None}, 'registered_name': None, 'build_config': {'input_shape': [None, 28, 28, 1]}, 'name': 'conv2d_8', 'inbound_nodes': [{'args': [{'class_name': '__keras_tensor__', 'config': {'shape': [None, 28, 28, 1], 'dtype': 'float32', 'keras_history': ['input_layer_2', 0, 0]}}], 'kwargs': {}}]}, {'module': 'keras.layers', 'class_name': 'Conv2D', 'config': {'name': 'conv2d_9', 'trainable': True, 'dtype': {'module': 'keras', 'class_name': 'DTypePolicy', 'config': {'name': 'float32'}, 'registered_name': None, 'shared_object_id': 137654361192000}, 'filters': 32, 'kernel_size': [3, 3], 'strides': [1, 1], 'padding': 'valid', 'data_format': 'channels_last', 'dilation_rate': [1, 1], 'groups': 1, 'activation': 'relu', 'use_bias': True, 'kernel_initializer': {'module': 'keras.initializers', 'class_name': 'GlorotUniform', 'config': {'seed': None}, 'registered_name': None}, 'bias_initializer': {'module': 'keras.initializers', 'class_name': 'Zeros', 'config': {}, 'registered_name': None}, 'kernel_regularizer': None, 'bias_regularizer': None, 'activity_regularizer': None, 'kernel_constraint': None, 'bias_constraint': None}, 'registered_name': None, 'build_config': {'input_shape': [None, 26, 26, 16]}, 'name': 'conv2d_9', 'inbound_nodes': [{'args': [{'class_name': '__keras_tensor__', 'config': {'shape': [None, 26, 26, 16], 'dtype': 'float32', 'keras_history': ['conv2d_8', 0, 0]}}], 'kwargs': {}}]}, {'module': 'keras.layers', 'class_name': 'MaxPooling2D', 'config': {'name': 'max_pooling2d_2', 'trainable': True, 'dtype': {'module': 'keras', 'class_name': 'DTypePolicy', 'config': {'name': 'float32'}, 'registered_name': None, 'shared_object_id': 137654361192000}, 'pool_size': [3, 3], 'padding': 'valid', 'strides': [3, 3], 'data_format': 'channels_last'}, 'registered_name': None, 'build_config': {'input_shape': [None, 24, 24, 32]}, 'name': 'max_pooling2d_2', 'inbound_nodes': [{'args': [{'class_name': '__keras_tensor__', 'config': {'shape': [None, 24, 24, 32], 'dtype': 'float32', 'keras_history': ['conv2d_9', 0, 0]}}], 'kwargs': {}}]}, {'module': 'keras.layers', 'class_name': 'Conv2D', 'config': {'name': 'conv2d_10', 'trainable': True, 'dtype': {'module': 'keras', 'class_name': 'DTypePolicy', 'config': {'name': 'float32'}, 'registered_name': None, 'shared_object_id': 137654361192000}, 'filters': 32, 'kernel_size': [3, 3], 'strides': [1, 1], 'padding': 'valid', 'data_format': 'channels_last', 'dilation_rate': [1, 1], 'groups': 1, 'activation': 'relu', 'use_bias': True, 'kernel_initializer': {'module': 'keras.initializers', 'class_name': 'GlorotUniform', 'config': {'seed': None}, 'registered_name': None}, 'bias_initializer': {'module': 'keras.initializers', 'class_name': 'Zeros', 'config': {}, 'registered_name': None}, 'kernel_regularizer': None, 'bias_regularizer': None, 'activity_regularizer': None, 'kernel_constraint': None, 'bias_constraint': None}, 'registered_name': None, 'build_config': {'input_shape': [None, 8, 8, 32]}, 'name': 'conv2d_10', 'inbound_nodes': [{'args': [{'class_name': '__keras_tensor__', 'config': {'shape': [None, 8, 8, 32], 'dtype': 'float32', 'keras_history': ['max_pooling2d_2', 0, 0]}}], 'kwargs': {}}]}, {'module': 'keras.layers', 'class_name': 'Conv2D', 'config': {'name': 'conv2d_11', 'trainable': True, 'dtype': {'module': 'keras', 'class_name': 'DTypePolicy', 'config': {'name': 'float32'}, 'registered_name': None, 'shared_object_id': 137654361192000}, 'filters': 16, 'kernel_size': [3, 3], 'strides': [1, 1], 'padding': 'valid', 'data_format': 'channels_last', 'dilation_rate': [1, 1], 'groups': 1, 'activation': 'relu', 'use_bias': True, 'kernel_initializer': {'module': 'keras.initializers', 'class_name': 'GlorotUniform', 'config': {'seed': None}, 'registered_name': None}, 'bias_initializer': {'module': 'keras.initializers', 'class_name': 'Zeros', 'config': {}, 'registered_name': None}, 'kernel_regularizer': None, 'bias_regularizer': None, 'activity_regularizer': None, 'kernel_constraint': None, 'bias_constraint': None}, 'registered_name': None, 'build_config': {'input_shape': [None, 6, 6, 32]}, 'name': 'conv2d_11', 'inbound_nodes': [{'args': [{'class_name': '__keras_tensor__', 'config': {'shape': [None, 6, 6, 32], 'dtype': 'float32', 'keras_history': ['conv2d_10', 0, 0]}}], 'kwargs': {}}]}, {'module': 'keras.layers', 'class_name': 'GlobalMaxPooling2D', 'config': {'name': 'global_max_pooling2d_2', 'trainable': True, 'dtype': {'module': 'keras', 'class_name': 'DTypePolicy', 'config': {'name': 'float32'}, 'registered_name': None, 'shared_object_id': 137654361192000}, 'data_format': 'channels_last', 'keepdims': False}, 'registered_name': None, 'build_config': {'input_shape': [None, 4, 4, 16]}, 'name': 'global_max_pooling2d_2', 'inbound_nodes': [{'args': [{'class_name': '__keras_tensor__', 'config': {'shape': [None, 4, 4, 16], 'dtype': 'float32', 'keras_history': ['conv2d_11', 0, 0]}}], 'kwargs': {}}]}], 'input_layers': [['input_layer_2', 0, 0]], 'output_layers': [['global_max_pooling2d_2', 0, 0]], 'input_shape': [28, 28, 1], 'filters': [16, 32], 'activation': 'relu'}, 'registered_name': 'Custom>DummyModel', 'build_config': {'input_shape': None}}.
Exception encountered: Function.__init__() got an unexpected keyword argument 'layers'
Comment From: sonali-kumari1
Hi @innat -
I have tried to replicate the issue in colab notebook with the latest version of keras(3.8.0) and the code works fine. Attaching gist for your reference.Thanks!
Comment From: innat
@sonali-kumari1 Thanks. I was running the model in kaggle where keras==3.5.0. And it fails to load the model. This seems like bug in 3.5 version which fixed in 3.8. Is there any workaround to make it work in 3.5?