I have difficulties exporting a custom VGG-Net (not exactly the one from Keras), that was trained with Keras, so that it can be used for the Google Cloud Predict API. I am loading my model with Keras.
sess = tf.Session()
K.set_session(sess)
model = load_model(model.h5)
The image that I want to classify was encoded as base64 string. So, I will have to decode it for the prediction task with some code that I found in one of the google examples.
channels = 3
height = 96
width = 96
def decode_and_resize(image_str_tensor):
"""Decodes jpeg string, resizes it and returns a uint8 tensor."""
image = tf.image.decode_jpeg(image_str_tensor, channels=channels)
image = tf.expand_dims(image, 0)
image = tf.image.resize_bilinear(
image, [height, width], align_corners=False)
image = tf.squeeze(image, squeeze_dims=[0])
image = tf.cast(image, dtype=tf.uint8)
return image
image_str_tensor = tf.placeholder(tf.string, shape=[None])
key_input = tf.placeholder(tf.string, shape=[None])
key_output = tf.identity(key_input)
input_tensor = tf.map_fn(
decode_and_resize, image_str_tensor, back_prop=False, dtype=tf.uint8)
input_tensor = tf.image.convert_image_dtype(image, dtype=tf.float32)
But after this point, I do no longer know how to proceed. How can I now put this input tensor into my model and get out the correct output tensor, so that I am able to define the SignatureDef and then export my graph as a SavedModel?
Any help would be appreciated.
Disclaimer: Although I'm an expert on Cloud ML Engine's prediction service, and fairly knowledgeable on TensorFlow, I do not know Keras very well. I'm simply piecing together information from other places, notably, this sample and this answer. I can only imagine there being better ways to do this and I hope folks will post such. In the meantime, I hope this serves your needs.
This particular answer assumes you've already saved the model. The code loads the model then exports it as a SavedModel.
The basic idea is to start building a "raw" TensorFlow model for the inputs (the input placeholder, the image decoding, resizing, and batching, etc.), and then "connect" it a Keras VGG model by "rebuilding" the VGG model structure and, finally, restoring the saved weights into the newly built model. Then we save this version of the model out as a SavedModel.
The "magic" here is the connection between the raw TF preprocessing and the VGG model. This happens by passing the "output" of the TF preprocessing graph (
input_tensorin the code below) as theinput_tensorto the Keras VGG graph.input_tensorcontains a batch of already decoded and resized images, just like VGG expects.Note I don't know if this code quite works yet (haven't tested); I'm worried about how it handles the batch dimension.
build_serving_inputscreates a tensor with a batch dimension and passes it to Keras.