docker
$ docker pull tensorflow/serving
docker run -it --rm -p 8500:8500 -p 8501:8501 \
-v "$ML_PATH/my_mnist_model:/models/my_mnist_model" \
-e MODEL_NAME=my_mnist_model \
tensorflow/serving
运行后我们要仔细看看日志,有没有报错,如果有报错,对外8500和8501端口是不对外访问的,但是内网可以访问8501(即使报错).
我们也可以使用下面命令看日志:
docker logs 容器名
2021-11-10 14:27:21.176828: W tensorflow_serving/sources/storage_path/file_system_storage_path_source.cc:268] No versions of servable my_mnist_model found under base path /models/my_mnist_model. Did you forget to name your leaf
说明没有找到我们的模型:
我的路径是
-v "/opt/tfmodel/mnist/saved/1:/models/my_mnist_model" \
后面去掉具体的版本号/1就可以了
-v "/opt/tfmodel/mnist/saved:/models/my_mnist_model"
上述命令需要注意:①当saved_model下有多个版本的模型时,它会自动选择最大版本号的模型。②模型的存放路径需要是绝对路径。③saved_model文件夹下面一定要有版本号文件夹,模型放在版本号文件夹中,否则会报错。
TensorFlow Serving 支持热更新模型,其典型的模型文件夹结构如下:
/saved_model_files
/1 # 版本号为1的模型文件
/assets
/variables
saved_model.pb
...
/N # 版本号为N的模型文件
/assets
/variables
saved_model.pb
上面 1~N 的子文件夹代表不同版本号的模型。当指定 --model_base_path
时,只需要指定根目录的 绝对地址 (不是相对地址)即可。例如,如果上述文件夹结构存放在 home/snowkylin
文件夹内,则 --model_base_path
应当设置为 home/snowkylin/saved_model_files
(不附带模型版本号)。TensorFlow Serving 会自动选择版本号最大的模型进行载入。
-it
使容器可交互(Ctrl-C 关闭),展示服务器的输出。
--rm
停止时删除容器。但不删除镜像。
-p 8500:8500
将 Docker 引擎将主机的 TCP 端口 8500 转发到容器的 TCP 端口 8500。默认时,TF Serving 使用这个端口服务 gRPC API。
-p 8501:8501
将 Docker 引擎将主机的 TCP 端口 8501 转发到容器的 TCP 端口 8501。默认时,TF Serving 使用这个端口服务 REST API。
-v "$ML_PATH/my_mnist_model:/models/my_mnist_model"
使主机的$ML_PATH/my_mnist_model
路径对容器的路径/models/mnist_model
开放。在 Windows 上,可能需要将/
替换为\
。
-e MODEL_NAME=my_mnist_model
将容器的MODEL_NAME
环境变量,让 TF Serving 知道要服务哪个模型。默认时,它会在路径/models
查询,并会自动服务最新版本。
tensorflow/serving
镜像名。
在客户端调用以 TensorFlow Serving 部署的模型
TensorFlow Serving 支持以 gRPC 和 RESTful API 调用以 TensorFlow Serving 部署的模型。本手册主要介绍较为通用的 RESTful API 方法。
RESTful API 以标准的 HTTP POST 方法进行交互,请求和回复均为 JSON 对象。为了调用服务器端的模型,我们在客户端向服务器发送以下格式的请求:
服务器 URI: http://服务器地址:端口号/v1/models/模型名:predict
请求内容:
{
"signature_name": "需要调用的函数签名(Sequential模式不需要)",
"instances": 输入数据
}
回复为:
{
"predictions": 返回值
}
ython 客户端示例
以下示例使用 Python 的 Requests 库 (你可能需要使用 pip install requests
安装该库)向本机的 TensorFlow Serving 服务器发送 MNIST 测试集的前 10 幅图像并返回预测结果,同时与测试集的真实标签进行比较。
import json
import numpy as np
import requests
from zh.model.utils import MNISTLoader
data_loader = MNISTLoader()
data = json.dumps({
"instances": data_loader.test_data[0:3].tolist()
})
headers = {"content-type": "application/json"}
json_response = requests.post(
'http://localhost:8501/v1/models/MLP:predict',
data=data, headers=headers)
predictions = np.array(json.loads(json_response.text)['predictions'])
print(np.argmax(predictions, axis=-1))
print(data_loader.test_label[0:10])
输出:
[7 2 1 0 4 1 4 9 6 9]
[7 2 1 0 4 1 4 9 5 9]
可见预测结果与真实标签值非常接近。
(上面代码可以简化:
import requests
SERVER_URL = 'http://localhost:8501/v1/models/my_mnist_model:predict'
response = requests.post(SERVER_URL, data=input_data_json)
response.raise_for_status() # raise an exception in case of error
response = response.json()
)
对于自定义的 Keras 模型,在发送的数据中加入 signature_name
键值即可,即将上面代码的 data
建立过程改为
data = json.dumps({
"signature_name": "call",
"instances": data_loader.test_data[0:10].tolist()
})
tensorflow serving热部署
这个文件里面说了,可以自己配置模型配置文件定期检查时间,那就是支持热部署的。如果不指定有默认的检查时间
- 一方面,支持多版本的热部署(比如当前生产环境部署的是1版本的模型,训练完成后生成一个2版本的模型,tensorflow会自动加载这个模型,停掉之前的模型)。
--model_config_file=/models/models.config \
--model_config_file_poll_wait_seconds=60
https://github.com/tensorflow/serving/blob/master/tensorflow_serving/g3doc/serving_config.md
https://www.136.la/shida/show-161983.html
https://tf.wiki/zh_hans/deployment/serving.html
https://jackiexiao.github.io/eat_tensorflow2_in_30_days/chinese/6.%E9%AB%98%E9%98%B6API/6-6,%E4%BD%BF%E7%94%A8tensorflow-serving%E9%83%A8%E7%BD%B2%E6%A8%A1%E5%9E%8B/
https://www.kancloud.cn/apachecn/hands-on-ml-2e-zh/1948582
https://blog.csdn.net/u011734144/article/details/82107610