前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >十分钟搞定 Tensorflow 服务

十分钟搞定 Tensorflow 服务

作者头像
AI研习社
发布2018-03-19 15:52:08
1.4K0
发布2018-03-19 15:52:08
举报
文章被收录于专栏:AI研习社

Tensorflow 服务是谷歌推荐用来部署 Tensorflow 模型的方法。如果你不具备一定的计算机工程知识背景,即使你对 Tensorflow 本身感觉很顺手,但是我觉得想要搞定 Tensorflow 服务也不是辣么容易的。以下三点是我总结的难点:

  • (谷歌官方)教程含有 C++ 代码(我不会 C++)
  • 教程里含有 kubernetes,gRPG,Bezel(其中一些我也是第一次见)
  • 需要被编译出来。那个过程时间太长了,恐怕要用一个世纪吧!

这里介绍一种可能是最简单的方式——用 tensorflow 服务部署你的算法模型。看完本教程,你也可以让自己的模型在 TF 服务里面运行。这个服务框架是弹性的,可以通过 REST 来请求。

本教程用的是 Docker 镜像。可以利用 Kitematic 来启动:

代码语言:javascript
复制
avloss/tensorflow-serving-rest.

起初,我试着在 DockerHub 上面搞 - 但是试了两个小时都没成功,所以我不得不弃坑去用 https://quay.io

我将一步步做好的镜像上传到 DockerHub,假如你想验证本文,你可以去拉取 https://quay.io/repository/avloss/tensorflow-serving-rest 上的镜像。

你可以用 Kitematic 启动 Docker 容器,或者在 console 里面用这行命令:

代码语言:javascript
复制
docker run --rm -it -p 8888:8888 -p 9000:9000 -p 5000:5000 quay.io/avloss/tensorflow-serving-rest

运行之后,执行这个脚本 http://localhost:8888/notebooks/tf_serving_rest_example.ipynb。(如果你用的是 Kitematic 的话,端口号要改改)

下面的内容最好用容器自带的 Jupyter notebook!

为了进一步演示运行细节,我们下面用典型的 TF 官方教程 MNIST 示例:https://www.tensorflow.org/get_started/mnist/pros

我们用一个标准模型来举个例子。

代码语言:javascript
复制
import tensorflow as tf

x = tf.placeholder(tf.float32, shape=[None, 784])
y_ = tf.placeholder(tf.float32, shape=[None, 10])

W = tf.Variable(tf.zeros([784,10]))
b = tf.Variable(tf.zeros([10]))


y = tf.matmul(x,W) + b

cross_entropy = tf.reduce_mean(
    tf.nn.softmax_cross_entropy_with_logits(labels=y_, logits=y))

train_step = tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy)

另外,我们说明一下pred值,该值就是我们得到的预测值。

代码语言:javascript
复制
pred = tf.argmax(y,axis=1)

我们下载示例训练部分的代码并训练这个模型。

代码语言:javascript
复制
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets('MNIST_data', one_hot=True)

sess = tf.InteractiveSession()
sess.run(tf.global_variables_initializer())for _ in range(1000):
    batch = mnist.train.next_batch(100)
    train_step.run(feed_dict={x: batch[0], y_: batch[1]})
代码语言:javascript
复制
Extracting MNIST_data/train-images-idx3-ubyte.gz
Extracting MNIST_data/train-labels-idx1-ubyte.gz
Extracting MNIST_data/t10k-images-idx3-ubyte.gz
Extracting MNIST_data/t10k-labels-idx1-ubyte.gz

接下来确保一切都如预期的那样。我们用数据集中某个数字的图片number

代码语言:javascript
复制
%matplotlib inlineimport matplotlib.pyplot as plt

number = mnist.train.next_batch(1)[0]

plt.imshow(number.reshape(28,28))
代码语言:javascript
复制
<matplotlib.image.AxesImage at 0x7fa28919ae90>

确认一下我们的模型可以很快得到预测结果:

这个示例 99% 管用!

代码语言:javascript
复制
sess.run(pred,feed_dict={x: number})[0]
代码语言:javascript
复制
6

现在我们要保存这个模型,并把它放在 tensorflow 服务里面供外部调用。我们为要保存的权重和模型版本的定义一下保存路径。

注意,如果你想保存另外一个模型的话,需要调高 “VERSION” 基准值,并且重构你的计算图(重启这 Jupyter notbook 脚本)。

代码语言:javascript
复制
EXPORT_PATH = "/tmp/models"
VERSION=1

这里我们保存得到的权重值。

代码语言:javascript
复制
from tensorflow.contrib.session_bundle import exporter

saver = tf.train.Saver(sharded=True)
model_exporter = exporter.Exporter(saver)
model_exporter.init(
    sess.graph.as_graph_def(),
    named_graph_signatures={
        'inputs': exporter.generic_signature({'x': x}),
        'outputs': exporter.generic_signature({'pred': pred})})
model_exporter.export(EXPORT_PATH, tf.constant(VERSION), sess)
代码语言:javascript
复制
INFO:tensorflow:/tmp/models/00000001-tmp/export is not in all_model_checkpoint_paths. Manually adding it.'/tmp/models/00000001'

下面让我们确认一下权重是否保存正确。

代码语言:javascript
复制
!ls -lhR /tmp/models
代码语言:javascript
复制
/tmp/models:
total 12K
drwxr-xr-x 2 root root 4.0K Mar 10 10:29 00000001
-rw-r--r-- 1 root root 7.6K Mar 10 10:29 model.log

/tmp/models/00000001:
total 72K
-rw-r--r-- 1 root root 119 Mar 10 10:29 checkpoint
-rw-r--r-- 1 root root 31K Mar 10 10:29 export.data-00000-of-00001
-rw-r--r-- 1 root root 159 Mar 10 10:29 export.index
-rw-r--r-- 1 root root 29K Mar 10 10:29 export.meta

Services

当这个 Docker 镜像启动时,会运行 "example_jupyter/setup.sh"。其实下面的服务已经启动:

  • jupyter notebook

这就是我们现在要运行的 jupyter notebook。

  • /serving/bazel-bin/tensorflow_serving/model_servers/tensorflow_model_server

这是 TF 模型服务正在运行。它来自 TF 服务的标准分布式,使用 gRPC 协议调用模型。

  • /serving/bazel-bin/tensorflow_serving/example/flask_client

我还把这个 Flask web 应用从 REST 请求转成 gPRC 请求。这样做可能会降低运行性能,但是至少能把每一步过程搞清楚 - 你可以在下面的网页中找到代码:tensorflow_serving/example/flask_client.py.

让我们验证一下 TF 模型服务器。截至目前,服务器一直处于空闲状态,正在等待文件夹里出现一个模型。我们现在可以检查一下日志来确定服务器辨识并加载了刚刚存档的模型:

代码语言:javascript
复制
!tail -n2 /tmp/models/model.log
代码语言:javascript
复制
2017-03-10 10:29:49.461339: I tensorflow_serving/core/loader_harness.cc:86] Successfully loaded servable version {name: default version: 1}
2017-03-10 10:29:49.464518: I tensorflow_serving/model_servers/main.cc:257] Running ModelServer at 0.0.0.0:9000 ...

REST 请求

接下来的部分可以单独运行之前做的 - 因此你可以在不同的 notebook 运行,或者说甚至在别的主机上运行

下面是用 REST 调用我们模型的函数的示例。

代码语言:javascript
复制
import numpy as np
import cPickle as pickle
import requests

def test_flask_client(x):
    URL = "http://localhost:5000/model_prediction"

    s = pickle.dumps({"x":x}, protocol=0)

    DATA = {"model_name": "default",
          "input": requests.utils.quote(s)}

    r = requests.get(URL, data=DATA)    
    return r.json()

确保对训练数据依然有效。

代码语言:javascript
复制
%matplotlib inline
import matplotlib.pyplot as plt
from tensorflow.examples.tutorials.mnist import input_data

mnist = input_data.read_data_sets('MNIST_data', one_hot=True)
number = mnist.train.next_batch(1)[0]

plt.imshow(number.reshape(28,28))
代码语言:javascript
复制
Extracting MNIST_data/train-images-idx3-ubyte.gz
Extracting MNIST_data/train-labels-idx1-ubyte.gz
Extracting MNIST_data/t10k-images-idx3-ubyte.gz
Extracting MNIST_data/t10k-labels-idx1-ubyte.gz

<matplotlib.image.AxesImage at 0x7fa28d001050>

预测过程

最后,用 Tensorflow 服务做预测。

代码语言:javascript
复制
test_flask_client(number)
代码语言:javascript
复制
{u'outputs': {u'pred': {u'dtype': u'DT_INT64',
   u'int64Val': [u'7'],
   u'tensorShape': {u'dim': [{u'size': u'1'}]}}}}

从这里提取得到的预测值

代码语言:javascript
复制
int(test_flask_client(number)["outputs"]["pred"]["int64Val"][0])
代码语言:javascript
复制
7

完成!

就这样,你学会用 Tensorflow 服务的 Docker 容器调用 tensorflow 模型。这个模型需要 REST 或者 gRPC(端口 9000)

也容易导出 Docker 镜像,可以在任何地方执行。在你的主机终端上执行下面的命令。 docker ps

会显示你正在运行的容器的 ID,在下面的命令中用这容器 ID 替代 “xxxxx"。

docker commit XXXXXX my_name/my_model:version1

docker save my_name/my_model:version1 > my_name.my_model.version1.tar

你的(内置模型的)Docker 镜像保存在 "tar” 包里,便于移动。我认为是这不是最佳实践,但是有用。如果把这文件解压到服务器,用下面的命令执行。

docker load --input my_name.my_model.version1.tar

docker run --rm -it -p 8888:8888 -p 9000:9000 -p 5000:5000 my_name/my_model:version1

这你就在新的服务器里运行你的模型。希望这篇博文能帮助到大家。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2017-07-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 AI研习社 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Services
  • REST 请求
  • 预测过程
  • 完成!
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档