免责声明:虽然我是 Cloud ML Engine 预测服务方面的专家,并且对 TensorFlow 相当了解,但我对 Keras 不是很了解。我只是将其他地方的信息拼凑在一起,特别是这个样本和这个答案。我只能想象有更好的方法来做到这一点,我希望人们会发布这样的。同时,我希望这能满足您的需求。
这个特定的答案假设您已经保存了模型。代码加载模型,然后将其导出为 SavedModel。
基本思想是开始为输入(输入占位符、图像解码、调整大小和批处理等)构建“原始”TensorFlow 模型,然后通过“重建”VGG 将其“连接”到 Keras VGG 模型模型结构,最后将保存的权重恢复到新建的模型中。然后我们将这个版本的模型保存为 SavedModel。
这里的“魔力”是原始 TF 预处理和 VGG 模型之间的联系。这是通过将 TF 预处理图(input_tensor
在下面的代码中)的“输出”作为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。