使用tensorflow-serving部署模型

TensorFlow訓(xùn)練好的模型以tensorflow原生方式保存成protobuf文件后可以用許多方式部署運(yùn)行膛檀。

例如:通過(guò) tensorflow-js 可以用javascrip腳本加載模型并在瀏覽器中運(yùn)行模型脐恩。

通過(guò) tensorflow-lite 可以在移動(dòng)和嵌入式設(shè)備上加載并運(yùn)行TensorFlow模型舍肠。

通過(guò) tensorflow-serving 可以加載模型后提供網(wǎng)絡(luò)接口API服務(wù),通過(guò)任意編程語(yǔ)言發(fā)送網(wǎng)絡(luò)請(qǐng)求都可以獲取模型預(yù)測(cè)結(jié)果呵燕。

通過(guò) tensorFlow for Java接口棠绘,可以在Java或者spark(scala)中調(diào)用tensorflow模型進(jìn)行預(yù)測(cè)。

我們主要介紹tensorflow serving部署模型再扭、使用spark(scala)調(diào)用tensorflow模型的方法氧苍。


〇,tensorflow serving模型部署概述


使用 tensorflow serving 部署模型要完成以下步驟泛范。

  • (1) 準(zhǔn)備protobuf模型文件让虐。

  • (2) 安裝tensorflow serving。

  • (3) 啟動(dòng)tensorflow serving 服務(wù)罢荡。

  • (4) 向API服務(wù)發(fā)送請(qǐng)求赡突,獲取預(yù)測(cè)結(jié)果。

可通過(guò)以下colab鏈接測(cè)試效果《tf_serving》:
https://colab.research.google.com/drive/1vS5LAYJTEn-H0GDb1irzIuyRB8E3eWc8

%tensorflow_version 2.x
import tensorflow as tf
print(tf.__version__)
from tensorflow.keras import * 

一柠傍,準(zhǔn)備protobuf模型文件

我們使用tf.keras 訓(xùn)練一個(gè)簡(jiǎn)單的線性回歸模型麸俘,并保存成protobuf文件辩稽。

import tensorflow as tf
from tensorflow.keras import models,layers,optimizers

## 樣本數(shù)量
n = 800

## 生成測(cè)試用數(shù)據(jù)集
X = tf.random.uniform([n,2],minval=-10,maxval=10) 
w0 = tf.constant([[2.0],[-1.0]])
b0 = tf.constant(3.0)

Y = X@w0 + b0 + tf.random.normal([n,1],
    mean = 0.0,stddev= 2.0) # @表示矩陣乘法,增加正態(tài)擾動(dòng)

## 建立模型
tf.keras.backend.clear_session()
inputs = layers.Input(shape = (2,),name ="inputs") #設(shè)置輸入名字為inputs
outputs = layers.Dense(1, name = "outputs")(inputs) #設(shè)置輸出名字為outputs
linear = models.Model(inputs = inputs,outputs = outputs)
linear.summary()

## 使用fit方法進(jìn)行訓(xùn)練
linear.compile(optimizer="rmsprop",loss="mse",metrics=["mae"])
linear.fit(X,Y,batch_size = 8,epochs = 100)  

tf.print("w = ",linear.layers[1].kernel)
tf.print("b = ",linear.layers[1].bias)

## 將模型保存成pb格式文件
export_path = "./data/linear_model/"
version = "1"       #后續(xù)可以通過(guò)版本號(hào)進(jìn)行模型版本迭代與管理
linear.save(export_path+version, save_format="tf") 
#查看保存的模型文件
!ls {export_path+version}
assets  saved_model.pb  variables
# 查看模型文件相關(guān)信息
!saved_model_cli show --dir {export_path+str(version)} --all
MetaGraphDef with tag-set: 'serve' contains the following SignatureDefs:

signature_def['__saved_model_init_op']:
  The given SavedModel SignatureDef contains the following input(s):
  The given SavedModel SignatureDef contains the following output(s):
    outputs['__saved_model_init_op'] tensor_info:
        dtype: DT_INVALID
        shape: unknown_rank
        name: NoOp
  Method name is: 

signature_def['serving_default']:
  The given SavedModel SignatureDef contains the following input(s):
    inputs['inputs'] tensor_info:
        dtype: DT_FLOAT
        shape: (-1, 2)
        name: serving_default_inputs:0
  The given SavedModel SignatureDef contains the following output(s):
    outputs['outputs'] tensor_info:
        dtype: DT_FLOAT
        shape: (-1, 1)
        name: StatefulPartitionedCall:0
  Method name is: tensorflow/serving/predict
WARNING:tensorflow:From /tensorflow-2.1.0/python3.6/tensorflow_core/python/ops/resource_variable_ops.py:1786: calling BaseResourceVariable.__init__ (from tensorflow.python.ops.resource_variable_ops) with constraint is deprecated and will be removed in a future version.
Instructions for updating:
If using Keras pass *_constraint arguments to layers.

Defined Functions:
  Function Name: '__call__'
    Option #1
      Callable with:
        Argument #1
          inputs: TensorSpec(shape=(None, 2), dtype=tf.float32, name='inputs')
        Argument #2
          DType: bool
          Value: False
        Argument #3
          DType: NoneType
          Value: None
    Option #2
      Callable with:
        Argument #1
          inputs: TensorSpec(shape=(None, 2), dtype=tf.float32, name='inputs')
        Argument #2
          DType: bool
          Value: True
        Argument #3
          DType: NoneType
          Value: None

  Function Name: '_default_save_signature'
    Option #1
      Callable with:
        Argument #1
          inputs: TensorSpec(shape=(None, 2), dtype=tf.float32, name='inputs')

  Function Name: 'call_and_return_all_conditional_losses'
    Option #1
      Callable with:
        Argument #1
          inputs: TensorSpec(shape=(None, 2), dtype=tf.float32, name='inputs')
        Argument #2
          DType: bool
          Value: True
        Argument #3
          DType: NoneType
          Value: None
    Option #2
      Callable with:
        Argument #1
          inputs: TensorSpec(shape=(None, 2), dtype=tf.float32, name='inputs')
        Argument #2
          DType: bool
          Value: False
        Argument #3
          DType: NoneType
          Value: None

二惧笛,安裝 tensorflow serving

安裝 tensorflow serving 有2種主要方法:通過(guò)Docker鏡像安裝,通過(guò)apt安裝逞泄。

通過(guò)Docker鏡像安裝是最簡(jiǎn)單患整,最直接的方法拜效,推薦采用。

Docker可以理解成一種容器各谚,其上面可以給各種不同的程序提供獨(dú)立的運(yùn)行環(huán)境紧憾。

一般業(yè)務(wù)中用到tensorflow的企業(yè)都會(huì)有運(yùn)維同學(xué)通過(guò)Docker 搭建 tensorflow serving.

無(wú)需算法工程師同學(xué)動(dòng)手安裝,以下安裝過(guò)程僅供參考昌渤。

不同操作系統(tǒng)機(jī)器上安裝Docker的方法可以參照以下鏈接赴穗。

Windows: https://www.runoob.com/docker/windows-docker-install.html

MacOs: https://www.runoob.com/docker/macos-docker-install.html

CentOS: https://www.runoob.com/docker/centos-docker-install.html

安裝Docker成功后,使用如下命令加載 tensorflow/serving 鏡像到Docker中

docker pull tensorflow/serving


三膀息,啟動(dòng) tensorflow serving 服務(wù)

!docker run -t --rm -p 8501:8501 \
    -v "/Users/.../data/linear_model/" \
    -e MODEL_NAME=linear_model \
    tensorflow/serving & >server.log 2>&1

四般眉,向API服務(wù)發(fā)送請(qǐng)求

可以使用任何編程語(yǔ)言的http功能發(fā)送請(qǐng)求,下面示范linux的 curl 命令發(fā)送請(qǐng)求潜支,以及Python的requests庫(kù)發(fā)送請(qǐng)求甸赃。

!curl -d '{"instances": [1.0, 2.0, 5.0]}' \
    -X POST http://localhost:8501/v1/models/linear_model:predict
{
    "predictions": [[3.06546211], [5.01313448]
    ]
}
import json,requests

data = json.dumps({"signature_name": "serving_default", "instances": [[1.0, 2.0], [5.0,7.0]]})
headers = {"content-type": "application/json"}
json_response = requests.post('http://localhost:8501/v1/models/linear_model:predict', 
        data=data, headers=headers)
predictions = json.loads(json_response.text)["predictions"]
print(predictions)
[[3.06546211], [6.02843142]]

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市冗酿,隨后出現(xiàn)的幾起案子埠对,更是在濱河造成了極大的恐慌,老刑警劉巖裁替,帶你破解...
    沈念sama閱讀 221,548評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件项玛,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡胯究,警方通過(guò)查閱死者的電腦和手機(jī)稍计,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,497評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)裕循,“玉大人臣嚣,你說(shuō)我怎么就攤上這事“疲” “怎么了硅则?”我有些...
    開封第一講書人閱讀 167,990評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)株婴。 經(jīng)常有香客問(wèn)我怎虫,道長(zhǎng),這世上最難降的妖魔是什么困介? 我笑而不...
    開封第一講書人閱讀 59,618評(píng)論 1 296
  • 正文 為了忘掉前任大审,我火速辦了婚禮,結(jié)果婚禮上座哩,老公的妹妹穿的比我還像新娘徒扶。我一直安慰自己,他們只是感情好根穷,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,618評(píng)論 6 397
  • 文/花漫 我一把揭開白布姜骡。 她就那樣靜靜地躺著导坟,像睡著了一般。 火紅的嫁衣襯著肌膚如雪圈澈。 梳的紋絲不亂的頭發(fā)上惫周,一...
    開封第一講書人閱讀 52,246評(píng)論 1 308
  • 那天,我揣著相機(jī)與錄音康栈,去河邊找鬼递递。 笑死,一個(gè)胖子當(dāng)著我的面吹牛啥么,可吹牛的內(nèi)容都是我干的漾狼。 我是一名探鬼主播,決...
    沈念sama閱讀 40,819評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼饥臂,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼逊躁!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起隅熙,我...
    開封第一講書人閱讀 39,725評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤稽煤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后囚戚,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體酵熙,經(jīng)...
    沈念sama閱讀 46,268評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,356評(píng)論 3 340
  • 正文 我和宋清朗相戀三年驰坊,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了匾二。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,488評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡拳芙,死狀恐怖察藐,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情舟扎,我是刑警寧澤分飞,帶...
    沈念sama閱讀 36,181評(píng)論 5 350
  • 正文 年R本政府宣布,位于F島的核電站睹限,受9級(jí)特大地震影響譬猫,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜羡疗,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,862評(píng)論 3 333
  • 文/蒙蒙 一染服、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧叨恨,春花似錦柳刮、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,331評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至午乓,卻和暖如春站宗,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背益愈。 一陣腳步聲響...
    開封第一講書人閱讀 33,445評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工梢灭, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人蒸其。 一個(gè)月前我還...
    沈念sama閱讀 48,897評(píng)論 3 376
  • 正文 我出身青樓敏释,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親摸袁。 傳聞我的和親對(duì)象是個(gè)殘疾皇子钥顽,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,500評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容