简体   繁体   English

导出自定义Keras模型以用于Cloud ML Engine进行预测

[英]Export a custom Keras model to be used for prediction with the Cloud ML Engine

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. 我很难导出经过Keras培训的自定义VGG-Net(并非完全来自Keras),因此可以将其用于Google Cloud Predict API。 I am loading my model with Keras. 我正在用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. 我要分类的图像被编码为base64字符串。 So, I will have to decode it for the prediction task with some code that I found in one of the google examples. 因此,为了进行预测任务,我必须使用在一个Google示例中找到的一些代码对它进行解码。

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? 现在如何将该输入张量放入模型中,并获得正确的输出张量,以便能够定义SignatureDef,然后将图形导出为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. 免责声明 :尽管我是Cloud ML Engine预测服务的专家,并且对TensorFlow相当了解,但我对Keras并不十分了解。 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. 代码加载模型,然后将其导出为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. 基本思想是开始为输入(输入占位符,图像解码,调整大小和批处理等)构建“原始” TensorFlow模型,然后通过“重建” VGG将其“连接”为Keras VGG模型模型结构,最后将保存的权重还原到新建模型中。 Then we save this version of the model out as a SavedModel. 然后,将这个版本的模型另存为SavedModel。

The "magic" here is the connection between the raw TF preprocessing and the VGG model. 这里的“魔术”是原始TF预处理与VGG模型之间的联系。 This happens by passing the "output" of the TF preprocessing graph ( input_tensor in the code below) as the input_tensor to the Keras VGG graph. 这种情况通过使所述TF预处理图表的“输出”( input_tensor在下面的代码)作为input_tensor到Keras VGG曲线图。 input_tensor contains a batch of already decoded and resized images, just like VGG expects. 就像VGG期望的那样, input_tensor包含一批已经解码和调整大小的图像。

import keras.backend as K
import tensorflow as tf
from keras.models import load_model, Sequential
from tensorflow.python.saved_model import builder as saved_model_builder
from tensorflow.python.saved_model import tag_constants, signature_constants
from tensorflow.python.saved_model.signature_def_utils_impl import predict_signature_def

MODEL_FILE = 'model.h5'
WEIGHTS_FILE = 'weights.h5'
EXPORT_PATH = 'YOUR/EXPORT/PATH'

channels = 3
height = 96
width = 96

def build_serving_inputs():

  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(input_tensor, dtype=tf.float32) 

  return image_str_tensor, input_tensor, key_input, key_output

# reset session
K.clear_session()

with tf.Graph().as_default() as g, tf.Session(graph=g) as sess:
  K.set_session(sess)

  image_str_tensor, input_tensor, key_input, key_output = build_serving_inputs()

  # disable loading of learning nodes
  K.set_learning_phase(0)

  # Load model and save out the weights
  model = load_model(MODEL_FILE)
  model.save_weights(WEIGHTS_FILE)

  # Rebuild the VGG16 model with the weights
  new_model = keras.applications.vgg16.VGG16(
    include_top=True, weights=WEIGHTS_FILE, input_tensor=input_tensor,
    input_shape=[width, height, channels], pooling=None)

  # export saved model
  tf.saved_model.simple_save(
      sess,
      EXPORT_PATH,
      inputs={'image_bytes': image_str_tensor, 'key': key_input},
      outputs={'predictions': new_model.outputs[0], 'key': key_output}
  )

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_inputs creates a tensor with a batch dimension and passes it to Keras. build_serving_inputs创建具有批处理尺寸的张量,并将其传递给Keras。

TensorFlow Keras (tf.keras) now has a way to go from Keras model to TF Estimator tf.keras.estimator.model_to_estimator . TensorFlow Keras(tf.keras)现在可以从Keras模型转到TF估计器tf.keras.estimator.model_to_estimator Estimator will get you to the SavedModel which you can use with Cloud ML Engine for prediction. Estimator将带您到SavedModel,您可以将其与Cloud ML Engine一起使用进行预测。 Checkout this post for the usage of this API. 查看此帖子以了解此API的用法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM