导出自定义 Keras 模型以用于使用 Cloud ML Engine 进行预测
Export a custom Keras model to be used for prediction with the Cloud ML Engine
我很难导出自定义的 VGG-Net(不完全是 Keras 的那个),它是用 Keras 训练的,因此它可以用于 Google Cloud Predict API。我正在用 Keras 加载我的模型。
sess = tf.Session()
K.set_session(sess)
model = load_model(model.h5)
我要分类的图像被编码为 base64 字符串。因此,我将不得不使用我在 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)
但到了这一步,我就不知道该怎么办了。我现在如何将这个输入张量放入我的模型并得到正确的输出张量,以便我能够定义 SignatureDef 然后将我的图形导出为 SavedModel?
如有任何帮助,我们将不胜感激。
免责声明:虽然我是 Cloud ML Engine 预测服务的专家,并且对 TensorFlow 相当了解,但我对 Keras 不是很了解。我只是将其他地方的信息拼凑在一起,特别是 this sample and this answer。我只能想象有更好的方法可以做到这一点,我希望人们会 post 这样。同时,希望这能满足您的需求。
此特定答案假设您已经保存了模型。代码加载模型,然后将其导出为 SavedModel。
基本思路是开始为输入(输入占位符、图像解码、调整大小和批处理等)构建 "raw" TensorFlow 模型,然后 "connect" Keras VGG model by "rebuilding" VGG模型结构,最后,将保存的权重恢复到新建的模型中。然后我们将这个版本的模型保存为 SavedModel。
这里的"magic"就是raw TF预处理和VGG模型的联系。这是通过将 TF 预处理图(下面代码中的 input_tensor
)的 "output" 作为 input_tensor
传递给 Keras VGG 图来实现的。input_tensor
包含一批已经解码的和调整图像大小,就像 VGG 期望的那样。
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}
)
注意我不知道这段代码是否有效(尚未测试);我担心它如何处理批量维度。 build_serving_inputs
创建一个具有批量维度的张量并将其传递给 Keras。
TensorFlow Keras (tf.keras) 现在有一种从 Keras 模型到 TF Estimator tf.keras.estimator.model_to_estimator. Estimator will get you to the SavedModel which you can use with Cloud ML Engine for prediction. Checkout this post 的方式来使用这个 API。
我很难导出自定义的 VGG-Net(不完全是 Keras 的那个),它是用 Keras 训练的,因此它可以用于 Google Cloud Predict API。我正在用 Keras 加载我的模型。
sess = tf.Session()
K.set_session(sess)
model = load_model(model.h5)
我要分类的图像被编码为 base64 字符串。因此,我将不得不使用我在 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)
但到了这一步,我就不知道该怎么办了。我现在如何将这个输入张量放入我的模型并得到正确的输出张量,以便我能够定义 SignatureDef 然后将我的图形导出为 SavedModel?
如有任何帮助,我们将不胜感激。
免责声明:虽然我是 Cloud ML Engine 预测服务的专家,并且对 TensorFlow 相当了解,但我对 Keras 不是很了解。我只是将其他地方的信息拼凑在一起,特别是 this sample and this answer。我只能想象有更好的方法可以做到这一点,我希望人们会 post 这样。同时,希望这能满足您的需求。
此特定答案假设您已经保存了模型。代码加载模型,然后将其导出为 SavedModel。
基本思路是开始为输入(输入占位符、图像解码、调整大小和批处理等)构建 "raw" TensorFlow 模型,然后 "connect" Keras VGG model by "rebuilding" VGG模型结构,最后,将保存的权重恢复到新建的模型中。然后我们将这个版本的模型保存为 SavedModel。
这里的"magic"就是raw TF预处理和VGG模型的联系。这是通过将 TF 预处理图(下面代码中的 input_tensor
)的 "output" 作为 input_tensor
传递给 Keras VGG 图来实现的。input_tensor
包含一批已经解码的和调整图像大小,就像 VGG 期望的那样。
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}
)
注意我不知道这段代码是否有效(尚未测试);我担心它如何处理批量维度。 build_serving_inputs
创建一个具有批量维度的张量并将其传递给 Keras。
TensorFlow Keras (tf.keras) 现在有一种从 Keras 模型到 TF Estimator tf.keras.estimator.model_to_estimator. Estimator will get you to the SavedModel which you can use with Cloud ML Engine for prediction. Checkout this post 的方式来使用这个 API。