使用docker部署模型的好处在于,避免了与繁琐的环境配置打交道。使用docker,不需要手动安装Python,更不需要安装numpy、tensorflow各种包,直接一个docker就包含了全部。docker的方式是如今部署项目的第一选择。

一、docker用法初探

1、安装

docker安装需要两个命令:

sudo apt-get install docker

sudo apt-get install docker.io

好的学习资料不必远求

docker --help

docker run --help

2、基础命令

docker ps 查看当前正在运行的实例

docker images查看现有的镜像

docker kill 实例名称或者实例ID 杀死正在运行的实例

docker pull 镜像名称 从远程docker仓库拉下来别人已经配置好的镜像

3、避免每次都sudo

docker命令默认只能root权限使用,这样实在有些繁琐。docker安装完成之后,docker组已经存在了,但是当前用户不在docker组里面,所以只需要把当前用户添加到docker组即可。

groups 查看当前用户所在的那些组

groupadd docker 添加组,这一步其实没有必要,因为docker组已经存在了

sudo usermod -aG docker $USER 把当前用户添加到docker组,还有另外一种方法:sudo gpasswd -a ${USER} docker

newgrp - docker 刷新docker组

sudo service docker restart 重启服务

4、docker映射

docker就是一个镜像,我们需要做的就是把docker和外部世界建立联系。最紧密的联系有如下三种:

  • 网络映射:IP和端口号
  • 磁盘映射

    使用docker -v 宿主机目录:docker目录,-v表示virtual,虚拟的路径

    一律采用绝对路径,不要投机取巧使用相对路径,这样可以给自己减少许多麻烦,大智若愚正是此意。
  • 环境变量

    使用docker -e one=two,three=four 这样的命令,e表示environment

二、快速运行tensorflow-serving

sudo docker pull tensorflow/serving 把serving的镜像拉下来

git clone https://github.com/tensorflow/serving 复制一份现有的模型,当然也可以使用自己的模型,这个仓库是tensorflow serving的整个源码库,里面给出了一些demo,我们只需要demo那一部分

使用docker命令启动服务

TESTDATA="$(pwd)/serving/tensorflow_serving/servables/tensorflow/testdata"
docker run -t --rm -p 8501:8501 \
-v "$TESTDATA/saved_model_half_plus_two_cpu:/models/half_plus_two" \
-e MODEL_NAME=half_plus_two \
tensorflow/serving &

docker -e设置环境变量

docker -p设置端口映射

docker -v设置磁盘映射

docker run -t 表示是否允许伪TTY

docker run --rm表示如果实例已经存在,则先remove掉该实例再重新启动新实例

建立映射时,都是形如“宿主机:docker容器”这种格式。

最后万事俱备,只欠东风了。

# Query the model using the predict API
curl -d '{"instances": [1.0, 2.0, 5.0]}' \
-X POST http://localhost:8501/v1/models/half_plus_two:predict # Returns => { "predictions": [2.5, 3.0, 4.5] }

容器启动之后,使用docker ps查看有哪些实例,使用docker kill 实例ID 杀死实例,使用docker inspect 实例ID查看实例详情。

建立磁盘映射除了使用-v参数,也可以使用mount参数。

docker run -p 8501:8501 --mount type=bind,\  source=/tmp/tfserving/serving/tensorflow_serving/servables/tensorflow/testdata/saved_model_half_plus_two_cpu,\
target=/models/half_plus_two \
-e MODEL_NAME=half_plus_two -t tensorflow/serving &

三、tensorflow-serving的默认配置

我们需要了解tensorflow/serving这个镜像的默认配置,镜像的默认配置就像电路板的引脚一样,是固定的。

serving镜像提供了两种调用方式:gRPC和HTTP请求。gRPC默认端口是8500,HTTP请求的默认端口是8501,serving镜像中的程序会自动加载镜像内/models下的模型,通过MODEL_NAME指定/models下的哪个模型。

四、从头编写一个完整的例子

Tensorflow官网上、github上的例子都比较旧,需要做些小修改才可使用。例如旧版的导出使用了contrib中的session_bundle,而这个包已经不鼓励使用了。

旧版的serving模型导出

from tensorflow import gfile
from tensorflow.contrib.session_bundle import exporter export_path = "/tmp/half_plus_two"
if not gfile.Exists(export_path):
gfile.MkDir(export_path)
with tf.Session() as sess:
# Make model parameters a&b variables instead of constants to
# exercise the variable reloading mechanisms.
a = tf.Variable(0.5)
b = tf.Variable(2.0) # Calculate, y = a*x + b
# here we use a placeholder 'x' which is fed at inference time.
x = tf.placeholder(tf.float32)
y = tf.add(tf.multiply(a, x), b) # Run an export.
tf.global_variables_initializer().run()
export = exporter.Exporter(tf.train.Saver())
export.init(named_graph_signatures={
"inputs": exporter.generic_signature({"x": x}),
"outputs": exporter.generic_signature({"y": y}),
"regress": exporter.regression_signature(x, y)
})
export.export(export_path, tf.constant(123), sess)

新版的模型导出:主要使用saved_model包下的工具

import os

import tensorflow as tf

def signature(function_dict):
signature_dict = {}
for k, v in function_dict.items():
inputs = {k: tf.saved_model.utils.build_tensor_info(v) for k, v in v['inputs'].items()}
outputs = {k: tf.saved_model.utils.build_tensor_info(v) for k, v in v['outputs'].items()}
signature_dict[k] = tf.saved_model.build_signature_def(inputs=inputs, outputs=outputs, method_name=v['method_name'])
return signature_dict output_dir = "/tmp/counter"
for i in range(100000, 9999999):
cur = os.path.join(output_dir, str(i))
if not tf.gfile.Exists(cur):
output_dir = cur
break
method_name = tf.saved_model.signature_constants.PREDICT_METHOD_NAME
print('outputdir', output_dir)
with tf.Graph().as_default(), tf.Session() as sess:
counter = tf.Variable(0.0, dtype=tf.float32, name="counter")
with tf.name_scope("incr_counter_op", values=[counter]):
incr_counter = counter.assign_add(1.0)
delta = tf.placeholder(dtype=tf.float32, name="delta")
with tf.name_scope("incr_counter_by_op", values=[counter, delta]):
incr_counter_by = counter.assign_add(delta)
with tf.name_scope("reset_counter_op", values=[counter]):
reset_counter = counter.assign(0.0)
nothing = tf.placeholder(dtype=tf.int32, shape=(None,))
sess.run(tf.global_variables_initializer())
signature_def_map = signature({
"get_counter": {"inputs": {"nothing": nothing},
"outputs": {"output": counter},
"method_name": method_name},
"incr_counter": {"inputs": {"nothing": nothing},
"outputs": {"output": incr_counter},
"method_name": method_name},
"incr_counter_by": {"inputs": {'delta': delta, },
"outputs": {'output': incr_counter_by},
"method_name": method_name},
"reset_counter": {"inputs": {"nothing": nothing},
"outputs": {"output": reset_counter},
"method_name": method_name}
})
builder = tf.saved_model.builder.SavedModelBuilder(output_dir)
builder.add_meta_graph_and_variables(sess, tags=[tf.saved_model.tag_constants.SERVING], signature_def_map=signature_def_map)
builder.save()
print("over")

以上代码有一个注意事项:

使用nothing作为inputs中的占位元素,这样做是因为模型的每个函数的inputs都不能为空,否则触发错误:

"error": "Failed to get input map for signature: get_counter" 。这似乎是tensorflow似乎有bug,调用get_counter方法是不管用的,传入的inputs为空,就无法调用成功。

运行此servable

$docker run -p 8555:8501 -v /home/ubuntu/counter:/models/counter -e MODEL_NAME=counter tensorflow/serving &

获取模型状态
$curl http://localhost:8555/v1/models/saved_model_counter {
"model_version_status": [
{
"version": "1343",
"state": "AVAILABLE",
"status": {
"error_code": "OK",
"error_message": ""
}
}
]
} 使用metadata获取可用模型元数据
~$curl http://localhost:8555/v1/models/saved_model_counter/metadata
{
"model_spec":{
...... 调用增长函数
~$curl http://localhost:8555/v1/models/counter:predict -X POST -d '{"signature_name":"incr_couter","inputs":[0]}'
{
"outputs": 1.0
} 调用increase_by
第一种方式inputs传入列表
curl http://localhost:8555/v1/models/counter:predict -X POST -d '{"signature_name":"incr_couter_by","inputs":[3]}'
第二种方式inputs传入字典
~$curl http://localhost:8555/v1/models/counter:predict -X POST -d '{"signature_name":"incr_counter_by","inputs":{"delta":3.0}}'

tf.saved_model.signature_constants这个包非常简单,它定义了以下三类变量签名

  • 分类classify
  • 回归regress
  • 预测predict

这三类分别具有:

  • 函数签名
CLASSIFY_METHOD_NAME = "tensorflow/serving/classify"
PREDICT_METHOD_NAME = "tensorflow/serving/predict"
REGRESS_METHOD_NAME = "tensorflow/serving/regress"
  • Inputs
  • Outputs

    其中CLASSIFY的output有两种:score、class。score返回各个类别的期望值,class返回各个类别的离散值。

总体来说,定义这些常量名其实并无卵用,我们只用predict就足够了。

五、对tensorflow/serving的整体认识

serving是一个非常通用的库,它不仅能够用来对tensorflow模型服务,也可以对其它机器学习模型服务。

serving只负责tensorflow模型部分,所以我们需要把用到的函数全部定义出来,这本身就相当于一种RPC。

serving能够起到解耦的作用,对于大项目来说是一件好事,但是对于小项目来说略嫌啰嗦。

参考资料

https://www.tensorflow.org/serving/api_rest

使用tensorflow-serving部署tensorflow模型的更多相关文章

  1. 使用TensorFlow Serving优化TensorFlow模型

    使用TensorFlow Serving优化TensorFlow模型 https://www.tensorflowers.cn/t/7464 https://mp.weixin.qq.com/s/qO ...

  2. TensorFlow Serving实现多模型部署以及不同版本模型的调用

    前提:要实现多模型部署,首先要了解并且熟练实现单模型部署,可以借助官网文档,使用Docker实现部署. 1. 首先准备两个你需要部署的模型,统一的放在multiModel/文件夹下(文件夹名字可以任意 ...

  3. 如何用 tensorflow serving 部署服务

    第一步,读一读这篇博客 https://www.jb51.net/article/138932.htm (浅谈Tensorflow模型的保存与恢复加载) 第二步: 参考博客: https://blog ...

  4. 基于TensorFlow Serving的深度学习在线预估

    一.前言 随着深度学习在图像.语言.广告点击率预估等各个领域不断发展,很多团队开始探索深度学习技术在业务层面的实践与应用.而在广告CTR预估方面,新模型也是层出不穷: Wide and Deep[1] ...

  5. Tensorflow Serving 模型部署和服务

    http://blog.csdn.net/wangjian1204/article/details/68928656 本文转载自:https://zhuanlan.zhihu.com/p/233614 ...

  6. 139、TensorFlow Serving 实现模型的部署(二) TextCnn文本分类模型

    昨晚终于实现了Tensorflow模型的部署 使用TensorFlow Serving 1.使用Docker 获取Tensorflow Serving的镜像,Docker在国内的需要将镜像的Repos ...

  7. docker部署tensorflow serving以及模型替换

    Using TensorFlow Serving with Docker 1.Ubuntu16.04下安装docker ce 1-1:卸载旧版本的docker sudo apt-get remove ...

  8. Tensorflow Serving Docker compose 部署服务细节(Ubuntu)

    [摘要] Tensorflow Serving 是tf模型持久化的重要工具,本篇介绍如何通过Docker compose搭建并调试TensorFlow Serving TensorFlow Servi ...

  9. 学习笔记TF067:TensorFlow Serving、Flod、计算加速,机器学习评测体系,公开数据集

    TensorFlow Serving https://tensorflow.github.io/serving/ . 生产环境灵活.高性能机器学习模型服务系统.适合基于实际数据大规模运行,产生多个模型 ...

  10. TensorFlow Serving简介

    一.TensorFlow Serving简介 TensorFlow Serving是GOOGLE开源的一个服务系统,适用于部署机器学习模型,灵活.性能高.可用于生产环境. TensorFlow Ser ...

随机推荐

  1. RV LayoutManager 流式布局 MD

    Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...

  2. Could not load file or assembly 'System.Data.SQLite' or one of its dependencies. An attempt was made to load a program

    今天同事在一个服务器(winserver 2008 x64)上新建了一个IIS(7) 网站,但是报了如下错误: Could not load file or assembly 'System.Data ...

  3. Openstack中为虚拟机使用CDROM光驱设备

    在Libvirt里处理 在nova里处理 实际效果 怎么卸载 在Libvirt里处理 尝试了下面有几种方法,为虚拟机载入光盘文件: 1.使用ide方式挂载: virsh attach-disk {in ...

  4. Android Migrate Android Code

    近期在更改程序架构的时候,用引用Library的方式实现程序的共享化过程中发现R.id.xx的文件不能够在  switch cases  中使用 看代码提示,如下信息: As of ADT 14, r ...

  5. 微信小程序阿里云服务器https搭建

    已更新 2018-11-20 1.什么是https?HTTPS(全称:安全套接字层上的超文本传输​​协议),是以安全为目标的HTTP通道,简单讲是HTTP的安全版.即HTTP下加入SSL层,HTTPS ...

  6. 安装loadrunner

    Loadrunner安装具体解释 一 .下载篇. 我的下载地址是:http://pan.baidu.com/s/1c0IqAOC 程序4G多.非常大. 二.           安装篇 1.执行&qu ...

  7. Sublime Es6教程1-环境搭建

    因为现在网上的教程都不靠谱,于是决定自己跳坑自己写,分为三块来玩: 一.环境搭建 二.语法讲解 三.项目实战 很多时候,你想搞一个东西,却因为环境没有搭建好,而不能很开森的探索未知的世界,多年的编程经 ...

  8. VC++导出具有命名空间的函数

    问题现象 原因分析 解决的方法 1 问题现象 导出具有命名空间的函数和类.源码例如以下: 头文件MiniMFC.h namespace MiniMFC { __declspec(dllexport) ...

  9. 【转】 Java多态特性:重载和覆写的比较

    Java重载: 在同一个类中 方法具有相同的名字,相同或不同的返回值,但参数不同的多个方法(参数个数或参数类型) public class MethoDemo{ public static void ...

  10. 【转】一些linux基础命令

    学习Linux,其实很多基础命令很重要. 不论多么复杂的shell或者命令组合,都是一个一个的拼接组合命令拼接而成: 大号一个基本功,遇到需要的场景,信手拈来,随意组合拼接,是非常重要的. 恰好看到一 ...