After reading blog "An Object Oriented Approach To Train an Image Classifier with Tensorflow" I've tried to set custom signatures for my Keras model (TF2) like this:
class ImageClassifierModel(tf.keras.Model):
def __init__(self,...)
def call(self,...)
def save(self, filepath, overwrite=True, include_optimizer=True, save_format=None, signatures=None, options=None,save_traces=True):
if signatures is None:
signatures = dict()
signatures["serving_default"] = self.predict_b64_image
signatures["serving_array"] = self.predict_numpy_image
super().save(filepath, overwrite, include_optimizer, save_format, signatures, options, save_traces)
@tf.function(input_signature=[tf.TensorSpec(name="image_b64_string", shape=None, dtype=tf.string)])
def predict_b64_image(self, b64_image):
#...
@tf.function(input_signature=[tf.TensorSpec(name="image_tensor", shape=(None, None, None, 3), dtype=tf.float32)])
def predict_numpy_image(self, image):
#...
I have a ModelCheckpoint callback that saves the model when learning is done.
Once learning is finished, if I looked at the model signatures with saved_model_cli tool, I can see that:
When learning is done locally (docker container): my signatures are there.
When learning is done on Google Cloud Platform (same custom container): After the download of the model locally (from Google Storage) I look at the signatures: my custom signatures are not there anymore. Only the "image" signature (probably inferred by TF) that expects an image of rank 4
How do you explain such a behavior?
EDIT: the only workaround I've found is:
model = tf.keras.models.load_model(my_model_path)
model.save_weights('/tmp/my_model_weights')
# redefine my model
model = ResnetModel(...)
keras_model.load_weights('/tmp/my_model_weights')
model.save(my_model_path)