Contents
java通过gRPC整合tensorflow serving(之二)——安装tfserving并部署示例模型
承接上一篇【java通过gRPC整合tensorflow serving——gRPC java入门例子】
这是本系列的第二篇,上一篇我们了解了如何用java构建grpc的简单服务端和客户端。
这一篇我们来介绍一下,如何安装tensorflow serving,如何根据已经train好的checkpoint文件导出tensorflow serving的模型并部署。
好了开始,我们的环境是Ubuntu 16.04,其他linux发行版安装过程大同小异,由于我们的目的是学习tensorflow serving和java的整合,而并不是解决繁琐的linux包依赖问题,所以我们使用tensorflow serving官方的docker镜像简化安装。now,go!
第一步 安装docker
1 sudo apt-get install docker.io
如果报错的话,自己google一下很容易解决,找不到源 就先添加repo 再apt-get update一下
第二步 build并启动镜像
1
2 wget https://raw.githubusercontent.com/tensorflow/serving/master/tensorflow_serving/tools/docker/Dockerfile.devel
sudo docker build --pull -t $USER/tensorflow-serving-devel -f Dockerfile.devel .
默默等待它完成后,执行
1 | sudo docker images |
可以看到已经列出了我们刚刚build的镜像
1
2
3
4
5 sudo docker run -it ubuntu/tensorflow-serving-devel /bin/bash # 启动并进入容器的shell
cd serving/tensorflow
./configure #配置的时候根据自己情况选择 因为我是做个示例 而且也没有gpu 所以所有选项 我都一路输入n
cd ..
bazel test tensorflow_serving/...
运行完后 如果没有报错,正常情况tensorflow serving已经安装完毕,生成的二进制文件在bazel-bin/tensorflow_serving/model_servers下,可以把这个目录加到path环境变量中,然后执行
1 | tensorflow_model_server |
如果打印出了帮助信息就证明安装ok了
Tips
安装完成后最好是把现有的docker容器commit到一个新的镜像 这样以后就不用再重复这个安装过程了 具体的命令可以参考docker commit
第三步导出模型并部署到tfserving
我们这里直接使用 https://github.com/opensourcesblog/tensorflow-mnist/tree/master/cps 这里的已经train好导出的checkpoint文件,它是一个解决mnist手写识别的问题,可以算得上是深度学习的helloworld了 也非常贴合我们的demo的意义。 下载这几个文件,然后编写导出脚本。
新建export.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41 #!/usr/bin/env python
# -*- coding:utf-8 -*-
import tensorflow as tf
W = tf.Variable(tf.zeros([784, 10]))
b = tf.Variable(tf.zeros([10]))
x = tf.placeholder("float", [None, 784], name="x")
y = tf.nn.softmax(tf.matmul(x, W) + b, name="y")
saver = tf.train.Saver()
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
ckpt = tf.train.get_checkpoint_state("./cps/")
if ckpt and ckpt.model_checkpoint_path:
print(ckpt.model_checkpoint_path)
saver.restore(sess, ckpt.model_checkpoint_path)
# summary = tf.summary.merge_all()
# summary_writer = tf.summary.FileWriter('/Users/andy/Downloads/mnist_logs_2', sess.graph)
builder = tf.saved_model.builder.SavedModelBuilder("/Users/andy/Downloads/mnist_tfserving_model")
prediction_signature = tf.saved_model.signature_def_utils.build_signature_def(
inputs={
'x': tf.saved_model.utils.build_tensor_info(x),
},
outputs={
'y': tf.saved_model.utils.build_tensor_info(y),
},
method_name=tf.saved_model.signature_constants.PREDICT_METHOD_NAME)
legacy_init_op = tf.group(
tf.tables_initializer(), name='legacy_init_op')
builder.add_meta_graph_and_variables(
sess, [tf.saved_model.tag_constants.SERVING],
signature_def_map={
'mnist':
prediction_signature,
},
clear_devices=False,
legacy_init_op=legacy_init_op)
builder.save()
print("model export done.")
上面的路径根据自己实际情况替换,导出的模型,在外层加一层目录命名为 1 (也就是tfserving对模型的版本标识)
最后的目录结构是这样的
然后就是把这个模型打个tar包 上传到刚才安装的tfserving服务器上,由于是个docker容器,所以我们需要先commit镜像(上面提过),然后关闭容器,再重新运行容器 运行的时候需要加上 -P 2222:22 -P 9000:9000 这个参数,将容器的22端口和9000端口映射到宿主机,这样我们就可以通过scp -P 2222 来将模型包上传到容器里了,9000端口是tfserving默认监听的端口,所以也要映射它。
上传就不介绍了(映射了端口就好办),然后我们就需要配置tensorflow serving的启动配置文件,其实如果是一个模型可以直接用命令行参数的方式指定,但是如果想让tensorflow serving支持多个模型服务,就要用到配置文件,我们新建一个models.json的文件,输入下面内容
1
2
3
4
5
6
7 model_config_list: {
config: {
name: "mnist",
base_path: "/root/models/mnist_tfserving_model/",
model_platform: "tensorflow"
},
}
路径名还是要根据自己实际情况替换,之后我们就可以运行tfserving了,执行
1 | nohup tensorflow_model_server --model_config_file=/root/models.json --port=9000 & |
其中路径也要替换为你自己的models.json,执行完tail -n 10 nohup.out看一下程序输出,如果看到类似
1 | Running ModelServer at 0.0.0.0:9000 |
的话 就代表ok了。
好了 这篇就到这里 我们目前已经了解了如果用java编写grpc客户端和简单服务端,也了解了如果部署tfserving部署模型, 下一篇就会开始通过java调用tfserving的模型了。
敲碗等下文 ~
谢谢支持,下一篇会在本周末更新~