SIG TFX-Addonsコミュニティに参加して、TFXをさらに改善するのを手伝ってください!

標準のTensorFlowModelServerの構築

このチュートリアルでは、TensorFlow Servingコンポーネントを使用して、トレーニング済みのTensorFlowモデルの新しいバージョンを動的に検出して提供する標準のTensorFlowModelServerを構築する方法を示します。標準サーバーを使用してモデルを提供するだけの場合は、 TensorFlowServingの基本チュートリアルを参照してください

このチュートリアルでは、TensorFlowチュートリアルで紹介した単純なSoftmax回帰モデルを使用して、手書き画像(MNISTデータ)を分類します。 TensorFlowまたはMNISTが何であるかわからない場合は、 MNIST For MLBeginnersチュートリアルを参照してください。

このチュートリアルのコードは、次の2つの部分で構成されています。

  • モデルの複数のバージョンをトレーニングおよびエクスポートするPythonファイルmnist_saved_model.py

  • 新しいエクスポートされたモデルを検出し、それらを提供するためのgRPCサービスを実行する標準のTensorFlowModelServerであるC ++ファイルmain.cc。

このチュートリアルでは、次のタスクを実行します。

  1. TensorFlowモデルをトレーニングしてエクスポートします。
  2. TensorFlowサービングとバージョン管理モデルの管理ServerCore
  3. SavedModelBundleSourceAdapterConfigを使用してバッチ処理を構成しSavedModelBundleSourceAdapterConfig
  4. TensorFlowサービングと要求サーブServerCore
  5. サービスを実行してテストします。

始める前に、まずDockerをインストールします

TensorFlowモデルのトレーニングとエクスポート

まず、まだ行っていない場合は、このリポジトリをローカルマシンに複製します。

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

エクスポートディレクトリがすでに存在する場合は、クリアします。

rm -rf /tmp/models

(100回の反復で)トレーニングし、モデルの最初のバージョンをエクスポートします。

tools/run_in_docker.sh python tensorflow_serving/example/mnist_saved_model.py \
  --training_iteration=100 --model_version=1 /tmp/mnist

(2000回の反復で)トレーニングし、モデルの2番目のバージョンをエクスポートします。

tools/run_in_docker.sh python tensorflow_serving/example/mnist_saved_model.py \
  --training_iteration=2000 --model_version=2 /tmp/mnist

mnist_saved_model.pyれているmnist_saved_model.pyに、トレーニングとエクスポートは、 TensorFlowServingの基本チュートリアルと同じ方法で実行されます。デモンストレーションの目的で、最初の実行のトレーニング反復を意図的にダイヤルダウンしてv1としてエクスポートし、2番目の実行のトレーニングを通常どおりに行い、同じ親ディレクトリにv2としてエクスポートします。より集中的なトレーニングにより、分類の精度が向上します。 /tmp/mnistディレクトリに実行された各トレーニングのトレーニングデータが表示されます。

$ ls /tmp/mnist
1  2

ServerCore

ここで、モデルのv1とv2が実行時に動的に生成されると想像してください。新しいアルゴリズムが実験されているとき、またはモデルが新しいデータセットでトレーニングされているときです。本番環境では、段階的なロールアウトをサポートできるサーバーを構築することをお勧めします。このサーバーでは、v1の提供中に、v2を検出、ロード、実験、監視、または元に戻すことができます。または、v2を起動する前にv1を破棄することもできます。 TensorFlow Servingは両方のオプションをサポートしています。一方は移行中の可用性を維持するのに適していますが、もう一方はリソース使用量(RAMなど)を最小限に抑えるのに適しています。

TensorFlowサービングManager正確に行います。 TensorFlowモデルのロード、提供、アンロード、バージョンの移行など、TensorFlowモデルのライフサイクル全体を処理します。このチュートリアルでは、サービングTensorFlowの上にサーバーを構築しますServerCore内部でラップし、 AspiredVersionsManager

int main(int argc, char** argv) {
  ...

  ServerCore::Options options;
  options.model_server_config = model_server_config;
  options.servable_state_monitor_creator = &CreateServableStateMonitor;
  options.custom_model_config_loader = &LoadCustomModelConfig;

  ::google::protobuf::Any source_adapter_config;
  SavedModelBundleSourceAdapterConfig
      saved_model_bundle_source_adapter_config;
  source_adapter_config.PackFrom(saved_model_bundle_source_adapter_config);
  (*(*options.platform_config_map.mutable_platform_configs())
      [kTensorFlowModelPlatform].mutable_source_adapter_config()) =
      source_adapter_config;

  std::unique_ptr<ServerCore> core;
  TF_CHECK_OK(ServerCore::Create(options, &core));
  RunServer(port, std::move(core));

  return 0;
}

ServerCore::Create()は、ServerCore :: Optionsパラメーターを取ります。一般的に使用されるオプションは次のとおりです。

  • ModelServerConfigするモデルを指定するModelServerConfig 。モデルは、いずれかを介して宣言されているmodel_config_listモデルの静的リストを宣言し、または貫通、 custom_model_config実行時に更新されるかもしれませんモデルのリストを宣言するためのカスタム方法を定義し、。
  • PlatformConfigMapの名前( tensorflowなど)からSourceAdapter作成に使用されるPlatformConfigMapにマップするPlatformConfigSourceAdapterは、 StoragePath (モデルバージョンが検出されるパス)をモデルLoader (ストレージパスからモデルバージョンをロードし、 Manager状態遷移インターフェイスを提供する)に適合させます。 PlatformConfigSavedModelBundleSourceAdapterConfigが含まれている場合、 SavedModelBundleSourceAdapterが作成されます。これについては後で説明します。

SavedModelBundleは、 SavedModelBundleの主要コンポーネントです。これは、特定のパスからロードされたTensorFlowモデルを表し、推論を実行するためにTensorFlowと同じSession::Runインターフェイスを提供します。 SavedModelBundleSourceAdapterは、ストレージパスをLoader<SavedModelBundle>適合させ、モデルの有効期間をManagerで管理できるようにします。 SavedModelBundleは非推奨のSessionBundleの後継であることに注意してください。 SessionBundleのサポートはまもなく削除されるため、ユーザーはSavedModelBundleを使用することをSavedModelBundle勧めします。

これらすべてを使用して、 ServerCore内部的に次のことを行います。

  • model_config_list宣言されたモデルエクスポートパスを監視するFileSystemStoragePathSourceをインスタンス化しFileSystemStoragePathSource
  • インスタンス化SourceAdapter使用PlatformConfigMapモデルプラットフォームとはで宣言さmodel_config_listと接続しFileSystemStoragePathSourceそれに。このようにして、エクスポートパスの下で新しいモデルバージョンが検出されるたびに、 SavedModelBundleSourceAdapterはそれをLoader<SavedModelBundle>適合させます。
  • SavedModelBundleSourceAdapterによって作成されたそのようなすべてのLoaderインスタンスを管理するAspiredVersionsManagerと呼ばれるManager特定の実装をインスタンス化します。 ServerCoreは、 AspiredVersionsManagerへの呼び出しを委任することにより、 Managerインターフェイスをエクスポートします。

新しいバージョンが利用可能になるたびに、このAspiredVersionsManagerは新しいバージョンをロードし、デフォルトの動作では古いバージョンをアンロードします。カスタマイズを開始する場合は、内部で作成されるコンポーネントとその構成方法を理解することをお勧めします。

TensorFlow Servingは、非常に柔軟で拡張可能であるようにゼロから設計されていることは言及する価値があります。 ServerCoreAspiredVersionsManagerなどの汎用コアコンポーネントを利用しながら、さまざまなプラグインを構築してシステムの動作をカスタマイズできます。たとえば、ローカルストレージの代わりにクラウドストレージを監視するデータソースプラグインを構築したり、別の方法でバージョン移行を行うバージョンポリシープラグインを構築したりできます。実際、 TensorFlow以外のモデル。これらのトピックは、このチュートリアルの範囲外です。ただし、詳細については、カスタムソースおよびカスタムサービス可能チュートリアルを参照できます。

バッチ処理

実稼働環境で必要なもう1つの典型的なサーバー機能は、バッチ処理です。機械学習の推論を行うために使用される最新のハードウェアアクセラレータ(GPUなど)は、通常、推論要求が大きなバッチで実行されるときに最高の計算効率を実現します。

SavedModelBundleSourceAdapter作成するときに適切なSessionBundleConfigすることで、 SavedModelBundleSourceAdapterオンにできます。この場合、 BatchingParametersをほぼデフォルト値で設定します。バッチ処理は、カスタムタイムアウト、batch_sizeなどの値を設定することで微調整できます。詳細については、 BatchingParametersを参照してください。

SessionBundleConfig session_bundle_config;
// Batching config
if (enable_batching) {
  BatchingParameters* batching_parameters =
      session_bundle_config.mutable_batching_parameters();
  batching_parameters->mutable_thread_pool_name()->set_value(
      "model_server_batch_threads");
}
*saved_model_bundle_source_adapter_config.mutable_legacy_config() =
    session_bundle_config;

tensorflow::Session::Run()に達すると、推論リクエストは内部で単一の大きなリクエスト(テンソル)にtensorflow::Session::Run()tensorflow::Session::Run()が呼び出されます(GPUの実際の効率向上はここから発生します)。

マネージャーと一緒に奉仕する

前述のように、TensorFlow Serving Managerは、任意の機械学習システムによって生成されたモデルのロード、サービング、アンロード、バージョン遷移を処理できる汎用コンポーネントとして設計されています。そのAPIは、次の主要な概念に基づいて構築されています。

  • Servable :Servableは、クライアント要求を処理するために使用できる不透明なオブジェクトです。サーバブルのサイズと粒度は柔軟であるため、1つのサーバブルには、ルックアップテーブルの単一のシャードから、単一の機械学習モデル、複数のモデルまで、あらゆるものが含まれる可能性があります。サーバブルは、任意のタイプとインターフェースにすることができます。

  • サービス提供可能なバージョン:Servablesはバージョン管理されているとTensorFlowサービングManagerサービス提供可能なの1つまたは複数のバージョンを管理することができます。バージョン管理により、サーバブルの複数のバージョンを同時にロードできるようになり、段階的なロールアウトと実験がサポートされます。

  • Servable StreamServable Streamは、バージョン番号が増加する、Servableのバージョンのシーケンスです。

  • モデル:機械学習モデルは、1つ以上のサーバブルで表されます。使用可能なものの例は次のとおりです。

    • 以下のような彼らの周りTensorFlowセッションやラッパー、 SavedModelBundle
    • 他の種類の機械学習モデル。
    • 語彙ルックアップテーブル。
    • ルックアップテーブルの埋め込み。

    複合モデルは、複数の独立したサーバブルとして、または単一の複合サーバブルとして表すことができます。サーバブルは、モデルの一部に対応する場合もあります。たとえば、多くのManagerインスタンスにまたがってシャーディングされた大きなルックアップテーブルがあります。

これらすべてをこのチュートリアルのコンテキストに入れるには:

  • TensorFlowモデルは、1種類のservable( SavedModelBundleで表されます。 SavedModelBundleは、内部的にtensorflow:Sessionと、セッションに読み込まれるグラフと推論のために実行する方法に関するメタデータで構成されています。

  • TensorFlowエクスポートのストリームを含むファイルシステムディレクトリがあり、それぞれがバージョン番号である独自のサブディレクトリにあります。外部ディレクトリは、提供されているTensorFlowモデルの提供可能なストリームのシリアル化された表現と考えることができます。各エクスポートは、ロード可能なサーバブルに対応しています。

  • AspiredVersionsManagerは、エクスポートストリームを監視し、すべてのSavedModelBundleサーバブルのライフサイクルを動的に管理します。

TensorflowPredictImpl::Predict次に、次のようにします。

  • (ServerCoreを介して)マネージャーからSavedModelBundleを要求します。
  • generic signaturesを使用して、 PredictRequest論理テンソル名を実際のテンソル名にマップし、値をテンソルにバインドします。
  • 推論を実行します。

サーバーをテストして実行します

エクスポートの最初のバージョンを監視対象フォルダーにコピーします。

mkdir /tmp/monitored
cp -r /tmp/mnist/1 /tmp/monitored

次に、サーバーを起動します。

docker run -p 8500:8500 \
  --mount type=bind,source=/tmp/monitored,target=/models/mnist \
  -t --entrypoint=tensorflow_model_server tensorflow/serving --enable_batching \
  --port=8500 --model_name=mnist --model_base_path=/models/mnist &

サーバーは、「サービス可能なバージョンを目指しています...」というログメッセージを1秒ごとに送信します。これは、エクスポートが検出され、その継続的な存在を追跡していることを意味します。

--concurrency=10クライアントを実行してみましょう。これにより、サーバーに同時リクエストが送信され、バッチ処理ロジックがトリガーされます。

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

その結果、次のような出力になります。

...
Inference error rate: 13.1%

次に、エクスポートの2番目のバージョンを監視対象フォルダーにコピーし、テストを再実行します。

cp -r /tmp/mnist/2 /tmp/monitored
tools/run_in_docker.sh python tensorflow_serving/example/mnist_client.py \
  --num_tests=1000 --server=127.0.0.1:8500 --concurrency=10

その結果、次のような出力になります。

...
Inference error rate: 9.5%

これにより、サーバーが新しいバージョンを自動的に検出し、それをサービスに使用することが確認されます。