提供 TensorFlow 模型

本教學課程說明如何使用 TensorFlow Serving 元件匯出已訓練的 TensorFlow 模型,並使用標準 tensorflow_model_server 提供模型。如果您已熟悉 TensorFlow Serving,而且想進一步瞭解伺服器內部運作方式,請參閱TensorFlow Serving 進階教學課程

本教學課程使用簡單的 Softmax 迴歸模型,對手寫數字進行分類。這個模型與TensorFlow 關於使用 Fashion MNIST 資料集進行圖片分類的教學課程中介紹的模型非常相似。

本教學課程的程式碼包含兩部分

  • Python 檔案 mnist_saved_model.py,用於訓練和匯出模型。

  • ModelServer 二進位檔,可以使用 Apt 安裝,或從 C++ 檔案 (main.cc) 編譯而來。TensorFlow Serving ModelServer 會探索新匯出的模型,並執行 gRPC 服務以提供模型。

開始使用前,請先安裝 Docker

訓練及匯出 TensorFlow 模型

在訓練階段,TensorFlow 圖表會在 TensorFlow 工作階段 sess 中啟動,其中輸入張量 (圖片) 為 x,輸出張量 (Softmax 分數) 為 y

接著,我們使用 TensorFlow 的 SavedModelBuilder 模組匯出模型。SavedModelBuilder 會將已訓練模型的「快照」儲存到可靠的儲存空間,以便日後載入以進行推論。

如需 SavedModel 格式的詳細資訊,請參閱 SavedModel README.md 的文件。

以下是來自 mnist_saved_model.py 的簡短程式碼片段,用於說明將模型儲存到磁碟的一般流程。

export_path_base = sys.argv[-1]
export_path = os.path.join(
    tf.compat.as_bytes(export_path_base),
    tf.compat.as_bytes(str(FLAGS.model_version)))
print('Exporting trained model to', export_path)
builder = tf.saved_model.builder.SavedModelBuilder(export_path)
builder.add_meta_graph_and_variables(
    sess, [tf.compat.v1.saved_model.tag_constants.SERVING],
    signature_def_map={
        'predict_images':
            prediction_signature,
        tf.compat.v1.saved_model.signature_constants
            .DEFAULT_SERVING_SIGNATURE_DEF_KEY:
            classification_signature,
    },
    main_op=tf.compat.v1.tables_initializer(),
    strip_default_attrs=True)
builder.save()

SavedModelBuilder.__init__ 接受下列引數

  • export_path 是匯出目錄的路徑。

如果目錄不存在,SavedModelBuilder 將會建立目錄。在本範例中,我們將命令列引數和 FLAGS.model_version 串連起來以取得匯出目錄。FLAGS.model_version 指定模型的版本。匯出相同模型的新版本時,您應指定較大的整數值。每個版本都會匯出到指定路徑下的不同子目錄。

您可以使用 SavedModelBuilder.add_meta_graph_and_variables() 將中繼圖表和變數新增至產生器,並搭配下列引數

  • sess 是 TensorFlow 工作階段,其中包含您要匯出的已訓練模型。

  • tags 是用於儲存中繼圖表的標記集。在本例中,由於我們打算在提供模型時使用圖表,因此我們使用預先定義的 SavedModel 標記常數中的 serve 標記。如需更多詳細資訊,請參閱 tag_constants.py相關的 TensorFlow API 文件

  • signature_def_map 指定使用者提供的金鑰地圖,用於將簽名新增至中繼圖表的 tensorflow::SignatureDef。簽名指定要匯出的模型類型,以及在執行推論時要繫結的輸入/輸出張量。

    特殊的簽名金鑰 serving_default 指定預設提供模型簽名。預設提供模型簽名定義金鑰,以及其他與簽名相關的常數,皆定義為 SavedModel 簽名常數的一部分。如需更多詳細資訊,請參閱 signature_constants.py相關的 TensorFlow API 文件

    此外,為了協助輕鬆建構簽名定義,SavedModel API 提供了簽名定義公用程式。具體來說,在原始 mnist_saved_model.py 檔案中,我們使用 signature_def_utils.build_signature_def() 來建構 predict_signatureclassification_signature

    以下說明如何定義 predict_signature 的範例,公用程式會採用下列引數

    • inputs={'images': tensor_info_x} 指定輸入張量資訊。

    • outputs={'scores': tensor_info_y} 指定分數張量資訊。

    • method_name 是用於推論的方法。對於預測要求,應設定為 tensorflow/serving/predict。如需其他方法名稱,請參閱 signature_constants.py相關的 TensorFlow API 文件

請注意,tensor_info_xtensor_info_y 具有 此處定義的 tensorflow::TensorInfo 通訊協定緩衝區結構。為了輕鬆建構張量資訊,TensorFlow SavedModel API 也提供 utils.py,以及相關的 TensorFlow API 文件

另請注意,imagesscores 是張量別名。它們可以是您想要的任何獨特字串,而且會成為您稍後在傳送預測要求以進行張量繫結時參考的張量 xy 的邏輯名稱。

例如,如果 x 參照名稱為 'long_tensor_name_foo' 的張量,而 y 參照名稱為 'generated_tensor_name_bar' 的張量,則 builder 會儲存張量邏輯名稱到實際名稱的對應 ('images' -> 'long_tensor_name_foo') 和 ('scores' -> 'generated_tensor_name_bar')。這可讓使用者在執行推論時使用邏輯名稱來參照這些張量。

開始執行吧!

首先,如果您尚未執行此操作,請將這個存放區複製到您的本機電腦

git clone https://github.com/tensorflow/serving.git
cd serving

清除匯出目錄 (如果已存在)

rm -rf /tmp/mnist

現在開始訓練模型

tools/run_in_docker.sh python tensorflow_serving/example/mnist_saved_model.py \
  /tmp/mnist

這應該會產生如下所示的輸出

Training model...

...

Done training!
Exporting trained model to models/mnist
Done exporting!

現在我們來看看匯出目錄。

$ ls /tmp/mnist
1

如上所述,系統會建立子目錄,用於匯出模型的每個版本。FLAGS.model_version 的預設值為 1,因此會建立對應的子目錄 1

$ ls /tmp/mnist/1
saved_model.pb variables

每個版本子目錄都包含下列檔案

  • saved_model.pb 是序列化的 tensorflow::SavedModel。它包含模型的一個或多個圖表定義,以及模型的 Metadata (例如簽名)。

  • variables 是儲存圖表序列化變數的檔案。

這樣一來,您的 TensorFlow 模型就已匯出,可以載入了!

使用標準 TensorFlow ModelServer 載入匯出的模型

使用 Docker 提供模型映像檔,即可輕鬆載入模型以進行提供

docker run -p 8500:8500 \
--mount type=bind,source=/tmp/mnist,target=/models/mnist \
-e MODEL_NAME=mnist -t tensorflow/serving &

測試伺服器

我們可以使用提供的 mnist_client 公用程式來測試伺服器。用戶端會下載 MNIST 測試資料、將資料做為要求傳送至伺服器,並計算推論錯誤率。

tools/run_in_docker.sh python tensorflow_serving/example/mnist_client.py \
  --num_tests=1000 --server=127.0.0.1:8500

這應該會輸出類似這樣的內容

    ...
    Inference error rate: 11.13%

我們預期已訓練的 Softmax 模型準確度約為 90%,而前 1000 張測試圖片的推論錯誤率為 11%。這證實伺服器已成功載入並執行已訓練的模型!