モデルのデプロイ

Cloud ML Engine でトレーニングしたモデルをクラウドでホストし、それらを使用して予測を処理することができます。このページでは、モデルをデプロイする方法を説明します。予測プロセスに関する一般的な背景情報については、予測の概要ページをご覧ください。

クラウド内でモデルをトレーニングする場合でも、他の場所でトレーニングする場合でも、TensorFlow モデルを Cloud ML Engine にデプロイし、それらを使用して予測を処理することができます。

始める前に

モデルをトレーニングした後、予測のために Cloud ML Engine にデプロイする前に、重要な調整を行う必要があります。

  • モデルを SavedModel にエクスポートする

  • 予測のためにグラフを明示的にエクスポートして、SavedModel のファイルサイズが Cloud ML Engine のデフォルトの 250 MB 以下であることを確認する。

  • SavedModel を Cloud Storage に保存する。

トレーニング グラフとサービスグラフについて

モデルをトレーニングして SavedModel としてエクスポートした場合、予測を取得する準備を整えるには重要なステップがあります。

トレーニング グラフとサービスグラフにはいくつかの重要な違いがあります。トレーニング グラフには、表示に適していない次のような機能が含まれています。

  • ファイル リーダー
  • 入力キュー
  • ドロップアウト レイヤ
  • 損失関数
  • オプティマイザー

サービス予測のプロセスにはトレーニングのプロセスとは異なるニーズがあるため、サービス予測用に明示的に個別のグラフをエクスポートすることがベスト プラクティスです。

SavedModel について

SavedModel は TensorFlow が推奨するモデルの保存形式で、トレーニングされた TensorFlow モデルを Cloud ML Engine にデプロイするために必要な形式です。トレーニングされたモデルを SavedModel としてエクスポートすると、アセット、変数、およびメタデータを含むトレーニング グラフが、Cloud ML Engine が予測用に消費および復元できる形式で保存されます。

SavedModel をエクスポートすると、SavedModel ディレクトリには次の内容が含まれます。

  • SavedModel プロトコル バッファに保存されたトレーニング グラフ
  • アセットと呼ばれる外部ファイル
  • チェックポイント ファイルとして保存される変数

SavedModel を Cloud ML Engine にデプロイするときは、グラフとそのメタデータを含む SavedModel プロトコル バッファ ファイルだけでなく、SavedModel ディレクトリ全体を含める必要があります。このファイルの拡張子は通常 .pb または .pbtxt です。

SavedModel を使用すると、同じアセットと変数(またはチェックポイント)を共有する複数のバージョンのグラフを保存できます。たとえば、同じグラフの 2 つのバージョン(CPU で実行するバージョンと GPU で実行するバージョン)を開発することができます。

詳しくは、SavedModel ディレクトリの構造をご覧ください。

モデルサイズの確認と調整

Cloud ML Engine をデプロイするには、SavedModel を 250 MB 以下にする必要があります。これには、SavedModel プロトコル バッファ ファイル自体(つまり、saved_model.pb または saved_model.pbtxt)だけでなく、SavedModel ディレクトリのすべてのアセットと変数が含まれます。

開発時にモデルサイズを確認するには、SavedModel をエクスポートしてディレクトリのファイルサイズを確認します。

SavedModel が 250 MB の制限を超えている場合:

モデルサイズを小さくする

モデルサイズを小さくするには:

  • 予測に必要なものだけを使って新しいグラフを作成する
  • 重みとデータの精度を低下させる

これらの手順を実行すると、SavedModel を 250 MB の制限に収めることができ、予測のレイテンシを減らすことができます。メリットとしては、パフォーマンスが向上し、割り当ての増加をリクエストして待機する必要がないことが挙げられます。

最適な予測グラフを作成する

トレーニングでは、サービス予測に使用されない複数のチェックポイントが生成されます。これらのアーティファクトがなく、デプロイするモデルのみを含むディレクトリをアップロードしてください。

たとえば、トレーニング プロセス中に TensorBoard の可視化に関する概要をエクスポートする場合、それらが SavedModel に含まれていないことを確認する必要があります。これらの TensorBoard の概要は、予測グラフには必要ありません。

Estimator をトレーニングおよび予測に使用する場合は、export_savedmodel 関数を使用して SavedModel を取得できます。それ以外の場合は、SavedModelBuilder を使用してモデルをエクスポートできます。正しいタグとシグネチャで SavedModelBuilder を使用してモデルをエクスポートする方法については、MNIST の例をご覧ください。

精度を下げてファイルサイズを減らす

変数と入力データの精度を下げることは、予測精度と引き換えに、モデルサイズを大幅に縮小することです。高精度データは、低精度データに比べて格納する際の効率が低下します。低精度のデータはノイズ源ですが、ニューラル ネットワークはこのノイズを「無視」し、かなり正確な予測を生成します。

これらの方法を使用すると、ユースケースの予測精度が大幅に低下する場合は、割り当ての増加のリクエストを試してみてください。

  • 重みのサイズを小さくすることによってファイルサイズを縮小します。重みは、デフォルトでは効率的に保存するのが難しい浮動小数点の数になります。これらの非効率的に格納された重みは、モデルの全体的なファイルサイズに最も大きく影響します。

  • 精度を大幅に犠牲にすることなく、モデルのサイズを最大 75% 削減するために、連続データを量子化します。

  • 精度の低い変数を使用します。たとえば、データ型(dtype)を int64 から int32 に変更します。

  • SavedModel ディレクトリの assets フォルダにある他の入力機能のサイズを減らします。たとえば、テキストデータの語彙サイズを小さくします。

SavedModels とグラフを検査するツール

TensorFlow は、入力書式や SignatureDefs など、SavedModel の側面の健全性チェックに使用できるコマンドライン インターフェースを提供します。詳しくは、SavedModel CLI をご覧ください。

TensorFlow のグラフ変換ツールを使用して、デプロイ用にモデルを最適化することができます。このツールの使用方法はモバイル デプロイのコンテキストで説明されていますが、モバイル以外のデプロイ用のモデルを最適化するためにも使用できます。

詳しくは、グラフ変換ツールの使用をご覧ください。

サービス入力関数の作成

サービスグラフをエクスポートする場合、重要なステップは、サービス入力関数を定義することです。これは、トレーニング プロセス全体に関連して、次の点で実行できます。

  • トレーニング プロセスの終了時。
  • トレーニングが完了した後の別のプロセスとして。

詳しくは、サービス入力関数をご覧ください。

トレーニング中にサービスグラフを作成する

これは通常、トレーニング プロセスの最後に発生しますが、まだトレーニングとつながっています。

  1. サービス入力関数を定義します。次のサンプルコードは国勢調査のサンプルに含まれています。この場合、サービス入力関数はトレーニング モデルと同じ Python ファイルで定義されます。

    def json_serving_input_fn():
      """Build the serving inputs."""
      inputs = {}
      for feat in INPUT_COLUMNS:
        inputs[feat.name] = tf.placeholder(shape=[None], dtype=feat.dtype)
    
      return tf.estimator.export.ServingInputReceiver(inputs, inputs)

  2. export_savedmodel を使用して Estimator から SavedModel をエクスポートし、モデルへのパスを export_dir_base パラメータとして渡し、サービス入力関数の名前を serving_input_fn パラメータとして渡します。国勢調査の例では、使用される Estimator のタイプは tf.contrib.learn.DNNLinearCombinedClassifier です。

トレーニングとは別にサービスグラフを作成する

すでにモデルをトレーニングしている場合は、再トレーニングをせずに予測を得ることができます。このプロセスは、トレーニング中にサービスグラフを作成する場合と非常によく似ています。主な違いは、トレーニングが終わった後に実行する個別の Python スクリプトでサービスグラフを作成することです。基本的な考え方は、トレーニングで使用されたものと同じ model_dir を使用して Estimator を構築し、次に前述のように export_savedmodel を呼び出すことです。

  1. トレーニング中に定義する方法と同様に、Python スクリプトでサービス入力関数を定義します。

    def json_serving_input_fn():
      """Build the serving inputs."""
      inputs = {}
      for feat in INPUT_COLUMNS:
        inputs[feat.name] = tf.placeholder(shape=[None], dtype=feat.dtype)
    
      return tf.estimator.export.ServingInputReceiver(inputs, inputs)

  2. Estimator を作成するときは、model_dir パラメータをトレーニングで使用したパラメータと同じに設定してください。これにより、以前に保存したモデルのチェックポイントを Estimator に使用できるようになります。

  3. 最後に Estimator を使用して export_savedmodel を呼び出し、モデルへのパスを export_dir_base パラメータとして渡し、サービス入力関数の名前を serving_input_fn パラメータとして渡します。

TensorFlow タグとシグネチャ

TensorFlow 予測グラフを作成するときは、グラフのタグとシグネチャに正しい値を指定する必要があります。TensorFlow が提供するこれらのタグ値とシグネチャ値の定数は、次の目的で使用されます。

  • サービス予測用に SavedModel のグラフを選択するため
  • 予測グラフ用に予測シグネチャを作成していることを示すため

シグネチャは、グラフの入力と出力を定義します。予測グラフのシグネチャを作成するときは、有効なシグネチャ定数build_signature_defmethod_name パラメータとして指定する必要があります。予測には、通常 PREDICT_METHOD_NAME が最適です。

タグを使用して、予測の生成に使用する SavedModel のグラフを指定する必要があります。add_meta_graph_and_variables で、tag_constants.SERVINGtags リストに追加します。

タグとシグネチャに正しい定数を使用して予測グラフを作成する方法のをご覧ください。

モデル バージョンの作成

Cloud ML Engine は、モデルとバージョンのリソースを使用して、トレーニング済みのモデルを編成します。Cloud ML Engine モデルとは、機械学習モデルの複数のバージョンを格納するコンテナに相当します。

Cloud ML Engine にモデルをデプロイするために必要なパラメータの詳細については、予測の概念ページを参照してください。

トレーニング済みのモデルを Cloud ML Engine にデプロイするには、次の作業を行う必要があります。

  • 開始する前に、SavedModel ディレクトリを Cloud Storage バケットにアップロードします。
  • Cloud ML Engine のモデルリソースを作成します。
  • Cloud Engine のバージョン リソースを作成し、SavedModel への Cloud Storage パスを指定します。
  • Cloud ML Engine のサービス アカウントに、SavedModel を含む Cloud Storage バケットに対する「一覧表示」アクセス権と、Cloud Storage バケット内の SavedModel に対する「読み取り」アクセス権があることを確認します。適切な権限がないと、バージョンの作成リクエストは失敗します。詳しくは、ストレージの権限の付与をご覧ください。

Console

  1. Google Cloud Platform Console で Cloud ML Engine ページを開きます。

    GCP Console でモデルを開く

  2. 必要に応じて、新しいバージョンを追加するモデルを作成します。

    1. [モデルを作成] をクリックします。

    2. モデルの名前を、[モデル名] ボックスに入力します。

    3. [作成] をクリックします。

    4. [モデル] ページに戻り、新しいモデルがリストに表示されていることを確認してください。

  3. リストからモデルを選択します。

  4. [モデルの詳細] ページの [バージョン] の下で、[バージョンの作成] をクリックします。

  5. [バージョンの作成] ページ上のフォームに入力します。

    1. [名前] ボックスにモデル名を入力します。

    2. SavedModel への Cloud Storage のパスを、[ソース] ボックスに入力します。

    3. [作成] をクリックします。

    4. [モデルの詳細] ページに戻り、新しいバージョンが [バージョン] リストに表示されていることを確認してください。

gcloud

  1. 必要な場合は、新しいバージョンをデプロイするモデルを作成します。

    gcloud ml-engine models create "model_name"
    
  2. 任意で次のコマンドを入力して Cloud Storage のパスを保存するための環境変数を設定します。

    DEPLOYMENT_SOURCE="bucket_path"
    
  3. バージョンを作成します。

    gcloud ml-engine versions create "version_name"\
        --model "model_name" --origin $DEPLOYMENT_SOURCE
    
  4. 新しいバージョンに関する情報を取得します。

    gcloud ml-engine versions describe "your_version_name" \
        --model "your_model_name"
    

    次のような出力が表示されるはずです。

    createTime: '2016-09-29T16:30:45Z'
    deploymentUri: gs://your_bucket_path
    isDefault: true
    name: projects/project_name/models/model_name/versions/version_name
    

Python

  1. 認証トークンを取得し、Google API クライアントから Cloud ML Engine API を使用するために必要なパッケージをインポートします。

    from oauth2client.client import GoogleCredentials
    from googleapiclient import discovery
    from googleapiclient import errors
    # Time is for waiting until the request finishes.
    import time
    
  2. プロジェクトおよびモデルの変数を、API に必要な形式(projects/project/models/model/versions/version)を使用して設定します。同様に、SavedModel を入れるストレージの場所のために変数を作成します。

    projectID = 'projects/{}'.format('project_name')
    modelName = 'model_name'
    modelID = '{}/models/{}'.format(projectID, modelName)
    versionName = 'version_name'
    versionDescription = 'version_description'
    trainedModelLocation = 'gs://bucket_path'
    
  3. アプリケーションのデフォルトの認証情報を取得し、Cloud ML Engine API の Python 表現を作成します。

    credentials = GoogleCredentials.get_application_default()
    ml = discovery.build('ml', 'v1', credentials=credentials)
    
  4. 必要に応じて、このバージョンが属するモデルを作成します。

    # Create a dictionary with the fields from the request body.
    requestDict = {'name': modelName,
        'description': 'Another model for testing.'}
    
    # Create a request to call projects.models.create.
    request = ml.projects().models().create(parent=projectID,
                                body=requestDict)
    
    # Make the call.
    try:
        response = request.execute()
    
        # Any additional code on success goes here (logging, etc.)
    
    except errors.HttpError as err:
        # Something went wrong, print out some information.
        print('There was an error creating the model.' +
            ' Check the details:')
        print(err._get_reason())
    
        # Clear the response for next time.
        response = None
    
  5. バージョン作成リクエストのエントリによって、辞書を作成します。

    requestDict = {'name': versionName,
        'description': versionDescription,
        'deploymentUri': trainedModelLocation}
    
  6. リクエストを作成し、サービスコールを行ってバージョンを作成します。

    # Create a request to call projects.models.versions.create
    request = ml.projects().models().versions().create(parent=modelID,
                  body=requestDict)
    
    # Make the call.
    try:
        response = request.execute()
    
        # Get the operation name.
        operationID = response['name']
    
        # Any additional code on success goes here (logging, etc.)
    
    except errors.HttpError as err:
        # Something went wrong, print out some information.
        print('There was an error creating the version.' +
              ' Check the details:')
        print(err._get_reason())
    
        # Handle the exception as makes sense for your application.
    
  7. 作成オペレーションのステータスをモニタリングします。

    done = False
    request = ml.projects().operations().get(name=operationID)
    
    while not done:
        response = None
    
        # Wait for 300 milliseconds.
        time.sleep(0.3)
    
    # Make the next call.
    try:
        response = request.execute()
    
        # Check for finish.
        done = response.get('done', False)
    
    except errors.HttpError as err:
        # Something went wrong, print out some information.
        print('There was an error getting the operation.' +
              'Check the details:')
        print(err._get_reason())
        done = True
    

    この例では、バージョンの作成が完了するまで待ちますが、アプリケーションの処理をブロックしたくない場合もあるでしょう。

次のステップ

このページは役立ちましたか?評価をお願いいたします。

フィードバックを送信...

Cloud Machine Learning Engine(Cloud ML Engine)