【tensorlow】tensorflow-serving教程
概述
tensorflow-serving支持rpc和rest,本文基于rest编写。构建k8s的pod
部署
单模型部署,dockerfile如下:
FROM tensorflow/serving
MAINTAINER zhouwenyang
ADD model /models/${model_name}/${version}
ENV MODEL_NAME=${model_name}
${model_name}和${version}根据自己需要更改。可以使用挂载文件的方式,但是如果部署k8s则需要打进容器,或者使用共享的volumes的方式
多模型部署参考:https://www.jianshu.com/p/d11a5c3dc757
查看模型输入输出情况: http://${host}:${port}/v1/models/${model_name}/metadata
指定/回滚版本配置
在默认情况下,tf会自动加载最新版本的模型,根据文件名的序列号取最大值。在加入配置的情况,可以指定特定的版本,以及一个服务加载多个模型。
按照其proto定义,https://github.com/tensorflow/serving/blob/master/tensorflow_serving/config/model_server_config.proto#L76,配置如下model.config
model_config_list { config { name: "tf-test" base_path: "/mnt/models" model_platform: "tensorflow" model_version_policy { specific { versions: 1666017972 } } } }
该配置指定模型版本为1666017972,可以利用该配置方式对模型回滚或者指定部署版本。
对应其docker/pod 启动的args: --model_config_file=/mnt/models/models.config。
注意:在启动后使用--model_config_file后,需要严格按照proto定义去配置config文件,这意味着args的 --model_base_path和--model_name将会失效。下面的配置是无效的,因为不符合其proto要求
model_config_list { config { model_platform: "tensorflow" model_version_policy { specific { versions: 1666017972 } } } }
自定义op
预测
根据查看模型的metadata,搞起一个http post接口
接口地址为: http://${host}:${port}/v1/models/${model_name}:predict
post参数为:
{ "inputs":{ "${param1}":${value1}, "${param2}":${value2}, "${param3}":${value3}, "${param4}":${value4} } }
冷启动
tf-serving默认情况下是冷启动,这会导致在模型迭代时响应时间造成极大的波动。
解决方案: https://www.tensorflow.org/tfx/serving/saved_model_warmup
大概意思就是在 {版本}/saved_model.pb 文件同级 建一个 {版本}/assets.extra 文件夹,然后在里面生成一个tf_serving_warmup_requests 文件
步骤:
- 添加依赖: pip install tensorflow-serving-api
这边意外发现安装tensorflow-serving-api时会安装对应版本的tensorflow。通过安装tensorflow-serving-api可以使得python3.6上装tensorflow2.6
- 编辑代码
import tensorflow as tf from tensorflow_serving.apis import classification_pb2 from tensorflow_serving.apis import inference_pb2 from tensorflow_serving.apis import model_pb2 from tensorflow_serving.apis import predict_pb2 from tensorflow_serving.apis import prediction_log_pb2 from tensorflow_serving.apis import regression_pb2 def main(): with tf.io.TFRecordWriter("tf_serving_warmup_requests") as writer: # replace <request> with one of: # predict_pb2.PredictRequest(..) # classification_pb2.ClassificationRequest(..) # regression_pb2.RegressionRequest(..) # inference_pb2.MultiInferenceRequest(..) log = prediction_log_pb2.PredictionLog( predict_log=prediction_log_pb2.PredictLog(request=<request>)) writer.write(log.SerializeToString()) if __name__ == "__main__": main()
- 修改模型内容
模型解压后,格式如下:
问题
- tag只支持serve
tf-serving模型目前支持模型tag为serve。这个是因为tf-serving官方支持的比较烂
排查: 查看源码 https://github.com/tensorflow/serving/blob/ceba636bb7c5c98bde35d1818fd033b36300fffe/tensorflow_serving/model_servers/main.cc#L189
查看tensorflow-serving这个镜像的Dockerfile如下: https://hub.docker.com/layers/tensorflow/serving/latest/images/sha256-6651f4839e1124dbde75ee531825112af0a6b8ef082c88ab14ca53eb69a2e4bb?context=explore 可知,其实tf-serving的docker镜像内部就是运行的/usr/bin/tf_serving_entrypoint.sh 脚本,
脚本内容:
#!/bin/bash
tensorflow_model_server --port=8500 --rest_api_port=8501 --model_name=${MODEL_NAME} --model_base_path=${MODEL_BASE_PATH}/${MODEL_NAME} "$@"
解决:
编写tf-serving-entrypoint.sh
#!/bin/bash
tensorflow_model_server --port=8500 --rest_api_port=8501 --model_name=${MODEL_NAME} --model_base_path=${MODEL_BASE_PATH}/${MODEL_NAME} --saved_model_tags=${MODEL_TAGS} "$@"
编写Dockerfile
FROM tensorflow/serving:latest MAINTAINER zhouwenyang ENV MODEL_TAGS=serve ADD tf_serving_entrypoint.sh /usr/bin RUN chmod u+x /usr/bin/tf_serving_entrypoint.sh ENTRYPOINT ["/usr/bin/tf_serving_entrypoint.sh"]
然后docker build。使用这个生成的镜像代替tensorflow-serving官方镜像即可
具体使用:
docker run -itd --name my-tf -v /model:/models/1/modelname -e MODEL_NAME=modelname -e MODEL_TAGS=my-tag wenyangchou/tf-serving:latest
镜像已上传:wenyangchou/tf-serving:latest
配置参数
https://github.com/tensorflow/serving/blob/2b20315418346837a26a11f640fed0da90048a08/tensorflow_serving/g3doc/serving_config.md#batching-configuration