Repository: tensorflow
Issue: Error with Custom Keras Model
Labels: type:bug,comp:keras,TF 2.13

### Issue type

Bug

### Have you reproduced the bug with TensorFlow Nightly?

No

### Source

source

### TensorFlow version

v2.13.0-17-gf841394b1b7 2.13.1

### Custom code

Yes

### OS platform and distribution

Linux Ubuntu 20.04.6 LTS

### Mobile device

_No response_

### Python version

3.9.18

### Bazel version

_No response_

### GCC/compiler version

_No response_

### CUDA/cuDNN version

_No response_

### GPU model and memory

_No response_

### Current behavior?

Expected output (ran using v2.8.3-90-g1b8f5c396f0 2.8.4):

```
{'name': 'custom_model', 'layers': [{'class_name': 'InputLayer', 'config': {'batch_input_shape': (None, 96, 96, 3), 'dtype': 'float32', 'sparse': False, 'ragged': False, 'name': 'input_1'}, 'name': 'input_1', 'inbound_nodes': []}, {'class_name': 'Conv2D', 'config': {'name': 'conv2d', 'trainable': True, 'dtype': 'float32', 'filters': 8, 'kernel_size': (3, 3), 'strides': (1, 1), 'padding': 'valid', 'data_format': 'channels_last', 'dilation_rate': (1, 1), 'groups': 1, 'activation': 'linear', 'use_bias': True, 'kernel_initializer': {'class_name': 'GlorotUniform', 'config': {'seed': None}}, 'bias_initializer': {'class_name': 'Zeros', 'config': {}}, 'kernel_regularizer': None, 'bias_regularizer': None, 'activity_regularizer': None, 'kernel_constraint': None, 'bias_constraint': None}, 'name': 'conv2d', 'inbound_nodes': [[['input_1', 0, 0, {}]]]}], 'input_layers': [['input_1', 0, 0]], 'output_layers': [['conv2d', 0, 0]]}
{'name': 'model', 'layers': [{'class_name': 'InputLayer', 'config': {'batch_input_shape': (None, 96, 96, 3), 'dtype': 'float32', 'sparse': False, 'ragged': False, 'name': 'input_1'}, 'name': 'input_1', 'inbound_nodes': []}, {'class_name': 'Conv2D', 'config': {'name': 'conv2d', 'trainable': True, 'dtype': 'float32', 'filters': 8, 'kernel_size': (3, 3), 'strides': (1, 1), 'padding': 'valid', 'data_format': 'channels_last', 'dilation_rate': (1, 1), 'groups': 1, 'activation': 'linear', 'use_bias': True, 'kernel_initializer': {'class_name': 'GlorotUniform', 'config': {'seed': None}}, 'bias_initializer': {'class_name': 'Zeros', 'config': {}}, 'kernel_regularizer': None, 'bias_regularizer': None, 'activity_regularizer': None, 'kernel_constraint': None, 'bias_constraint': None}, 'name': 'conv2d', 'inbound_nodes': [[['input_1', 0, 0, {}]]]}], 'input_layers': [['input_1', 0, 0]], 'output_layers': [['conv2d', 0, 0]]}
WARNING:tensorflow:Compiled the loaded model, but the compiled metrics have yet to be built. `model.compile_metrics` will be empty until you train or evaluate the model.
WARNING:tensorflow:Compiled the loaded model, but the compiled metrics have yet to be built. `model.compile_metrics` will be empty until you train or evaluate the model.
WARNING:tensorflow:No training configuration found in the save file, so the model was *not* compiled. Compile it manually.
WARNING:tensorflow:No training configuration found in the save file, so the model was *not* compiled. Compile it manually.
Model: "custom_model"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 input_1 (InputLayer)        [(None, 96, 96, 3)]       0         
                                                                 
 conv2d (Conv2D)             (None, 94, 94, 8)         224       
                                                                 
=================================================================
Total params: 224
Trainable params: 224
Non-trainable params: 0
_________________________________________________________________
Model: "model"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 input_1 (InputLayer)        [(None, 96, 96, 3)]       0         
                                                                 
 conv2d (Conv2D)             (None, 94, 94, 8)         224       
                                                                 
=================================================================
Total params: 224
Trainable params: 224
Non-trainable params: 0
_________________________________________________________________
```


### Standalone code to reproduce the issue

```shell
import os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
import tensorflow as tf  # noqa: E402


class CustomModel(tf.keras.Model):
    def __init__(self, **kwargs):
        super(CustomModel, self).__init__(**kwargs)


input_shape = (96, 96, 3)
inputs = tf.keras.layers.Input(shape=input_shape)
outputs = tf.keras.layers.Conv2D(
    filters=8, kernel_size=3, strides=1)(inputs)

cust_model = CustomModel(inputs=inputs, outputs=outputs)
print(cust_model.get_config())

model = tf.keras.Model(inputs=inputs, outputs=outputs)
print(model.get_config())

cust_model_path = '/home/ubuntu/automltraining/my_custom_model.h5'
cust_model.save(cust_model_path)

model_path = '/home/ubuntu/automltraining/my_model.h5'
model.save(model_path)

cust_model2 = tf.keras.models.load_model(
    cust_model_path, custom_objects={"CustomModel": CustomModel})
model2 = tf.keras.models.load_model(model_path)

cust_model2.summary()
model2.summary()
```


### Relevant log output

```shell
{'name': 'custom_model', 'trainable': True}
{'name': 'model', 'trainable': True, 'layers': [{'module': 'keras.layers', 'class_name': 'InputLayer', 'config': {'batch_input_shape': (None, 96, 96, 3), 'dtype': 'float32', 'sparse': False, 'ragged': False, 'name': 'input_1'}, 'registered_name': None, 'name': 'input_1', 'inbound_nodes': []}, {'module': 'keras.layers', 'class_name': 'Conv2D', 'config': {'name': 'conv2d', 'trainable': True, 'dtype': 'float32', 'filters': 8, 'kernel_size': (3, 3), 'strides': (1, 1), 'padding': 'valid', 'data_format': 'channels_last', 'dilation_rate': (1, 1), 'groups': 1, 'activation': 'linear', '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, 96, 96, 3)}, 'name': 'conv2d', 'inbound_nodes': [[['input_1', 0, 0, {}]]]}], 'input_layers': [['input_1', 0, 0]], 'output_layers': [['conv2d', 0, 0]]}
/home/ubuntu/miniconda3/envs/automl/lib/python3.9/site-packages/keras/src/engine/training.py:3000: UserWarning: You are saving your model as an HDF5 file via `model.save()`. This file format is considered legacy. We recommend using instead the native Keras format, e.g. `model.save('my_model.keras')`.
  saving_api.save_model(
WARNING:tensorflow:Compiled the loaded model, but the compiled metrics have yet to be built. `model.compile_metrics` will be empty until you train or evaluate the model.
WARNING:tensorflow:Compiled the loaded model, but the compiled metrics have yet to be built. `model.compile_metrics` will be empty until you train or evaluate the model.
Traceback (most recent call last):
  File "/home/ubuntu/automltraining/get_config_debug.py", line 28, in <module>
    cust_model2 = tf.keras.models.load_model(
  File "/home/ubuntu/miniconda3/envs/automl/lib/python3.9/site-packages/keras/src/saving/saving_api.py", line 238, in load_model
    return legacy_sm_saving_lib.load_model(
  File "/home/ubuntu/miniconda3/envs/automl/lib/python3.9/site-packages/keras/src/utils/traceback_utils.py", line 70, in error_handler
    raise e.with_traceback(filtered_tb) from None
  File "/home/ubuntu/miniconda3/envs/automl/lib/python3.9/site-packages/keras/src/engine/training.py", line 3246, in from_config
    raise TypeError(
TypeError: Unable to revive model from config. When overriding the `get_config()` method, make sure that the returned config contains all items used as arguments in the  constructor to <class '__main__.CustomModel'>, which is the default behavior. You can override this default behavior by defining a `from_config(cls, config)` class method to specify how to create an instance of CustomModel from its config.

Received config={'name': 'custom_model', 'trainable': True}

Error encountered during deserialization: __init__() missing 2 required positional arguments: 'inputs' and 'outputs'
```