【Keras】TensorFlow Serving
当我们将模型训练完毕后,往往需要将模型在生产环境中部署。最常见的方式,是在服务器上提供一个 API,即客户机向服务器的某个 API 发送特定格式的请求,服务器收到请求数据后通过模型进行计算,并返回结果。如果仅仅是做一个 Demo,不考虑高并发和性能问题,其实配合 Flask 等 Python 下的 Web 框架就能非常轻松地实现服务器 API。不过,如果是在真的实际生产环境中部署,这样的方式就显得力不从心了。这时,TensorFlow 为我们提供了 TensorFlow Serving 这一组件,能够帮助我们在实际生产环境中灵活且高性能地部署机器学习模型。
TensorFlow Serving简单来说就是一个适合在生产环境中对tensorflow深度学习模型进行部署,然后可以非常方便地通过restful形式的接口进行访问。
除此之外,它拥有许多有点:
- 支持配置文件的定期轮询更新(periodically poll for updated),无需重新启动;
- 优秀的模型版本控制;
- 支持并发;
- 支持批处理;
- 基于docker,部署简单。
一、TensorFlow Serving 安装
TensorFlow Serving 可以使用 apt-get 或 Docker 安装。在生产环境中,推荐 使用 Docker 部署 TensorFlow Serving 。不过此处出于教学目的,介绍依赖环境较少的 apt-get 安装 。
首先设置安装源:
# 添加Google的TensorFlow Serving源
echo "deb [arch=amd64] http://storage.googleapis.com/tensorflow-serving-apt stable tensorflow-model-server tensorflow-model-server-universal" | sudo tee /etc/apt/sources.list.d/tensorflow-serving.list
# 添加gpg key
curl https://storage.googleapis.com/tensorflow-serving-apt/tensorflow-serving.release.pub.gpg | sudo apt-key add -
更新源后,即可使用 apt-get 安装 TensorFlow Serving
sudo apt-get update
sudo apt-get install tensorflow-model-server
二、TensorFlow Serving 模型部署
TensorFlow Serving 可以直接读取 SavedModel 格式的模型进行部署。使用以下命令即可:
tensorflow_model_server \--rest_api_port=端口号(如8501) \--model_name=模型名 \--model_base_path="SavedModel格式模型的文件夹绝对地址(不含版本号)"
2.1 Keras Sequential 模式模型的部署
由于 Sequential 模式的输入和输出都很固定,因此这种类型的模型很容易部署,无需其他额外操作。例如,要将 使用 SavedModel 导出的 MNIST 手写体识别模型 (使用 Keras Sequential 模式建立)以 MLP 的模型名在 8501 端口进行部署,可以直接使用以下命令:
tensorflow_model_server \--rest_api_port=8501 \--model_name=MLP \--model_base_path="/home/.../.../saved" # 文件夹绝对地址根据自身情况填写,无需加入版本号
然后就可以使用 gRPC 或者 RESTful API 在客户端调用模型了。
2.2 自定义 Keras 模型的部署
使用继承 tf.keras.Model 类建立的自定义 Keras 模型的自由度相对更高。因此当使用 TensorFlow Serving 部署模型时,对导出的 SavedModel 文件也有更多的要求:
- 需要导出到 SavedModel 格式的方法(比如 call )不仅需要使用 @tf.function 修饰,还要在修饰时指定 input_signature 参数,以显式说明输入的形状。该参数传入一个由 tf.TensorSpec 组成的列表,指定每个输入张量的形状和类型。例如,对于 MNIST 手写体数字识别,我们的输入是一个 [None, 28, 28, 1] 的四维张量( None 表示第一维即 Batch Size 的大小不固定),此时我们可以将模型的 call 方法做以下修饰:
class MLP(tf.keras.Model):...@tf.function(input_signature=[tf.TensorSpec([None, 28, 28, 1], tf.float32)])def call(self, inputs):...
- 在将模型使用 tf.saved_model.save 导出时,需要通过 signature 参数提供待导出的函数的签名(Signature)。简单说来,由于自定义的模型类里可能有多个方法都需要导出,因此,需要告诉 TensorFlow Serving 每个方法在被客户端调用时分别叫做什么名字。例如,如果我们希望客户端在调用模型时使用 call 这一签名来调用 model.call 方法时,我们可以在导出时传入 signature 参数,以 dict 的键值对形式告知导出的方法对应的签名,代码如下:
model = MLP()
...
tf.saved_model.save(model, "saved_with_signature/1", signatures={"call": model.call})
以上两步均完成后,即可使用以下命令部署:
tensorflow_model_server \--rest_api_port=8501 \--model_name=MLP \--model_base_path="/home/.../.../saved_with_signature" # 修改为自己模型的绝对地址
2.3 自定义版本
TensorFlow Serving有着优秀的模型版本控制功能。首先,TensorFlow Serving默认是加载最大版本号的模型。例如,上面我们部署了一个版本号为“1”的模型,如果之后模型又进行更新,版本号升级为“2”,那么仅需要将新的模型拷贝到相同的目录下即可。
比如,这个时候就有两个模型/tmp/model/1和/tmp/model/2,TensorFlow Serving会默认加载版本号“2”的模型。
如果我们想要多个版本的模型同时存在,并且多个模型同时部署,那么也是可以实现的。
在/tmp/model下创建一个models.config文件,以protocol的形式写入以下内容:
model_config_list {config {name: 'myserving'base_path: '/models/myserving/'model_platform: 'tensorflow'model_version_policy {specific {versions: 1versions: 2}}version_labels {key: 'stable'value: 1}version_labels {key: 'canary'value: 2}}config {name: 'model2'base_path: '/models/model2/'model_platform: 'tensorflow'}
}
可以看到,里面有两个config,意味着我们同时上线两个模型。
看第一个config:name为模型的名称,base_path为容器中模型的位置,model_platform就设置为tensorflow即可;
model_version_policy不加的话就是默认最新的版本控制策略。specific指定上线的版本,version_labels将版本号映射为对应的key,如stable对应版本号“1”的模型。
然后,在启动容器服务的时候,需要指定配置文件路径:
docker run -p 8501:8501 \
--mount type=bind,source=/tmp/model,target=/models/myserving \
-e MODEL_NAME=myserving -t tensorflow/serving \
--model_config_file=/models/models.config \
--allow_version_labels_for_unavailable_models=true
(如果不加这个配置项–allow_version_labels_for_unavailable_models=true,那么版本号和key的映射关系不能在启动时设置,只能在启动后才能进行设置)
那么,如果访问第一个模型的stable版本,地址则为:
http://localhost:8501/v1/models/myserving/labels/stable:predict
或者
http://localhost:8501/v1/models/myserving/versions/1:predict
官方推荐第一种。
2.4 轮询更新
想要对模型的配置文件进行定期轮询更新的话,只需要加上配置项
--model_config_file_poll_wait_seconds=60
这里是设置为60秒一次。
2.5 并发和批处理
批处理简单来说就是可以将多个接口的请求合并一个batch,然后模型计算完成之后一起返回。
在/tmp/model下创建一个batcj.config文件,仍是protocol的形式写入以下内容:
max_batch_size { value: 128 }
batch_timeout_micros { value: 1000 }
max_enqueued_batches { value: 1000000 }
num_batch_threads { value: 8 }
max_batch_size:一个批次允许的最大请求数量
batch_timeout_micros:合并一个批次等待的最长时间,即使该批次的数量未达到max_batch_size,也会立即进行计算(单位是微秒)
max_enqueued_batches:队列的最大数量
num_batch_threads:线程数,在这里体现并发。
这些都是全局设置,针对所有版本的模型!!!
那么,此时启动容器服务的命令就变成:
docker run -p 8501:8501 \
--mount type=bind,source=/tmp/model,target=/models/myserving \
-e MODEL_NAME=myserving -t tensorflow/serving \
--model_config_file=/models/models.config \
--allow_version_labels_for_unavailable_models=true \
--enable_batching=true \
--batching_parameters_file=/models/batch.config
三、在客户端调用以 TensorFlow Serving 部署的模型
TensorFlow Serving 支持以 gRPC 和 RESTful API 调用以 TensorFlow Serving 部署的模型。本手册主要介绍较为通用的 RESTful API 方法。
RESTFUL是一种网络应用程序的设计风格和开发方式,基于HTTP,可以使用XML格式定义或JSON格式定义。RESTFUL适用于移动互联网厂商作为业务接口的场景,实现第三方OTT调用移动网络资源的功能,动作类型为新增、变更、删除所调用资源。
RESTful API 以标准的 HTTP POST 方法进行交互,请求和回复均为 JSON 对象。为了调用服务器端的模型,我们在客户端向服务器发送以下格式的请求:
服务器 URI: http://服务器地址:端口号/v1/models/模型名:predict
请求内容:
{"signature_name": "需要调用的函数签名(Sequential模式不需要)","instances": 输入数据
}
回复为:
{"predictions": 返回值
}
3.1 Python 客户端示例
以下示例使用 Python 的 Requests 库 (你可能需要使用 pip install requests 安装该库)向本机的 TensorFlow Serving 服务器发送 MNIST 测试集的前 10 幅图像并返回预测结果,同时与测试集的真实标签进行比较。
import json
import numpy as np
import requests
from zh.model.utils import MNISTLoaderdata_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]
可见预测结果与真实标签值非常接近。
对于自定义的 Keras 模型,在发送的数据中加入 signature_name 键值即可,即将上面代码的 data 建立过程改为:
data = json.dumps({"signature_name": "call","instances": data_loader.test_data[0:10].tolist()})
参考资料
- TensorFlow Serving:深度学习模型在生产环境的部署&上线
- TensorFlow Serving
【Keras】TensorFlow Serving相关推荐
- 【干货】TensorFlow 2.0官方风格与设计模式指南(附示例代码)
本文转自专知 [导读]TensorFlow 1.0并不友好的静态图开发体验使得众多开发者望而却步,而TensorFlow 2.0解决了这个问题.不仅仅是默认开启动态图模式,还引入了大量提升编程体验的新 ...
- 【keras】一维卷积神经网络多分类
刚刚接触到深度学习,前2个月的时间里,我用一维的卷积神经网络实现了对于一维数据集的分类和回归.由于在做这次课题之前,我对深度学习基本上没有过接触,所以期间走了很多弯路. 在刚刚收到题目的要求时,我选择 ...
- 【keras】3. 泰坦尼克号数据集处理与预测
[参考:1-01 实战 泰坦尼克号沉船人员获救案例 数据清洗_哔哩哔哩_bilibili] [参考:Titanic - Machine Learning from Disaster | Kaggle] ...
- 【Keras】基于SegNet和U-Net的遥感图像语义分割
from:[Keras]基于SegNet和U-Net的遥感图像语义分割 上两个月参加了个比赛,做的是对遥感高清图像做语义分割,美其名曰"天空之眼".这两周数据挖掘课期末projec ...
- 【问题解决】Tensorflow运行出现错误: No module named tensorflow.contrib
我本来想用keras,,这样写的 import tensorflow.contrib.keras as kr 但是报错了 我的tensorflow 版本如下 [问题解决]因为tensorflow1.1 ...
- 【Keras】减少过拟合的秘诀——Dropout正则化
摘要: Dropout正则化是最简单的神经网络正则化方法.阅读完本文,你就学会了在Keras框架中,如何将深度学习神经网络Dropout正则化添加到深度学习神经网络模型里. Dropout正则化是最简 ...
- 【python】tensorflow框架中的tf.gather_nd()函数对应的 pytorch框架的gather_nd()函数
tf.gather_nd 函数对应的pytorch函数 1. 简单介绍 2. 步入正题 2.1 tensorflow tf.gather_nd() 2.2 pytorch框架手动实现gather_nd ...
- 【tfcoreml】tensorflow向CoreML模型的转换工具封装
安装tf向apple coreml模型转换包tfcoreml 基于苹果自己的转换工具coremltools进行封装 tfcoreml 为了将训练的模型转换到apple中使用,需要将模型转换为ios支持 ...
- 【9】tensorflow下图像预处理之图像批量处理
背景:在深度学习时候,通常需要批量处理大量的图片,一般几千张,图像不够时还需要进行数据增强,因此需要批量处理图像数据. [1]批量加载文件夹里面的数据 import os import cv2#批量处 ...
最新文章
- 树莓派电压过低 串口数据错误增多
- 应用程序异常管理组件 Example 程序
- C#笔记 Public,Private,Protected,Internal,Protected internal
- docker 离线安装 mysql_docker 离线安装
- 【组合数学】排列组合 ( 多重集组合数 | 所有元素重复度大于组合数 | 多重集组合数 推导 1 分割线推导 | 多重集组合数 推导 2 不定方程非负整数解个数推导 )
- 【Java基础】一篇文章读懂多线程
- Go语言入门篇-使用Beego构建完整web应用
- 前端学习(672):if-else
- Dojo API中文 Dojo内容模块概览,初学者
- Windows下卸载TensorFlow
- linux 切换root账号_Linux 服务器的安全保障,看看这些
- 32位mips运算器logisim_很多网友问32位低功耗MCU设计
- 2-SAT 问题(洛谷-P4782)
- 数据结构与算法分析(十)——母牛的故事
- EPPlus 读写 Excel 资料收集
- 开发前奏曲之添加Android SDK平台工具
- 计算机硬件开票几个点,财务税控开票电脑装机配置清单和价格介绍
- 知识竞赛中如何按抢答器才能最先抢到
- 海信电视开启开发者模式
- 五子棋项目结束总结_五子棋比赛总结报告
热门文章
- C++ 无符号高精度计算合集
- linux——基本工具:gcc/g++,make(makefile)与gdb
- 国内B2C 26个经典购物网站商城收集(更新至2009年11月3日)转载
- php基地论坛,中国原创歌词基地论坛 - 最大的原创歌词社区
- MySql Povit,[MySQL|Postgresql] Pivot 通用技巧
- 如何在安装 Ubuntu 22.04 时加密全盘
- 头条原创文章一键转换剪映生成视频
- 防计算机病毒主题,主题3+计算机病毒的查杀与防御要点.ppt
- 航天器轨道六要素和TLE两行轨道数据格式
- 结构光相移法中相机投影仪的标定信息如何与相位差联系