Skip to content

The signatures in SavedModel do not contain serving_default when a subclass of the keras model has multiple inputs #69307

@ian-huu

Description

@ian-huu

Issue type

Bug

Have you reproduced the bug with TensorFlow Nightly?

Yes

Source

binary

TensorFlow version

2.16.1

Custom code

Yes

OS platform and distribution

Linux Ubuntu 22.04.1

Mobile device

No response

Python version

3.10.13

Bazel version

No response

GCC/compiler version

No response

CUDA/cuDNN version

No response

GPU model and memory

No response

Current behavior?

The code below illustrates that when a Keras model has multiple inputs, the tf.saved_model does not function correctly, resulting in an empty signatures field.

Standalone code to reproduce the issue

import tempfile

import keras
import tensorflow as tf

path = tempfile.mkdtemp()

model1 = keras.models.Sequential([keras.layers.Dense(8), keras.layers.Dense(1)])
model1.build((None, 16))
tf.saved_model.save(model1, f"{path}/model1")
loaded1 = tf.saved_model.load(f"{path}/model1")
print(f"loaded1: {loaded1.signatures}")


class Model2(keras.Model):
    def __init__(self):
        super().__init__()

        self.fc1 = keras.layers.Dense(8)
        self.fc2 = keras.layers.Dense(1)

    def call(self, inputs, **kwargs):
        out1 = self.fc1(inputs)
        out2 = self.fc2(out1)
        return out2


model2 = Model2()
model2.build((None, 16))
tf.saved_model.save(model2, f"{path}/model2")
loaded2 = tf.saved_model.load(f"{path}/model2")
print(f"loaded2: {loaded2.signatures}")


class Model3(keras.Model):
    def __init__(self):
        super().__init__()

        self.fc1 = keras.layers.Dense(8)
        self.fc2 = keras.layers.Dense(1)

    def build(self, input_shape):
        self.fc1.build((None, sum([shape[1] for shape in input_shape])))
        self.fc2.build((None, 8))

    def call(self, inputs, **kwargs):
        concat_inputs = keras.ops.concatenate(inputs, axis=1)
        out1 = self.fc1(concat_inputs)
        out2 = self.fc2(out1)
        return out2


model3 = Model3()
model3.build([(None, 8), (None, 8)])
tf.saved_model.save(model3, f"{path}/model3")

loaded3 = tf.saved_model.load(f"{path}/model3")
print(f"loaded3: {loaded3.signatures}")

Relevant log output

loaded1: _SignatureMap({'serving_default': <ConcreteFunction (*, inputs: TensorSpec(shape=(None, 16), dtype=tf.float32, name='inputs')) -> Dict[['output_0', TensorSpec(shape=(None, 1), dtype=tf.float32, name='output_0')]] at 0x7A4E8429C8E0>})
python3.10/site-packages/keras/src/layers/layer.py:361: UserWarning: `build()` was called on layer 'model2', however the layer does not have a `build()` method implemented and it looks like it has unbuilt state. This will cause the layer to be marked as built, despite not being actually built, which may cause failures down the line. Make sure to implement a proper `build()` method.
  warnings.warn(
loaded2: _SignatureMap({'serving_default': <ConcreteFunction (*, inputs: TensorSpec(shape=(None, 16), dtype=tf.float32, name='inputs')) -> Dict[['output_0', TensorSpec(shape=(None, 1), dtype=tf.float32, name='output_0')]] at 0x7A4E841D4A00>})
loaded3: _SignatureMap({})

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions