Search code examples
pythontensorflowkerastensorflow-servingresnet

Exporting VGGFace ResNet to Tensorflow Serving: ValueError: The last dimension of the inputs to `Dense` should be defined. Found `None`


I have a code to load VGGFace pretrained ResNet model and export it to the tensorflow serving format. The snippet has worked on similar models that are not VGGFace ResNet.

import tensorflow as tf
import keras
from keras_vggface.vggface import VGGFace

tf.keras.backend.set_learning_phase(0) 
CHANNELS = 3

model = VGGFace(model='resnet50')
model.compile(
    loss=keras.losses.categorical_crossentropy,
    optimizer='adam',
    metrics=['accuracy'])
model.save('models/VGGFaceResnet50_celebrity_classifier.h5')

def serving_input_receiver_fn():

    def decode_and_resize(image_str_tensor):
        """Decodes jpeg string, resizes it and raeturns a uint8 tensor."""
        image = tf.image.decode_jpeg(image_str_tensor, channels=CHANNELS)
        image = tf.cast(image, dtype=tf.uint8)
        return image

    # Optional; currently necessary for batch prediction.
    key_input = tf.placeholder(tf.string, shape=[None]) 
    key_output = tf.identity(key_input)

    input_ph = tf.placeholder(tf.string, shape=[None], name='image_binary')
    images_tensor = tf.map_fn(
            decode_and_resize, input_ph, back_prop=False, dtype=tf.uint8)
    images_tensor = tf.image.convert_image_dtype(images_tensor, dtype=tf.float32) 

    return tf.estimator.export.ServingInputReceiver(
         {'input_1': images_tensor},
         {'bytes': input_ph})


KERAS_MODEL_PATH='models/VGGFaceResnet50_celebrity_classifier.h5'
EXPORT_PATH='serving_model'

# If you are invoking this from your training code, use `keras_model=model` instead.
estimator = tf.keras.estimator.model_to_estimator(
    keras_model_path=KERAS_MODEL_PATH)
estimator.export_savedmodel(
    EXPORT_PATH,
    serving_input_receiver_fn=serving_input_receiver_fn
) 

However, I get the following error:

ValueError                  Traceback (most recent call last)
<ipython-input-1-edfbc77c298a> in <module>
     44 estimator.export_savedmodel(
     45     EXPORT_PATH,
---> 46     serving_input_receiver_fn=serving_input_receiver_fn
     47 ) 
...
ValueError: The last dimension of the inputs to `Dense` should be defined. Found `None`.

I checked the model summary and I don't see any None in the last dimension. Why is there an error?


Solution

  • Constructor of the VGGFace is defined as: def VGGFace(include_top=True, model='vgg16', weights='vggface', input_tensor=None, input_shape=None, pooling=None, classes=None). The size of the last dimension is computed based on the input_shape, i.e. if it is None last dimension size will be None as well.