专栏首页AI研习社十分钟搞定 Tensorflow 服务

十分钟搞定 Tensorflow 服务

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

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

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

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

avloss/tensorflow-serving-rest.

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

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

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

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

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

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值,该值就是我们得到的预测值。

pred = tf.argmax(y,axis=1)

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

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]})
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

%matplotlib inlineimport matplotlib.pyplot as plt

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

plt.imshow(number.reshape(28,28))
<matplotlib.image.AxesImage at 0x7fa28919ae90>

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

这个示例 99% 管用!

sess.run(pred,feed_dict={x: number})[0]
6

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

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

EXPORT_PATH = "/tmp/models"
VERSION=1

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

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)
INFO:tensorflow:/tmp/models/00000001-tmp/export is not in all_model_checkpoint_paths. Manually adding it.'/tmp/models/00000001'

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

!ls -lhR /tmp/models
/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 模型服务器。截至目前,服务器一直处于空闲状态,正在等待文件夹里出现一个模型。我们现在可以检查一下日志来确定服务器辨识并加载了刚刚存档的模型:

!tail -n2 /tmp/models/model.log
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 调用我们模型的函数的示例。

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()

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

%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))
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 服务做预测。

test_flask_client(number)
{u'outputs': {u'pred': {u'dtype': u'DT_INT64',
   u'int64Val': [u'7'],
   u'tensorShape': {u'dim': [{u'size': u'1'}]}}}}

从这里提取得到的预测值

int(test_flask_client(number)["outputs"]["pred"]["int64Val"][0])
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

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

本文分享自微信公众号 - AI研习社(okweiwu),作者:雷锋字幕组

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2017-07-24

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 基于 Tensorflow eager 的文本生成,注意力,图像注释的完整代码

    我总是发现生成和序列模型令人着迷:他们提出的问题与我们刚开始学习机器学习时常遇到的问题不同。当我第一次开始学习ML时,我学了分类和回归(和大多数人一样)。这些帮...

    AI研习社
  • 专栏 | 目标检测算法之YOLOv3及YOLOV3-Tiny

    昨天稍微填上了YOLOv2损失函数的坑,然后我在知乎关注了一个有趣的问题,地址是:https://www.zhihu.com/question/35700517...

    AI研习社
  • Github 项目推荐 | TensorFlow 项目模板架构最佳实践

    一个简单且设计良好的架构对于任何深度学习项目来讲非常有必要,这里的 Tensorflow 项目模板经过了大量的实践,拥有简单性、良好的文件结构以及 OOP 设计...

    AI研习社
  • 20项任务全面碾压BERT,全新XLNet预训练模型

    这是继BERT发布以来又一个令广大NLPer兴奋的消息, CMU 与谷歌大脑提出的 XLNet 在 20 个任务上超过了 BERT 的表现,并在 18 个任务上...

    昱良
  • [Oracle ASM全解析] 管理ASM 目录

    bsbforever
  • 最新版chevereto3.10.5使用体验

    使用chevereto图床几天之后,发现这个图床系统还是挺好用的,虽然安装简单,功能很强大。 既然是一个功能的网站,就说说他使用的体验 ? chevereto网...

    用户1188347
  • 优雅的备份博客内的外链图片

    这是我早就想做的一件事情了,但没想到不得不做这件事的这一天这么快就来临了。其实从一开始,我就对免费图床并不放心,在国内一直使用的是付费的作业部落的图片存储(阿里...

    ZONGLYN
  • 如何揭开Linux中的命名空间和容器的神秘面纱【Containers】

    容器已经席卷全球了。听到这个术语时,无论您想到Kubernetes,Docker,CoreOS,Silverblue还是Flatpak,很明显,现代应用程序都在...

    王欣壳
  • 如何揭开Linux中的命名空间和容器的神秘面纱

    集装箱已经席卷全球了。听到这个术语时,无论您想到Kubernetes,Docker,CoreOS,Silverblue还是Flatpak,很明显,现代应用程序都...

    王欣壳
  • TidyFriday 每天 5 分钟,轻轻松松上手 R 语言(六)数据读取与保存

    我们最先要了解的是我们的工作目录,当文件在当前目录下时我们输入文件名即可, 没有在当前目录我们就要输入数据文件的绝对路径。

    王诗翔呀

扫码关注云+社区

领取腾讯云代金券