日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

用Docker容器自带的tensorflow serving部署模型对外服务

發布時間:2023/12/13 编程问答 46 豆豆
生活随笔 收集整理的這篇文章主要介紹了 用Docker容器自带的tensorflow serving部署模型对外服务 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

相信很多人和我一樣,在試圖安裝tensorflow serving的時候,翻遍了網上的博客和官網文檔,安裝都是以失敗而告終,我也是一樣,這個問題折磨了我兩個星期之久,都快放棄了。幸運的是在同事的建議下,我采用了一種迂回的策略安裝成功了。

?

我們采用的策略是:

? ? ? ? pull一個已經安裝好了tensorflow serving的docker鏡像,替換它自帶的一些模型為我們自己的模型。

?

步驟:

1、拉取帶tensorflow serving的docker鏡像,這樣我們服務器上就有了一個安裝了ModelServer的docker容器, 這個容器就可以看做一臺虛擬機,這個虛擬機上已經安裝好了tensorflow serving,環境有了,就可以用它來部署我們的模型了。注意這個拉取下來后不是直接放在當前目錄的,而是docker默認存儲的路徑,這個是個docker容器,和第2步clone下來的不是同一個東西

$docker pull tensorflow/serving

2、獲取例子模型:(當然,也可以直接用上面容器中自帶的例子),當然這里是直接拉取了tensorflow serving的源碼,源碼中有一些訓練好的例子模型

  • $cd /root/software/
  • $git clone https://github.com/tensorflow/serving
  • 3、用第一步拉取的docker容器運行例子模型

    第2步中clone下來的serving源碼中有這樣一個訓練好的例子模型,路徑為:

    /root/software/serving/tensorflow_serving/servables/tensorflow/testdata/saved_model_half_plus_two_cpu

    現在我們就要用第1步拉下來的docker容器來運行部署這個例子模型

  • $docker run -p 8501:8501 \
  • --mount type=bind,\
  • source=/root/software/serving/tensorflow_serving/servables/tensorflow/testdata/saved_model_half_plus_two_cpu,\
  • target=/models/half_plus_two \
  • -e MODEL_NAME=half_plus_two -t tensorflow/serving &
  • 參數說明:

  • --mount: 表示要進行掛載
  • source: 指定要運行部署的模型地址, 也就是掛載的源,這個是在宿主機上的模型目錄
  • target: 這個是要掛載的目標位置,也就是掛載到docker容器中的哪個位置,這是docker容器中的目錄
  • -t: 指定的是掛載到哪個容器
  • -p: 指定主機到docker容器的端口映射
  • docker run: 啟動這個容器并啟動模型服務(這里是如何同時啟動容器中的模型服務的還不太清楚)
  • 綜合解釋:
  • 將source目錄中的例子模型,掛載到-t指定的docker容器中的target目錄,并啟動
  • 這步注意,如果執行報錯無法識別type=bind, 那應該是source的路徑有問題

    4、調用這個服務,這里用的http接口

  • $curl -d '{"instances": [1.0, 2.0, 5.0]}' \
  • -X POST http://localhost:8501/v1/models/half_plus_two:predict
  • 得到的結果如下:

    { "predictions": [2.5, 3.0, 4.5] }

    這就表明服務已經部署成功了,當然你也可以用requests來模型上述http請求

    5、查看啟動的這個模型的目錄的結構

    我們可以看到啟動服務的命令有一個參數:

    source=/root/software/serving/tensorflow_serving/servables/tensorflow/testdata/saved_model_half_plus_two_cpu

    這實際就是模型的位置, 我們進入到這個目錄下(這個目錄基于自己pull時所在的目錄),可以看到里面是一個名為00000123的目錄,這實際是模型的版本,再進入到這個目錄下可以看到一個如下兩個文件:

    saved_model.pb, variables

    variable目錄下有如下兩個文件:

    variables.data-00000-of-00001, variables.index

    6、用自己的模型替換上述half_plus_two模型

    我在和saved_model_half_plus_two_cpu模型同級的目錄下創建了一個文件夾,名為textcnnrnn, 這是我模型的名稱,然后

  • $cd textcnnrnn
  • $mkdir 00000123
  • $cd 00000123
  • $mkdir variables
  • $cd variables
  • 我一開始是直接用的我之前訓練好的模型放到了variables目錄下,我訓練好的模型包含如下幾個文件:

    best_validation.data-00000-of-00001 best_validation.index best_validation.meta checkpoint

    相信大家都看出來了,這個是用這種方式保存的:

  • saver = tf.train.Saver()
  • saver.save(sess=session, save_path=save_path)
  • 于是我激動的去重新啟動我的模型,當然這里要修改模型的地址,我也把我的模型的名字改了下:

    docker run -p 8501:8501 --mount source=/root/software/serving/tensorflow_serving/servables/tensorflow/testdata/textcnnrnn,type=bind,target=/models/find_lemma_category -e MODEL_NAME=find_lemma_category -t tensorflow/serving &

    可是這個時候報錯了,做法不對。下面是正確的做法。

    其實仔細比較我的模型的幾個文件和half_plus_two模型的下的文件的結構根本不一樣,怎么辦呢? 其實應該對模型的格式進行轉換。 代碼如下:

  • # coding: utf-8
  • from __future__ import print_function
  • import pdb
  • import time
  • import os
  • import tensorflow as tf
  • import tensorflow.contrib.keras as kr
  • from cnn_rnn_model import TCNNRNNConfig, TextCNNRNN
  • save_path = 'model_saver/textcnnrnn/best_validation'
  • try:
  • bool(type(unicode))
  • except NameError:
  • unicode = str
  • config = TCNNRNNConfig()
  • def build_and_saved_wdl():
  • model = TextCNNRNN(config) #我自己的模型結構是在這個類中定義的,基于自己的模型進行替換
  • session = tf.Session()
  • session.run(tf.global_variables_initializer())
  • saver = tf.train.Saver()
  • saver.restore(sess=session, save_path=save_path)
  • # 將訓練好的模型保存在model_name下,版本為2,當然你的版本可以隨便寫
  • builder = tf.saved_model.builder.SavedModelBuilder("./model_name/2")
  • inputs = {
  • #注意,這里是你預測模型的時候需要傳的參數,調用模型的時候,傳參必須和這里一致
  • #這里的model.input_x和model.keep_prob就是模型里面定義的輸入placeholder
  • "input_x": tf.saved_model.utils.build_tensor_info(model.input_x),
  • "keep_prob": tf.saved_model.utils.build_tensor_info(model.keep_prob)
  • }
  • #model.y_pred_cls是模型的輸出, 預測的時候就是計算這個表達式
  • output = {"output": tf.saved_model.utils.build_tensor_info(model.y_pred_cls)}
  • prediction_signature = tf.saved_model.signature_def_utils.build_signature_def(
  • inputs=inputs,
  • outputs=output,
  • method_name=tf.saved_model.signature_constants.PREDICT_METHOD_NAME
  • )
  • builder.add_meta_graph_and_variables(
  • session,
  • [tf.saved_model.tag_constants.SERVING],
  • {tf.saved_model.signature_constants.DEFAULT_SERVING_SIGNATURE_DEF_KEY: prediction_signature}
  • )
  • builder.save()
  • if __name__ == '__main__':
  • build_and_saved_wdl()
  • 執行后,會在當前目錄下生成一個名稱為./model_name/2的文件夾, 這個文件夾下的文件格式和halt_plus_two中的文件格式是一致的了,這下肯定沒錯了。

    將./model_name/2文件夾下的內容拷貝到textcnnrnn/00000123目錄下即可。

    重新啟動模型,這次啟動成功了,沒有報錯,說明我們的模型已經被識別成功。

    7、調用模型

    咋調啊?咋傳參數啊?懵逼,先看看調用自帶的模型怎么傳參數的吧:

  • curl -d '{"instances": [1.0, 2.0, 5.0]}' \
  • -X POST http://localhost:8501/v1/models/half_plus_two:predict
  • 看樣子instances應該是參數的名字,于是我想看看tensorflow serving源碼里面是怎么解析這個參數的,所以我在源碼根目錄下全局搜索了這個關鍵字,在根目錄下搜索關鍵詞instances:

    $find . -name '*.*' | xargs grep -l instances

    可以找到一個名為json_tensor.h的文件,這個文件詳細介紹了不同的傳參的方式:

    instances是一個list,list中每個元素是一個待預測實例,每個實例里面是所有參數的值, 所以參數按照這種方式構造就可以了。

    這里json.dumps的時候可能會遇到一個序列化的錯誤,原因是json.dumps對于含numpy.array類型的數據無法序列化, 可以構造一個編碼器, 然后作為json.dumps參數:

  • class NumpyEncoder(json.JSONEncoder):
  • def default(self, obj):
  • if isinstance(obj, np.ndarray):
  • return obj.tolist()
  • return json.JSONEncoder.default(self, obj)
  • p_data = {"keep_prob": 1.0, "input_x": x_test[0]}
  • param = {"instances": [p_data]}
  • param = json.dumps(param, cls=NumpyEncoder)
  • res = requests.post('http://localhost:8501/v1/models/find_lemma_category:predict', data=param)
  • 這樣就大功告成了!

    這里還有一個地方需要注意:其實我的模型Input_x本身是直接可以接收多個實例的,也就是上面我的參數x_test是多個實例構造的參數,但是直接傳入會出錯,所以我只能傳入一個實例x_test[0]。 如果想同時預測多個的話只能這樣構造參數:

  • data1 = {"keep_prob": 1.0, "input_x": x_test[0]}
  • data2 = {"keep_prob": 1.0, "input_x": x_test[1]}
  • data3 = {"keep_prob": 1.0, "input_x": x_test[2]}
  • param = {"instances": [data1, data2, data3]}
  • param = json.dumps(param, cls=NumpyEncoder)
  • res = requests.post('http://localhost:8501/v1/models/find_lemma_category:predict', data=param)
  • 8、參數要預處理怎么辦?

    假如我們需要在將參數輸入模型之前做一些預處理怎么辦?比如要對大段文本進行分詞等等。

    解決辦法: 部署一個中轉服務,我采用的策略是用tornado再部署一個服務,這個服務負責對業務方傳輸過來的參數進行預處理,處理成模型需要的格式后,再傳輸給模型, 所以我的結構是這樣的:

    業務方 ==> ?tornado服務(參數預處理) ==> 模型(tensorflow serving服務)

    這里面的兩次遠程調用都是http協議。

    ?

    參考地址:

    ? ??https://www.tensorflow.org/serving/docker

    ? ??https://www.jianshu.com/p/2fffd0e332bc

    ?

    ?

    ?

    ?

    ?

    總結

    以上是生活随笔為你收集整理的用Docker容器自带的tensorflow serving部署模型对外服务的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。