question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Not able to convert trained model for Tensorflow Serving API

See original GitHub issue

First of all, thanks for taking the time to make this amazing repo.

While using this repo I am stuck in the following situation, I am trying to convert a trained keras model to a compatible format to enable running it using tensorflow serving. I have the following two pieces of code with me which I am trying to use to convert.

  1. Using model variable:
from __future__ import print_function
import os
import shutil

from glob import glob

from keras.models import load_model
from keras.preprocessing.image import img_to_array
from keras.applications import imagenet_utils

from tensorflow.python.keras.estimator import model_to_estimator
import tensorflow as tf
import keras_resnet

from tensorflow.python.keras._impl.keras.models import Model
from keras_retinanet import models
import keras_resnet.models
from keras_retinanet.utils.image import read_image_bgr, preprocess_image, resize_image
from keras_retinanet.utils.visualization import draw_box, draw_caption
from keras_retinanet.utils.colors import label_color

def export_for_serving(model_path, model):
  '''
  Converts model to the TensorFlow estimator and saves it to the disk
  :param model: keras model to prepare for serving
  '''
  export_dir = 'tf_serving_model/'
  if os.path.exists(export_dir):
    shutil.rmtree(export_dir)

  tf_estimator = model_to_estimator(keras_model=model)

  tf_estimator.export_savedmodel(
    export_dir,
    serving_input_receiver_fn,
    strip_default_attrs=True)

model_path = os.path.join('.', 'snapshots', 'resnet50_csv_15_model.h5')
model = Model(models.load_model(model_path, backbone_name='resnet50'))
print("loaded model")
export_for_serving(model_path=model_path, model=model)

Running this throws the following error:

Traceback (most recent call last):  File "keras_to_tensorflow_serving.py", line 42, in <module>
   model = Model(models.load_model(model_path, backbone_name='resnet50'))
TypeError: __init__() missing 1 required positional argument: 'outputs'
  1. Using the .h5 file stored on disk:
from __future__ import print_function
import os
import shutil

from glob import glob

from keras.models import load_model

from keras.preprocessing.image import img_to_array
from keras.applications import imagenet_utils

from tensorflow.python.keras.estimator import model_to_estimator
import tensorflow as tf
import keras_resnet

from keras_retinanet import models
import keras_resnet.models
from keras_retinanet.utils.image import read_image_bgr, preprocess_image, resize_image
from keras_retinanet.utils.visualization import draw_box, draw_caption
from keras_retinanet.utils.colors import label_color

def export_for_serving(model_path, model):
  '''
  Converts model to the TensorFlow estimator and saves it to the disk
  :param model: keras model to prepare for serving
  '''
  export_dir = 'tf_serving_model/'
  if os.path.exists(export_dir):
    shutil.rmtree(export_dir)

  tf_estimator = model_to_estimator(keras_model_path=model_path)

  tf_estimator.export_savedmodel(
    export_dir,
    serving_input_receiver_fn,
    strip_default_attrs=True)

model_path = os.path.join('.', 'snapshots', 'resnet50_csv_15_model.h5')
model = models.load_model(model_path, backbone_name='resnet50')
print("Loaded Model")
export_for_serving(model_path=model_path, model=model)

I am receiving the following error:

Traceback (most recent call last):
 File "keras_to_tensorflow_serving.py", line 42, in <module>
   export_for_serving(model_path=model_path, model=model)
 File "keras_to_tensorflow_serving.py", line 32, in export_for_serving
   tf_estimator = model_to_estimator(keras_model_path=model_path, custom_objects=custom_objects)
 File "/usr/local/lib/python2.7/dist-packages/tensorflow/python/keras/_impl/keras/estimator.py", line 456, in model_to_estimator
   keras_model = models.load_model(keras_model_path)
 File "/usr/local/lib/python2.7/dist-packages/tensorflow/python/keras/_impl/keras/engine/saving.py", line 240, in load_model
   model = model_from_config(model_config, custom_objects=custom_objects)
 File "/usr/local/lib/python2.7/dist-packages/tensorflow/python/keras/_impl/keras/engine/saving.py", line 317, in model_from_config
   return deserialize(config, custom_objects=custom_objects)
 File "/usr/local/lib/python2.7/dist-packages/tensorflow/python/keras/_impl/keras/layers/serialization.py", line 63, in deserialize
   printable_module_name='layer')
 File "/usr/local/lib/python2.7/dist-packages/tensorflow/python/keras/_impl/keras/utils/generic_utils.py", line 171, in deserialize_keras_object
   list(custom_objects.items())))
 File "/usr/local/lib/python2.7/dist-packages/tensorflow/python/keras/_impl/keras/engine/network.py", line 1060, in from_config
   process_layer(layer_data)
 File "/usr/local/lib/python2.7/dist-packages/tensorflow/python/keras/_impl/keras/engine/network.py", line 1046, in process_layer
   layer = deserialize_layer(layer_data, custom_objects=custom_objects)
 File "/usr/local/lib/python2.7/dist-packages/tensorflow/python/keras/_impl/keras/layers/serialization.py", line 63, in deserialize
   printable_module_name='layer')
 File "/usr/local/lib/python2.7/dist-packages/tensorflow/python/keras/_impl/keras/utils/generic_utils.py", line 173, in deserialize_keras_object
   return cls.from_config(config['config'])
 File "/usr/local/lib/python2.7/dist-packages/tensorflow/python/keras/_impl/keras/engine/base_layer.py", line 473, in from_config
   return cls(**config)
 File "/usr/local/lib/python2.7/dist-packages/tensorflow/python/keras/_impl/keras/layers/normalization.py", line 107, in __init__
   **kwargs
 File "/usr/local/lib/python2.7/dist-packages/tensorflow/python/layers/normalization.py", line 146, in __init__
   name=name, trainable=trainable, **kwargs)
 File "/usr/local/lib/python2.7/dist-packages/tensorflow/python/keras/_impl/keras/engine/base_layer.py", line 128, in __init__
   raise TypeError('Keyword argument not understood:', kwarg)
TypeError: ('Keyword argument not understood:', u'freeze')

I am using the latest version of the repo using Keras 2.2.0. Also, the model I am trying to convert is trained using the same latest version of the repo.

Can anyone please point out the mistake I am making. Any help would be greatly appreciated. Thanks in advance.

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Comments:29 (8 by maintainers)

github_iconTop GitHub Comments

7reactions
faustomoralescommented, Jul 6, 2019

I use the following to create a TensorFlow model for TensorFlow serving. The code below assumes that you have a RetinaNet model with 8 classes using the resnet101 backbone with weights saved in a file called model.h5. You’ll need to edit those for your use case. It will create a folder called retinanet_savedmodel with the TensorFlow files inside of it.

from keras import backend as K
import tensorflow as tf
from tensorflow.python import saved_model
from tensorflow.python.saved_model.signature_def_utils_impl import (
    build_signature_def, predict_signature_def
)
from keras_retinanet import models
import shutil
import os

export_path = 'retinanet_savedmodel'
model = models.convert_model(
    model=models.backbone(backbone_name='resnet101').retinanet(num_classes=8),
    nms=True,
    class_specific_filter=True,
    anchor_params=None
)
model.load_weights('model.h5')

print('Output layers', [o.name[:-2] for o in model.outputs])
print('Input layer', model.inputs[0].name[:-2])
if os.path.isdir(export_path):
    shutil.rmtree(export_path)
builder = saved_model.builder.SavedModelBuilder(export_path)

signature = predict_signature_def(
    inputs={'images': model.input},
    outputs={
        'output1': model.outputs[0],
        'output2': model.outputs[1],
        'output3': model.outputs[2]
    }
)

sess = K.get_session()
builder.add_meta_graph_and_variables(sess=sess,
                                     tags=[saved_model.tag_constants.SERVING],
                                     signature_def_map={'predict': signature})
builder.save()

After executing the above, you can use TensorFlow Serving using the following command (note the 1 which is important).

docker run -t --rm -p 8501:8501 -v "$PWD/retinanet_savedmodel:/models/retinanet/1" -e MODEL_NAME=retinanet tensorflow/serving

I hope this helps someone! 😃

1reaction
maxisawesomecommented, Jun 17, 2019

I haven’t found a solution, but I think I’ve found the root of the problem.

Retinanet implements batch norm with it’s own layer that allows freezing, found here: https://github.com/broadinstitute/keras-resnet/blob/master/keras_resnet/layers/_batch_normalization.py It passes one extra boolean variable freeze that controls the freezing. The file is pretty simple but I can explain it if someone doesn’t get it.

So when tensorflow tries to load up the custom objects, it gets confused when it gets batch norm with one extra variable name “freeze,” and thus returns the error. My layer’s batch norm was all default values, so I tried doing something like so:

    bn = keras.layers.BatchNormalization()
    c_o = models.backbone("resnet50").custom_objects
    c_o["BatchNormalization"] = bn

    tf_estimator = model_to_estimator(keras_model_path=model_path, custom_objects=c_o)

but ended up STILL getting the error. Based on the traceback, which I’ll put below, I was pretty certain that replacing the custom BatchNormalization would do the trick. I looked at the other layers in custom_objects and they didn’t have anything like “freeze,” and the final lines of the traceback imply that the problem is in defining the normalization. The fact that it’s a keyword argument further reinforces my idea that it’s the batch norm layer.

I didn’t figure it out but I think we can get this working!!

Here’s the full traceback error I got. Happy to provide more info if it’d help.

Traceback (most recent call last):
  File "app/models/convert_model.py", line 93, in <module>
    export_for_serving("resnet50_kw_24.h5", model)
  File "app/models/convert_model.py", line 84, in export_for_serving
    tf_estimator = model_to_estimator(keras_model_path=model_path, custom_objects=c_o)
  File "/home/max/anaconda3/envs/paper2digital/lib/python3.7/site-packages/tensorflow/python/keras/estimator/__init__.py", line 73, in model_to_estimator
    config=config)
  File "/home/max/anaconda3/envs/paper2digital/lib/python3.7/site-packages/tensorflow_estimator/python/estimator/keras.py", line 458, in model_to_estimator
    keras_model = models.load_model(keras_model_path)
  File "/home/max/anaconda3/envs/paper2digital/lib/python3.7/site-packages/tensorflow/python/keras/engine/saving.py", line 234, in load_model
    model = model_from_config(model_config, custom_objects=custom_objects)
  File "/home/max/anaconda3/envs/paper2digital/lib/python3.7/site-packages/tensorflow/python/keras/engine/saving.py", line 324, in model_from_config
    return deserialize(config, custom_objects=custom_objects)
  File "/home/max/anaconda3/envs/paper2digital/lib/python3.7/site-packages/tensorflow/python/keras/layers/serialization.py", line 74, in deserialize
    printable_module_name='layer')
  File "/home/max/anaconda3/envs/paper2digital/lib/python3.7/site-packages/tensorflow/python/keras/utils/generic_utils.py", line 192, in deserialize_keras_object
    list(custom_objects.items())))
  File "/home/max/anaconda3/envs/paper2digital/lib/python3.7/site-packages/tensorflow/python/keras/engine/network.py", line 1263, in from_config
    process_layer(layer_data)
  File "/home/max/anaconda3/envs/paper2digital/lib/python3.7/site-packages/tensorflow/python/keras/engine/network.py", line 1249, in process_layer
    layer = deserialize_layer(layer_data, custom_objects=custom_objects)
  File "/home/max/anaconda3/envs/paper2digital/lib/python3.7/site-packages/tensorflow/python/keras/layers/serialization.py", line 74, in deserialize
    printable_module_name='layer')
  File "/home/max/anaconda3/envs/paper2digital/lib/python3.7/site-packages/tensorflow/python/keras/utils/generic_utils.py", line 194, in deserialize_keras_object
    return cls.from_config(cls_config)
  File "/home/max/anaconda3/envs/paper2digital/lib/python3.7/site-packages/tensorflow/python/keras/engine/base_layer.py", line 402, in from_config
    return cls(**config)
  File "/home/max/anaconda3/envs/paper2digital/lib/python3.7/site-packages/tensorflow/python/keras/layers/normalization.py", line 155, in __init__
    name=name, trainable=trainable, **kwargs)
  File "/home/max/anaconda3/envs/paper2digital/lib/python3.7/site-packages/tensorflow/python/training/checkpointable/base.py", line 442, in _method_wrapper
    method(self, *args, **kwargs)
  File "/home/max/anaconda3/envs/paper2digital/lib/python3.7/site-packages/tensorflow/python/keras/engine/base_layer.py", line 122, in __init__
    raise TypeError('Keyword argument not understood:', kwarg)
TypeError: ('Keyword argument not understood:', 'freeze')
Read more comments on GitHub >

github_iconTop Results From Across the Web

Train and serve a TensorFlow model with ...
This guide trains a neural network model to classify images of clothing, like sneakers and shirts, saves the trained model, and then serves ......
Read more >
Serving TensorFlow models with TF Serving
TensorFlow Serving is a flexible, high-performance serving system for machine learning models, designed for production environments.
Read more >
Convert a TensorFlow model in a format that can be served
tf.saved_model.simple_save => In this case, only Predict API is supported during Serving. Example of this is mentioned by KrisR89 in his answer.
Read more >
How to Serve Machine Learning Models With TensorFlow ...
In this tutorial, I'm going to show you how to serve ML models using Tensorflow Serving, an efficient, flexible, high-performance serving system for...
Read more >
Issue in tensorflow serving java API when using keras ...
As load the model using tensorflow serving java apis, we encountered the log “The specified SavedModel has no variables; no checkpoints were restored.”.It...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found