tensorflow [saved_model,.pb]模型生成及處理以及多模型合併到上線服務請求從0到1

多模型合併:在模型上線時,我們訓練的多個模型往往功能相似或相近或有某種聯繫,在請求模型的返回結果時,如果一個接一個的去請求,會嚴重影響程序的效率。併發請求雖然能夠緩解這種現象,理論上甚至可以達到與單個模型相同的請求時間,但是實際操作與理論還是有很大差距的。很明顯,這種將模型串聯起來的方式不夠科學。如果把這些模型並聯起來,分別接受相同或不同的輸入,效果會大大不同,其運行效率與單個模型相差無幾。

接下來我將用幾篇的篇幅,講述模型從建立到上線的一系列流程,以及整個流程涉及到的併發請求、模型合併、串聯改並聯等一系列方式方法的實現及對比。

 

準備工作:爲了方便講解,整個過程均採用很簡單的模型作爲講解對象,以後稱爲模型一。

公式:

op = x*y+b

op1 = x*y + op

實現:

 

傳入參數x=5,y=5的測試結果是[26,51],

 

結果截圖

第一步,模型固化:

將模型一固化爲.pb模型,此處的.pb模型與上線用的saved_model裏的pb模型不一樣,這裏的pb模型包含了模型的縮影信息(結構和參數值)。

需要引入 graph_util:

from tensorflow.python.framework import graph_util

 

 

上圖中,‘op_to_store’和'op_1_to_store'是模型的輸出,這裏定義的輸出是模型一中的op,op_1.可以看到這裏用的是op,op_1的name屬性。’model.pb‘是pb模型的文件名,這裏是保存在當前目錄下的'model.pb'文件裏。

pb模型的讀取一般採用ParseFromString()函數,具體如下圖:

上圖中第一個框是讀pb模型的過程,第二個框是打印模型中的參數,第三個框是運行模型。要注意的是如何獲取模型參數,格式爲“模型名/參數名:0",讀取pb模型參數時,後面的”:0“一定不能去掉。

第二步:多個pb模型合併

合併模型前,首先要將要合併的模型讀取出來,然後重定向輸入輸出,最後固化保存。

首先,將讀取pb模型的部分寫成函數。

 

然後調用函數,分別讀取pb模型,爲了方便,本文將讀取5個相同的模型。不同結構、不同輸入輸出的模型也一樣可以執行接下來的並行操作,改變下輸入輸出即可。

 

上面是讀取模型的代碼,分別將讀出來的模型賦值給5個變量。由於5個模型輸入輸出一樣,因此定義輸入的時候,只需要定義一組。如果幾個模型結構不同,那就需要根據每個模型的要求分別定義輸入。

 

接下來重定向輸入輸出,

 

import_graph_def的第一個參數,就是我們上面讀取到的模型,在這裏是“graph_def_x”.

第二個參數”input_map“,輸入的是字典類型的數據,字典的鍵是“舊的輸入”,即子模型中的原來的輸入,這裏用名字來標記,字典的值是“新的輸入”,即上面定義的變量名。如上圖“input_x”和“input_y”是新的輸入,“x:0”和"y:0"是對應的子模型中的輸入,其含義就是“x:0”接受”input_x“的值,“y:0”接受"input_y"的值。

第三個參數,return_elements 定義的是模型的返回的值,比如當模型獲得一個輸入,可能會返回類別信息,或是一個評分,或是一個句子等等。在這裏我們返回的是“op_to_store:0”和“op_1_to_store:0”,與子模型裏的變量op和op_1的”name“屬性相對應。

tf.identity(graph_4, "mod_4") 表示的是在新的大模型裏,將子模型graph_4,識別爲“mod_4”;也可以理解爲,大模型重新爲小模型取了個名字。這個名字在模型結合,以及後續模型轉化、上線的過程中都會用到。

接下來是模型結合。

 

convert_variables_to_constants函數的第三個參數“output_node_names”是列表形式,傳入的是之前重定向後的模型名字。這個函數也可以用來固化單個模型爲pb模型,很方便。

write_graph函數將固化好的模型保存,g_combined_def是固化後的大模型;out_pb_path是模型保存的目錄;‘merge_model.pb’是模型保存後的名字;as_text的值一定要設置爲False,否則,讀取模型的時候會出錯。

至此,原來串聯的小模型已經是一個大的並行模型了。我們要驗證一下他的輸入輸出是否符合要求,讀取大模型的方式與之前類似,只是輸入和輸出變了。輸入時之前定義的新輸入,輸出是子模型的名字。

第一個框是讀取模型的過程,與之前類似,但注意一定要傳入“name”屬性,讀取模型內部參數時需要用到,這裏定義的“name”是“XXX”。

第二個框是讀取模型變量並打印出來的過程。

第三個框是,傳入一組數據得到輸出的過程。下圖爲執行結果。

 

 

 

可以看到,我們打印出來了獲取到的tensor,也打印出來了5個模型的輸出,每個子模型輸出和單個模型的輸出一樣,沒有被改變。

至此,合併子模型爲大模型的操作結束,同時也完成了子模型串聯改並聯。

第三步:模型上線準備:

純pb模型轉換爲saved_model模式,即saved_model.pb+variables的tfserving需要的模式。

接着上面的步驟,一步一步來,可以之前運行測試的代碼去掉,沒有影響,須保留讀取模型tensor的代碼:

 

builder是用來保存saved_model全程都需要的工具,用builder.SavedModelBuilder函數聲明,傳入的參數"./success/1/"是saved_model將要保存的地址。

inputs:定義模型要接受的輸入;

outputs:定義模型的輸出;

prediction_signature將模型的輸入輸出進行整合,其中method_name參數必須傳入,否則會提示錯誤;

builder.add_meta_graph_and_variables將模型結構及參數傳入builder;

builder.save():保存saved_model模型。

運行之後,/success/1下會有saved_model.pb和文件夾variables.

 

至此,模型已經可以利用tfserving部署上線了,上線流程與普通模型一樣,教程很多,在此不在贅述。要注意的一點是--enable-batch這個參數要去掉,否則請求的時候會出錯。

 

上線之後模型的請求,測試代碼如下:

 

下圖是模型請求的返回結果

 

以上所有代碼均在:

https://github.com/pkulics/tensorflow_model_process

歡迎訪問個人官網:lichangsong.win

我的個人網站:lichangsong.win

我的又大又全又便宜的某寶資料鋪:

 

緮置這行話¥PCYX1QCAm9R¥轉移至淘宀┡ē【碼世界資料鋪】;或https://m.tb.cn/h.V6uwZ9I?sm=916410 點擊鏈街,再選擇瀏..覽..噐dakai

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章