使用 TensorFlow Serving 服务 Keras 模型

Posted

技术标签:

【中文标题】使用 TensorFlow Serving 服务 Keras 模型【英文标题】:Serving Keras Models With Tensorflow Serving 【发布时间】:2017-09-24 18:22:02 【问题描述】:

现在,我们可以使用 Tensorflow Serving 成功地为模型提供服务。我们使用以下方法导出模型并使用 Tensorflow Serving 托管它。

     ------------
      For exporting 
     ------------------
     from tensorflow.contrib.session_bundle import exporter

     K.set_learning_phase(0)
     export_path = ... # where to save the exported graph
     export_version = ... # version number (integer)

     saver = tf.train.Saver(sharded=True)
     model_exporter = exporter.Exporter(saver)
     signature = exporter.classification_signature(input_tensor=model.input,
                                          scores_tensor=model.output)
     model_exporter.init(sess.graph.as_graph_def(),
                default_graph_signature=signature)
     model_exporter.export(export_path, tf.constant(export_version), sess)

      --------------------------------------

      For hosting
      -----------------------------------------------

      bazel-bin/tensorflow_serving/model_servers/tensorflow_model_server --port=9000 --model_name=default --model_base_path=/serving/models

但是我们的问题是 - 我们希望将 keras 与 Tensorflow 服务集成。我们想通过使用 Keras 的 Tensorflow 服务来服务模型。 我们想要这样做的原因是 - 在我们的架构中,我们遵循几种不同的方法来训练我们的模型,比如 deeplearning4j + Keras, Tensorflow + Keras,但对于服务,我们只想使用一个可服务的引擎,即 Tensorflow Serving。我们没有看到任何直接的方法来实现这一目标。有没有cmets?

谢谢。

【问题讨论】:

我知道您要求提供 TF 服务,因此我不会将此作为答案发布,但如果您希望将实际工具附加到您的模型而不是黑匣子,您也可以查看:@987654321 @ for keras(我只提到这一点是因为您使用 dl4j 作为管道的一部分) 【参考方案1】:

最近,TensorFlow 改变了它导出模型的方式,因此网络上提供的大多数教程都已过时。老实说,我不知道 deeplearning4j 是如何工作的,但我经常使用 Keras。我设法创建了一个简单的示例,我已经在 TensorFlow Serving Github 的 issue 上发布了该示例。

我不确定这是否会对您有所帮助,但我想分享一下我的做法,也许它会给您一些见解。在创建自定义模型之前,我的第一次尝试是使用 Keras 上可用的训练模型,例如 VGG19。我是这样做的。

模型创建

import keras.backend as K
from keras.applications import VGG19
from keras.models import Model

# very important to do this as a first thing
K.set_learning_phase(0)

model = VGG19(include_top=True, weights='imagenet')

# The creation of a new model might be optional depending on the goal
config = model.get_config()
weights = model.get_weights()
new_model = Model.from_config(config)
new_model.set_weights(weights)

导出模型

from tensorflow.python.saved_model import builder as saved_model_builder
from tensorflow.python.saved_model import utils
from tensorflow.python.saved_model import tag_constants, signature_constants
from tensorflow.python.saved_model.signature_def_utils_impl import     build_signature_def, predict_signature_def
from tensorflow.contrib.session_bundle import exporter

export_path = 'folder_to_export'
builder = saved_model_builder.SavedModelBuilder(export_path)

signature = predict_signature_def(inputs='images': new_model.input,
                                  outputs='scores': new_model.output)

with K.get_session() as sess:
    builder.add_meta_graph_and_variables(sess=sess,
                                         tags=[tag_constants.SERVING],
                                         signature_def_map='predict': signature)
    builder.save()

一些旁注

可能因 Keras、TensorFlow 和 TensorFlow Serving 而异 版本。我用的是最新的。 注意签名的名称,因为它们也应该在客户端中使用。 创建客户端时,所有需要的预处理步骤 模型(例如 preprocess_input() )必须被执行。我没有尝试 在图中添加这样的步骤作为 Inception 客户端示例。

关于在同一服务器中提供不同的模型,我认为类似于创建 model_config_file 的东西可能会对您有所帮助。为此,您可以创建一个类似这样的配置文件:

model_config_list: 
  config: 
    name: "my_model_1",
    base_path: "/tmp/model_1",
    model_platform: "tensorflow"
  ,
  config: 
     name: "my_model_2",
     base_path: "/tmp/model_2",
     model_platform: "tensorflow"
  

最后,你可以像这样运行客户端:

bazel-bin/tensorflow_serving/model_servers/tensorflow_model_server --port=9000 --config_file=model_config.conf

【讨论】:

实际上我正在寻找一些关于“DL4J 到 Tensorflow Serving”的参考资料。但无论如何,这有帮助。谢谢托马斯。 我必须将所有模型文件放入带有版本号的base_path 的版本子文件夹中(例如/tmp/model/00001)。目前无法找到此内容的来源,但也许可以为未来的读者节省一些时间。 你能看看这里***.com/questions/65869272/…吗? 即使我在 Tensorflow Serving 的学习阶段也有这个问题,我在点击此链接 towardsdatascience.com/… 后得到了想法【参考方案2】:

试试我写的这个脚本,你可以将 keras 模型转换成 tensorflow 冻结图,(我看到有些模型在导出它们而不冻结变量时会产生奇怪的行为)。

import sys
from keras.models import load_model
import tensorflow as tf
from keras import backend as K
from tensorflow.python.framework import graph_util
from tensorflow.python.framework import graph_io
from tensorflow.python.saved_model import signature_constants
from tensorflow.python.saved_model import tag_constants


K.set_learning_phase(0)
K.set_image_data_format('channels_last')

INPUT_MODEL = sys.argv[1]
NUMBER_OF_OUTPUTS = 1
OUTPUT_NODE_PREFIX = 'output_node'
OUTPUT_FOLDER= 'frozen'
OUTPUT_GRAPH = 'frozen_model.pb'
OUTPUT_SERVABLE_FOLDER = sys.argv[2]
INPUT_TENSOR = sys.argv[3]


try:
    model = load_model(INPUT_MODEL)
except ValueError as err:
    print('Please check the input saved model file')
    raise err

output = [None]*NUMBER_OF_OUTPUTS
output_node_names = [None]*NUMBER_OF_OUTPUTS
for i in range(NUMBER_OF_OUTPUTS):
    output_node_names[i] = OUTPUT_NODE_PREFIX+str(i)
    output[i] = tf.identity(model.outputs[i], name=output_node_names[i])
print('Output Tensor names: ', output_node_names)


sess = K.get_session()
try:
    frozen_graph = graph_util.convert_variables_to_constants(sess, sess.graph.as_graph_def(), output_node_names)    
    graph_io.write_graph(frozen_graph, OUTPUT_FOLDER, OUTPUT_GRAPH, as_text=False)
    print(f'Frozen graph ready for inference/serving at OUTPUT_FOLDER/OUTPUT_GRAPH')
except:
    print('Error Occured')



builder = tf.saved_model.builder.SavedModelBuilder(OUTPUT_SERVABLE_FOLDER)

with tf.gfile.GFile(f'OUTPUT_FOLDER/OUTPUT_GRAPH', "rb") as f:
    graph_def = tf.GraphDef()
    graph_def.ParseFromString(f.read())

sigs = 
OUTPUT_TENSOR = output_node_names
with tf.Session(graph=tf.Graph()) as sess:
    tf.import_graph_def(graph_def, name="")
    g = tf.get_default_graph()
    inp = g.get_tensor_by_name(INPUT_TENSOR)
    out = g.get_tensor_by_name(OUTPUT_TENSOR[0] + ':0')

    sigs[signature_constants.DEFAULT_SERVING_SIGNATURE_DEF_KEY] = \
        tf.saved_model.signature_def_utils.predict_signature_def(
            "input": inp, "outout": out)

    builder.add_meta_graph_and_variables(sess,
                                         [tag_constants.SERVING],
                                         signature_def_map=sigs)
    try:
        builder.save()
        print(f'Model ready for deployment at OUTPUT_SERVABLE_FOLDER/saved_model.pb')
        print('Prediction signature : ')
        print(sigs['serving_default'])
    except:
        print('Error Occured, please checked frozen graph')

【讨论】:

【参考方案3】:

我最近添加了this blogpost,它解释了如何保存 Keras 模型并使用 Tensorflow Serving 为其提供服务。

TL;DR: 保存 Inception3 预训练模型:

### Load a pretrained inception_v3
inception_model = keras.applications.inception_v3.InceptionV3(weights='imagenet')

# Define a destination path for the model
MODEL_EXPORT_DIR = '/tmp/inception_v3'
MODEL_VERSION = 1
MODEL_EXPORT_PATH = os.path.join(MODEL_EXPORT_DIR, str(MODEL_VERSION))

# We'll need to create an input mapping, and name each of the input tensors.
# In the inception_v3 Keras model, there is only a single input and we'll name it 'image'
input_names = ['image']
name_to_input = name: t_input for name, t_input in zip(input_names, inception_model.inputs)

# Save the model to the MODEL_EXPORT_PATH
# Note using 'name_to_input' mapping, the names defined here will also be used for querying the service later
tf.saved_model.simple_save(
    keras.backend.get_session(),
    MODEL_EXPORT_PATH,
    inputs=name_to_input,
    outputs=t.name: t for t in inception_model.outputs)

然后启动一个 TF 服务 Docker:

    将保存的模型复制到主机的指定目录。 (本例中为 source=/tmp/inception_v3)

    运行泊坞窗:

docker run -d -p 8501:8501 --name keras_inception_v3 --mount type=bind,source=/tmp/inception_v3,target=/models/inception_v3 -e MODEL_NAME=inception_v3 -t tensorflow/serving
    验证是否可以通过网络访问 Tensorflow 服务。为了获取本地 docker ip (172.*.*.*) 进行测试运行:
docker inspect -f 'range .NetworkSettings.Networks.IPAddressend' keras_inception_v3

【讨论】:

以上是关于使用 TensorFlow Serving 服务 Keras 模型的主要内容,如果未能解决你的问题,请参考以下文章

为 TensorFlow Serving 保存模型

Tensorflow serving的编译

学习笔记tensorflow-serving模型部署

TensorFlow REST 前端,但不是 TensorFlow Serving

81TensorFlow 2 模型部署方法实践--TensorFlow Serving 部署模型

Tensorflow Serving介绍及部署安装