关于与TensorFlow一起使用的几个问题,例如
我发现有许多与Estimator
的{{1}}相关的过时,或者使用了其他API(例如C#)。
此外,“ Basic” Serving Guide也不是。它假定熟悉docker,需要使用单独的TensorFlow repo,并且加载模型的指南仅限于以下内容:
使用标准TensorFlow ModelServer加载导出的模型
使用Docker服务映像轻松加载服务模型:
export_outputs
无需费心解释任何参数的含义以及如何将其适应自定义估算器。
有人可以用通俗易懂的方式向我解释,对于不知道gRPC服务是什么的人,如何从上述colab中提取导出的模型(例如我从{ {3}}至docker run -p 8500:8500 \
--mount type=bind,source=/tmp/mnist,target=/models/mnist \
-e MODEL_NAME=mnist -t tensorflow/serving &
)并提供服务(最好不使用docker)
答案 0 :(得分:2)
假设您有一个经过培训且随时可以提供服务的自定义估算器,就像问题中链接的估算器一样。保存并提供经过训练的估算器模型的过程为:
在某些情况下,您训练有素的估算器模型可能会更好地部署和重用,而无需提供服务。有时,最好冻结模型并将其直接部署在程序中。或者有时您想将模型转换为TensorFlow的javascript或lite版本。有很多方法可以重复使用经过训练的估算器而不提供服务。但是,由于您的问题专门询问有关服务的问题,因此该答案是有关如何专门为标准ModelServer服务的。
要准备训练有素的估算器进行投放,您必须将其导出为标准的SavedModel格式。
为此,我们可以使用export_saved_model
函数,并且需要首先定义服务输入接收器函数。服务输入接收器功能指定并命名在服务时成为模型输入的所有张量。
服务输入接收器功能有两种,每种类型都告诉TensorFlow在步骤3中应如何预期输入:
解析提供的输入接收器功能:这些输入以序列化的Example
原型提供。该类型告诉TensorFlow期望模型输入来自将被解析为特征的字符串张量。可以使用tf.estimator.export.build_parsing_serving_input_receiver_fn
构建此接收器。
原始服务的输入接收器功能:输入直接作为Tensor
原型提供。可以使用tf.estimator.export.build_raw_serving_input_receiver_fn
构建此接收器。
您的合作代码正在构建两个执行相同功能的接收器函数:
serving_fn = tf.estimator.export.build_raw_serving_input_receiver_fn(
{'input_tensors': tf.placeholder(tf.float32, I_SHAPE(None), name="input_tensors")})
和:
def serving_input_receiver_fn():
input_tensors = tf.placeholder(tf.float32, I_SHAPE(None), name="input_tensors")
features = {'input_tensors' : input_tensors}
receiver_tensors = {'input_tensors': input_tensors}
return tf.estimator.export.ServingInputReceiver(features, receiver_tensors)
但是只能导出一个:
est.export_savedmodel('./here', serving_input_receiver_fn)
您可以删除serving_input_receiver_fn
方法并使用第一个定义:
est.export_savedmodel('./here', serving_fn)
和
exporter = tf.estimator.BestExporter(
name="best_exporter",
serving_input_receiver_fn=serving_fn,
exports_to_keep=5
)
您的问题是您希望不使用docker来提供模型。根据{{3}},docker映像仅在运行its Dockerfile二进制文件,您可以按照其自述文件中的说明从容器外部的源代码安装或构建二进制文件,也可以从{{1 }}容器。
一旦安装了二进制文件,请运行它以启动gRPC服务器,以侦听所需的端口,例如8500:
tensorflow/serving
现在,您正在“服务”模型。如果您只想运行模型而不需要tensorflow_serving存储库中的任何内容,则可以使用TensorFlow ModelServer来运行不带模型服务器的SavedModel。如果是从预构建的二进制文件安装的,则应该已经与TensorFlow一起安装了。
查询模型的标准方法是使用ModelServer提供的gRPC服务。 gRPC是saved model command line interface框架,它使用Google的协议缓冲区格式来定义服务并在主机之间进行通信。它被设计为快速,跨平台和可扩展的。当您已经以protobuf格式处理了所有数据时,例如在处理TFRecord文件时,这将特别方便。
有许多不同语言的gRPC库,您甚至可以通过以下方式与服务器通信: cURL,但是由于您的问题是针对Python标记的,因此我将使用RPC和grpcio Python包来执行针对所提供的模型进行预测所需的gRPC调用。
服务器运行并安装Python软件包后,您可以通过查询模型的签名def元数据来验证连接:
tensorflow_model_server --port=8500 --model_name=my_model --model_base_path=/path/to/export/dir
有了合作实验室中的模型,您会看到
from __future__ import print_function
import grpc
from tensorflow_serving.apis import get_model_metadata_pb2
from tensorflow_serving.apis import model_pb2
from tensorflow_serving.apis import prediction_service_pb2_grpc
with grpc.insecure_channel("localhost:8500") as channel:
stub = prediction_service_pb2_grpc.PredictionServiceStub(channel)
request = get_model_metadata_pb2.GetModelMetadataRequest(
model_spec=model_pb2.ModelSpec(name="my_model"),
metadata_field=["signature_def"])
response = stub.GetModelMetadata(request)
sigdef_str = response.metadata["signature_def"].value
print ("Name:", response.model_spec.name)
print ("Version:", response.model_spec.version.value)
print (get_model_metadata_pb2.SignatureDefMap.FromString(sigdef_str))
因此,根据其签名定义,模型期望将Name: my_model
Version: ...
signature_def {
key: "labels"
value {
inputs {
key: "input_tensors"
value {
name: "input_tensors:0"
dtype: DT_FLOAT
tensor_shape {
dim {
size: -1
}
dim {
size: 20
}
dim {
size: 7
}
}
}
}
outputs {
key: "output"
value {
name: "Sigmoid:0"
dtype: DT_FLOAT
tensor_shape {
dim {
size: -1
}
dim {
size: 20
}
dim {
size: 4
}
}
}
}
method_name: "tensorflow/serving/predict"
}
}
signature_def {
key: "serving_default"
value {
inputs {
key: "input_tensors"
value {
name: "input_tensors:0"
dtype: DT_FLOAT
tensor_shape {
dim {
size: -1
}
dim {
size: 20
}
dim {
size: 7
}
}
}
}
outputs {
key: "output"
value {
name: "Sigmoid:0"
dtype: DT_FLOAT
tensor_shape {
dim {
size: -1
}
dim {
size: 20
}
dim {
size: 4
}
}
}
}
method_name: "tensorflow/serving/predict"
}
}
键映射到浮点类型和形状input_tensors
的Tensor原型的字典,并将输出映射[-1, 20, 7]
键的字典浮点类型和形状output
的Tensor原型。我们可以使用tensorflow-serving-api在numpy数组中用Python创建Tensor原型,然后使用tf.make_tensor_proto
进行转换:
[-1, 20, 4]
实际上,您应该具有由服务的估算器模型返回的形状为from __future__ import print_function
import grpc
import numpy as np
import tensorflow as tf
from tensorflow_serving.apis import model_pb2
from tensorflow_serving.apis import predict_pb2
from tensorflow_serving.apis import prediction_service_pb2_grpc
# Dummy input data for batch size 3.
batch_input = np.ones((3, 20, 7), dtype="float32")
with grpc.insecure_channel("localhost:8500") as channel:
stub = prediction_service_pb2_grpc.PredictionServiceStub(channel)
request = predict_pb2.PredictRequest(
model_spec=model_pb2.ModelSpec(name="my_model"),
inputs={"input_tensors": tf.make_tensor_proto(batch_input)})
response = stub.Predict(request)
batch_output = tf.make_ndarray(response.outputs["output"])
print (batch_output.shape)
的浮点数组。
有关如何在Python中定义和使用gRPC服务的更多信息,请参见tf.make_ndarray
。有关(3, 20, 4)
API的详细信息,请参见tutorial on the gRPC website。
答案 1 :(得分:1)
在链接的colab代码中,run your estimator之后,您应该在colab的默认文件系统中拥有一个saved_model.pb
和/variables
文件夹。我将这些文件的位置称为OUTPUT_PATH
。
要弄清楚OUTPUT_PATH
是什么,让我们在这里快速浏览colab中的相关代码:
Estimator > define exporter
exporter = tf.estimator.BestExporter( name="best_exporter", serving_input_receiver_fn=serving_input_receiver_fn, exports_to_keep=5 ) # this will keep the 5 best checkpoints
和
Estimator > init estimator
est = tf.estimator.Estimator( model_fn = model_fn, config = run_config, # <--- model_dir is set in here params = run_params, )
自Setup > Constants
下定义MODEL_DIR = './test'
起,您的BestExporter
被保存在test/export/best_exporter/<model_num>/
下
所以您的OUTPUT_PATH
等于那个。
将此文件夹下载到要存储结果的位置。为了提高可读性,请使用有意义的名称重命名<model_num>
,例如test/export/best_exporter/demo_model
为清楚起见,使用docker服务并使用经修改的docker命令:
docker run -p 8500:8500 \
--mount type=bind,\
source=$OUTPUT_PATH,\
target=/models/$MODEL_NAME \
-e MODEL_NAME=$MODEL_NAME -t tensorflow/serving &
对于未使用docker的用户,source=$OUTPUT_PATH,target=/models/$MODEL_NAME
将目录OUTPUT_PATH
映射到docker容器的目录/models/$MODEL_NAME
。
因此在这种情况下,您将:
source=<path-to-downloaded-dir>/test/export/best_exporter/demo_model,\
target=/models/demo_model,\
-e MODEL_NAME=demo_model
我们假设源是model_dir
,而<path-to-downloaded-dir>
是您下载/test/export/best_exporter/demo_model
的位置。
然后按照grpc示例编写客户端。
如果您更喜欢RESTful API,则可能需要将docker端口更改为8501:8501
或同时使用8500-8501:8500-8501
。这是我的另一个answer,用于解释此docker命令。
如果您不想使用docker,请尝试安装tf-serving locally,这几乎是运行服务器的相同命令。