Tensorflow Serving 模型部署和服務

http://blog.csdn.net/wangjian1204/article/details/68928656

本文轉載自:https://zhuanlan.zhihu.com/p/23361413 ,原題:TensorFlow Serving 嚐嚐鮮html

 

2016年,機器學習在 Alpha Go 與李世石的世紀之戰後變得更加煊赫一時。Google也在今年推出了 TensorFlow Serving 又加了一把火。python

TensorFlow Serving 是一個用於機器學習模型 serving 的高性能開源庫。它能夠將訓練好的機器學習模型部署到線上,使用 gRPC 做爲接口接受外部調用。更加讓人眼前一亮的是,它支持模型熱更新與自動模型版本管理。這意味着一旦部署 TensorFlow Serving 後,你不再須要爲線上服務操心,只須要關心你的線下模型訓練。git

今天我就帶你們來用 TensorFlow Serving 部署一個簡單的 Linear Regression 模型。github

如下演示運行在 Ubuntu 16.04 LTS 之上。算法

TensorFlow Serving 處於快速迭代期。若是本文內容與官方文檔矛盾,請以官方文檔爲參考。api

環境

TensorFlow Serving 目前依賴 Google 的開源編譯工具 Bazel。Bazel 是 Google 內部編譯工具 Blaze 的開源版本,功能與性能基本一致。具體的安裝能夠參考官方文檔。此外還須要安裝 gRPC (Google 又一個內部工具的開源版)。session

以後請參考官方安裝指南完成。值得注意的是,最後的 bazel build 將會須要大約30分鐘時間並佔用約5-10G的空間(時間取決於機器性能)。配合使用 -c opt 能必定程度加快 build。app

模型訓練

接下來咱們用 TensorFlow 寫一個簡單的測試用 Linear Regression 模型。數據的話我就使用正弦函數生成 1000 個點,嘗試用一條直線去擬合。dom

樣本數據生成以下:機器學習

# Generate input data 
x_data = np.arange(100, step=.1)
y_data = x_data + 20 * np.sin(x_data / 10)
  • 1
  • 2
  • 3

 

Reshape data

x_data = np.reshape(x_data, (n_samples, 1)) y_data = np.reshape(y_data, (n_samples, 1))
  • 1
  • 2

 

而後用一個簡單的 y = wx + b 來作一個訓練,使用 Adam 算法。簡單調整了下參數:

sample = 1000, learning_rate = 0.01, batch_size = 100, n_steps = 500

# Placeholders for batched input 
x = tf.placeholder(tf.float32, shape=(batch_size, 1))
y = tf.placeholder(tf.float32, shape=(batch_size, 1))
  • 1
  • 2
  • 3

Do training

with tf.variable_scope('test'): w = tf.get_variable('weights', (1, 1), initializer=tf.random_normal_initializer()) b = tf.get_variable('bias', (1,), initializer=tf.constant_initializer(0)) y_pred = tf.matmul(x, w) + b loss = tf.reduce_sum((y - y_pred) ** 2 / n_samples) opt = tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(loss) with tf.Session() as sess: sess.run(tf.initialize_all_variables()) for _ in range(n_steps): indices = np.random.choice(n_samples, batch_size) x_batch = x_data[indices] y_batch = y_data[indices] _, loss_val = sess.run([opt, loss], feed_dict={x:x_batch, y:y_batch}) print w.eval() print b.eval() print loss_val
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

 

大體把 loss 收斂在 15.8 左右。精度應該足夠了,畢竟只是一個簡單的測試用模型。

模型導出

接下來的就是本文的重點:導出模型。

tf.train.Saver

用於保存和恢復Variable。它能夠很是方便的保存當前模型的變量或者倒入以前訓練好的變量。一個最簡單的運用:

saver - tf.train.Saver()
  • 1
  • 2
  • 3

Save the variables to disk.

saver.save(sess, 「/tmp/test.ckpt」)

Restore variables from disk.

saver.restore(sess, 「/tmp/test.ckpt」) 

tf.contrib.session_bundle.exporter.Exporter

導出模型還須要這個 Exporter 的協助。使人尷尬的是這個 Exporter 太新了,尚未 API 文檔支持,只能參考 Github 的代碼實現

Exporter 的基本使用方式是

  1. 傳入 saver 構造一個實例

  2. 調用 init 定義模型的 graph 和 input/output

  3. 使用 export 導出爲文件

  • 1
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({'y': y_pred})}) model_exporter.export(FLAGS.work_dir, tf.constant(FLAGS.export_version),sess)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

 

大功告成!編譯!咱們成功導出了一個能夠部署在 TensorFlow Serving 上的模型。它接受一個 x 值而後返回一個 y 值。導出的文件夾以 version 命名,包含用於部署的 meta 文件, 模型 checkpoint 文件和序列化的模型 graph:

/tmp/test/00000001 
checkpoint export-00000-of-00001 export.meta
  • 1
  • 2
  • 3

模型部署

部署的方式很是簡單,只須要如下兩步:

$ bazel build //tensorflow_serving/model_servers:tensorflow_model_server 
$
bazel-bin/tensorflow_serving/model_servers/tensorflow_model_server --port=9000 --model_name=test --model_base_path=/tmp/test/
  • 1
  • 2
  • 3
  • 4

咱們看到 TensorFlow Serving 成功加載了咱們剛剛導出的 model。而且還在不斷嘗試 poll 新的 model:

客戶端

接下來咱們寫一個簡單的 Client 來調用下咱們部署好的 Model。這裏咱們須要用到 TensorFlow Serving 的 Predict API 和 gRPC 的 implementations.insecure_channel 來construct 一個 request。特別要注意的是 input 的 signature 和數據必須和以前 export 的模型匹配。本例中爲 名稱爲 x, float32類型,大小爲 [100, 1] 的 Tensor。

  • 1
from grpc.beta import implementations import numpy as np import tensorflow as tf from tensorflow_serving.apis import predict_pb2 from tensorflow_serving.apis import prediction_service_pb2 tf.app.flags.DEFINE_string('server', 'localhost:9000', 'PredictionService host:port') FLAGS = tf.app.flags.FLAGS n_samples = 100 host, port = FLAGS.server.split(':') channel = implementations.insecure_channel(host, int(port)) stub = prediction_service_pb2.beta_create_PredictionService_stub(channel)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

Generate test data

x_data = np.arange(n_samples, step=1, dtype=np.float32) 
x_data = np.reshape(x_data, (n_samples, 1))

Send request

request = predict_pb2.PredictRequest() 
request.model_spec.name = ‘test’ 
request.inputs[‘x’].CopyFrom(tf.contrib.util.make_tensor_proto(x_data, shape=[100, 1])) 
result = stub.Predict(request, 10.0) # 10 secs timeout 

別忘了配置一下 bazel 的 BUILD 文件:

py_binary( 
name = "test_client",
srcs = [
"test_client.py",
],
deps = [
"//tensorflow_serving/apis:predict_proto_py_pb2",
"//tensorflow_serving/apis:prediction_service_proto_py_pb2",
"@org_tensorflow//tensorflow:tensorflow_py",
],
)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

最後編譯運行,就能看到在線預測結果啦!

bazel build //tensorflow_serving/test:test_client && ./bazel-bin/tensorflow_serving/test/test_client 
  • 1
  • 2

延伸

TensorFlow 封裝了衆多經常使用模型成爲 Estimator,幫助用戶避免了冗長易錯的算法實現部分。好比以上的例子就能夠徹底用 LinearRegressor 來替換。只須要幾行代碼簡單地調用 fit() 函數就能輕鬆獲得收斂的模型。惟一不足的是目前與 TensorFlow Serving 還不能 100% 兼容。雖然 Google 還在全力完善 TensorFlow Serving,可是距離完善還須要必定的時間。

若是既想要使用方便快捷的的 Estimator ,又想線上部署呢?固然也是有辦法的,筆者鑽研了一下後,實現了一個用 Estimator 訓練數據,導出模型後再部署上線的方法。最後用這個線上部署的模型實現一個在線評估房屋價值的系統。

相關文章
相關標籤/搜索