次の方法で共有


Azure Machine Learning にバッチ デプロイで MLflow モデルをデプロイする

適用対象:Azure CLI ml extension v2 (現行)Python SDK azure-ai-ml v2 (現行)

この記事では、MLflow モデルを Azure Machine Learning にデプロイして、バッチ エンドポイントを使ってバッチ推論を行う方法について説明します。 MLflow モデルをバッチ エンドポイントにデプロイするとき、Azure Machine Learning によって次のタスクが実行されます。

  • Machine Learning バッチ ジョブを実行するために必要な依存関係を含む MLflow ベース イメージまたはキュレーション環境を提供します。
  • スコアリング スクリプトを使って、並列化を使ったデータの処理に使用できるバッチ ジョブ パイプラインを自動的に作成できます。

サポートされている入力ファイルの種類と MLflow モデルの動作について詳しくは、「バッチ推論にデプロイするときの考慮事項」をご覧ください。

前提条件

  • Azure サブスクリプション。 Azure サブスクリプションをお持ちでない場合は、開始する前に無料アカウントを作成してください。 無料版または有料版の Azure Machine Learning をお試しください。

  • Azure Machine Learning ワークスペース。 ワークスペースを作成するには、「Azure Machine Learning ワークスペースの管理」を参照してください。

  • Machine Learning ワークスペースでの以下のアクセス許可があることを確認してください。

    • バッチ エンドポイントとバッチ デプロイを作成または管理する: 所有者または共同作成者のロール、あるいは Microsoft.MachineLearningServices/workspaces/batchEndpoints/* を許可するカスタム役割を使用します。
    • ワークスペース リソース グループ内での Azure Resource Manager デプロイの作成: 所有者、共同作成者、またはワークスペースがデプロイされるリソース グループ での Microsoft.Resources/deployments/write を許可するカスタム ロールを使用します。
  • Machine Learning を使用するには、以下のソフトウェアをインストールします。

    次のコマンドを実行して、Azure CLIml という Azure Machine Learning 用の拡張機能をインストールします。

    az extension add -n ml
    

    バッチ エンドポイントのパイプライン コンポーネント デプロイは、Azure CLI 用拡張機能 ml のバージョン 2.7 で導入されました。 az extension update --name ml コマンドを使用して、最新バージョンを取得します。


ワークスペースに接続する

ワークスペースは、Machine Learning の最上位のリソースです。 これは Machine Learning を使用する際に作成するすべての成果物を操作するための一元的な場所を提供します。 このセクションでは、デプロイ タスクを実行するワークスペースに接続します。

次のコマンドで、サブスクリプション ID、ワークスペース、場所、リソース グループの値を入力します。

az account set --subscription <subscription>
az configure --defaults workspace=<workspace> group=<resource-group> location=<location>

例を調べる

この記事の例は、バッチ予測を実行するために、バッチ エンドポイントに MLflow モデルをデプロイする方法を示しています。 MLflow モデルは、UCI Heart Disease Data Set をベースにしています。 このデータベースには 76 個の属性が含まれていますが、この例では 14 個のサブセットのみを使用します。 このモデルは、0 (存在しない) から 1 (存在する) までの整数値を使用して、患者の心臓病の存在を予測しようと試みるものです。

モデルは、XGBBoost 分類器を使用してトレーニングされます。 必要な前処理はすべて scikit-learn パイプラインとしてパッケージ化されているため、このモデルは生データから予測までを行うエンドツーエンドのパイプラインになっています。

この記事の例は、azureml-examples リポジトリに含まれているコード サンプルを基にしています。 YAML などのファイルをコピーして貼り付けることなくコマンドをローカルで実行するには、最初にリポジトリを複製してから、ディレクトリをそのフォルダーに変更します。

git clone https://github.com/Azure/azureml-examples --depth 1
cd azureml-examples/cli

この例のファイルは、次のフォルダーにあります。

cd endpoints/batch/deploy-models/heart-classifier-mlflow

Jupyter ノートブックで経過をたどる

公開されている Jupyter Notebook を使用して、このサンプルに従って実行できます。 クローンされたリポジトリで、mlflow-for-batch-tabular.ipynb ノートブックを開きます。

MLflow モデルをデプロイする

このセクションでは、新しいデータに対してバッチ推論を実行できるように、MLflow モデルをバッチ エンドポイントにデプロイします。 デプロイを進める前に、モデルが登録され、ワークスペースに使用可能なコンピューティング クラスターがあることを確認する必要があります。

モデルを登録する

バッチ エンドポイントでデプロイできるのは登録済みのモデルのみです。 この記事では、リポジトリ内のモデルのローカル コピーを使用します。 その結果、モデルをワークスペース内のレジストリに発行するだけで済みます。

Note

デプロイするモデルが既に登録されている場合は、「コンピューティング クラスターを作成する」セクションに進むことができます。

次のコマンドを実行して、モデルを登録します。

MODEL_NAME='heart-classifier-mlflow'
az ml model create --name $MODEL_NAME --type "mlflow_model" --path "model"

コンピューティング クラスターを作成する

バッチ デプロイが何らかの使用可能なインフラストラクチャ ("コンピューティング") 上で実行できることを確認する必要があります。 バッチ デプロイは、ワークスペースに既に存在する Machine Learning コンピューティング上で実行できます。 複数のバッチ デプロイが同じコンピューティング インフラストラクチャを共有できます。

この記事では、cpu-cluster という名前の Machine Learning コンピューティング クラスター上で作業します。 次の例では、ワークスペースにコンピューティングが存在するかどうかを確認し、存在しない場合は、新しいコンピューティングを作成します。

次のようにコンピューティング クラスターを作成します。

az ml compute create -n batch-cluster --type amlcompute --min-instances 0 --max-instances 5

バッチ エンドポイントを作成する

エンドポイントを作成するには、名前と説明が必要です。 エンドポイント名は、エンドポイントに関連付けられる URI に含まれるため、Azure リージョン内で一意である必要があります。 たとえば、WestUS2 リージョンに存在できる mybatchendpoint という名前のバッチ エンドポイントは 1 つだけです。

  1. 後で簡単に参照できるように、エンドポイントの名前を変数に配置します。

    次のコマンドを実行します。

    ENDPOINT_NAME="heart-classifier"
    
  2. エンドポイントを作成します。

    1. 新しいエンドポイントを作成するには、次のコードのような YAML 構成を作成します。

      endpoint.yml

      $schema: https://azuremlschemas.azureedge.net/latest/batchEndpoint.schema.json
      name: heart-classifier-batch
      description: A heart condition classifier for batch inference
      auth_mode: aad_token
      
    2. 次のコマンドを使ってエンドポイントを作成します。

      az ml batch-endpoint create -n $ENDPOINT_NAME -f endpoint.yml
      

バッチ デプロイを作成する

MLflow モデルでは、デプロイの作成時に環境またはスコアリング スクリプトを指定する必要はありません。 環境またはスコアリング スクリプトは自動的に作成されます。 ただし、デプロイによる推論方法をカスタマイズする場合は、環境またはスコアリング スクリプトを指定できます。

  1. 作成されたエンドポイントの下に新しいデプロイを作成するには、次のコードに示すような YAML 構成を作成します。 追加のプロパティについては、完全なバッチ エンドポイント YAML スキーマを確認してください。

    deployment-simple/deployment.yml

    $schema: https://azuremlschemas.azureedge.net/latest/modelBatchDeployment.schema.json
    endpoint_name: heart-classifier-batch
    name: classifier-xgboost-mlflow
    description: A heart condition classifier based on XGBoost
    type: model
    model: azureml:heart-classifier-mlflow@latest
    compute: azureml:batch-cluster
    resources:
      instance_count: 2
    settings:
      max_concurrency_per_instance: 2
      mini_batch_size: 2
      output_action: append_row
      output_file_name: predictions.csv
      retry_settings:
        max_retries: 3
        timeout: 300
      error_threshold: -1
      logging_level: info
    
  2. 次のコマンドを使ってデプロイを作成します。

    az ml batch-deployment create --file deployment-simple/deployment.yml --endpoint-name $ENDPOINT_NAME --set-default
    

重要

モデルが 1 つのバッチで推論を実行するのにかかる時間に基づいて、デプロイでの timeout 値を構成します。 バッチ サイズが大きいほど、timeout 値は長くなります。 mini_batch_size 値は、サンプルの数ではなく、バッチ内のファイルの数を示すことに注意してください。 表形式データを処理するときは、各ファイルに複数の行が含まれている場合があり、バッチ エンドポイントが各ファイルを処理するのにかかる時間が長くなります。 このような場合は、タイムアウト エラーを回避するために、大きい timeout 値を使用します。

エンドポイントを呼び出す

エンドポイント内で特定のデプロイを呼び出すこともできますが、通常はエンドポイント自体を呼び出し、使用するデプロイはエンドポイントで決定されるようにします。 この種類のデプロイは、"既定" のデプロイと呼ばれます。 この方法では、既定のデプロイを変更できます。これにより、エンドポイントを呼び出すユーザーとのコントラクトを変更することなく、デプロイを提供するモデルを変更できます。

既定のデプロイを更新するには、次の手順に従います。

DEPLOYMENT_NAME="classifier-xgboost-mlflow"
az ml batch-endpoint update --name $ENDPOINT_NAME --set defaults.deployment_name=$DEPLOYMENT_NAME

これで、バッチ エンドポイントを使用する準備ができました。

展開をテスト

エンドポイントをテストするには、このリポジトリ内にあり、このモデルに使用できるラベルのないデータのサンプルを使用します。 バッチ エンドポイントは、クラウド内にあり、Machine Learning ワークスペースからアクセスできるデータのみを処理できます。 この例では、サンプルを Machine Learning データ ストアにアップロードします。 スコアリングのためにエンドポイントを呼び出すのに使用できるデータ資産を作成します。 バッチ エンドポイントは、さまざまな場所に配置されている可能性があるデータを受け入れることに注意してください。

  1. 最初に、データ資産を作成します。 そのデータ資産は、バッチ エンドポイントを使って並列処理する複数の CSV ファイルを含む 1 つのフォルダーで構成されています。 データがデータ資産として既に登録されている場合、または別の入力の種類を使う場合、この手順はスキップできます。

    1. YAML でデータ資産定義を作成します。

      heart-dataset-unlabeled.yml

      $schema: https://azuremlschemas.azureedge.net/latest/data.schema.json
      name: heart-dataset-unlabeled
      description: An unlabeled dataset for heart classification.
      type: uri_folder
      path: data
      
    2. データ資産を作成します。

      az ml data create -f heart-dataset-unlabeled.yml
      
  2. データをアップロードしたら、エンドポイントを呼び出します。

    ヒント

    次のコマンドでは、デプロイ名が invoke 操作で示されていないことに注意してください。 エンドポイントにはデプロイが 1 つしかないため、エンドポイントによってジョブが既定のデプロイに自動的にルーティングされます。 引数またはパラメーター deployment_name を指定することで、特定のデプロイをターゲットにできます。

    次のコマンドを実行します。

    JOB_NAME = $(az ml batch-endpoint invoke --name $ENDPOINT_NAME --input azureml:heart-dataset-unlabeled@latest --query name -o tsv)
    

    Note

    ユーティリティ jq は、すべてのインストールでインストールされるとは限りません。 インストール手順については、jq のダウンロードのページを参照してください。

  3. コマンドが戻ると、すぐにバッチ ジョブが開始されます。 ジョブの状態は、完了するまで監視できます。

    次のコマンドを実行します。

    az ml job show -n $JOB_NAME --web
    

出力を分析する

デプロイ構成の指定に従い、出力予測が predictions.csv ファイル内に生成されます。 このジョブにより、このファイルが配置されている場所に score という名前の出力が生成されます。 バッチ ジョブごとに 1 つのファイルのみが生成されます。

ファイルは次のような構造です。

  • モデルに送信されたデータ ポイントごとに 1 行。 表形式データの場合、ファイル predictions.csv には、処理された各ファイルに存在する行ごとに 1 行が含まれています。 他のデータ型 (画像、オーディオ、テキスト) の場合は、処理されたファイルごとに 1 行が含まれます。

  • このファイルには次の列が (指定した順番どおりに) 含まれています。

    • row (省略可能): 入力データ ファイル内の対応する行インデックス。 この列は、入力データが表形式の場合にのみ適用されます。 予測は、入力ファイルの出現順と同じ順序で返されます。 行番号を頼りに、対応する予測を照合することができます。

    • prediction: 入力データに関連付けられた予測。 この値は、モデルの predict(). 関数で提供されたとおりに "そのまま" の形で返されます。

    • file_name: データが読み取られたファイル名を表す名前。 表形式データの場合、各入力データにどの予測が属するかを決めるためにこのフィールドを使います。

ジョブ名を使って、そのジョブの結果をダウンロードできます。

予測をダウンロードするには、次のコマンドを使用します。

az ml job download --name $JOB_NAME --output-name score --download-path ./

ファイルをダウンロードしたら、任意の編集ツールを使用してファイルを開くことができます。 次の例では、Pandas データフレームを使って予測を読み込みます。

import pandas as pd

score = pd.read_csv(
    "named-outputs/score/predictions.csv", names=["row", "prediction", "file"]
)

出力には、テーブルが表示されます。

予測 ファイル
0 0 heart-unlabeled-0.csv
1 1 heart-unlabeled-0.csv
2 0 heart-unlabeled-0.csv
... ... ...
307 0 heart-unlabeled-3.csv

ヒント

この例では、入力データに CSV 形式の表形式データが含まれていることに注意してください。 入力ファイルは 4 種類あります: heart-unlabeled-0.csvheart-unlabeled-1.csvheart-unlabeled-2.csvheart-unlabeled-3.csv です。

バッチ推論に関する考慮事項を確認する

Machine Learning では、スコアリング スクリプトを示さなくても、バッチ エンドポイントに MLflow モデルをデプロイできます。 この方法は、バッチ処理と同様に大量のデータの処理を必要とするモデルをデプロイするのに便利な方法です。 Machine Learning は、MLflow モデル仕様の情報を使って推論プロセスを調整します。

worker での作業の分散を調べる

バッチ エンドポイントは、構造化データと非構造化データの両方について、ファイル レベルで作業を分散させます。 その結果、この機能では、URI ファイルURI フォルダーのみがサポートされます。 各 worker は一度に Mini batch size 個のファイルのバッチを処理します。 表形式データの場合、バッチ エンドポイントによって作業が分散されるとき、各ファイル内の行数は考慮されません。

警告

入れ子になったフォルダー構造は、推論中に探索されません。 フォルダーを使ってデータをパーティション分割する場合は、先に進む前に構造をフラット化してください。

バッチ デプロイにより、1 ファイルにつき 1 回、MLflow モデルの predict 関数が呼び出されます。 複数行を含む CSV ファイルの場合、この操作は基となるコンピューティングのメモリを圧迫する可能性があります。 この動作により、大規模言語モデルのようなコストがかかるモデルの場合は特に、モデルによる 1 つのファイルのスコア付けにかかる時間が長くなる可能性があります。 メモリ不足例外やログのタイムアウト エントリが複数発生する場合は、より少ない行数のファイルにデータを分割するか、モデル スコアリング スクリプト内で行レベルのバッチ処理を実装することを検討してください。

ファイルの種類のサポートを確認する

バッチ推論で環境またはスコアリングのスクリプトを使わずに MLflow モデルをデプロイする場合、次のデータ型がサポートされています。 別のファイルの種類を処理したり、推論を異なる方法で実行したりするには、スコアリング スクリプトを使用して MLflow モデルのデプロイをカスタマイズしてデプロイを作成できます。

[ファイル拡張子] モデル入力として返される型 シグネチャの要件
.csv.parquet.pqt pd.DataFrame ColSpec 指定しない場合、列の型指定は強制されません。
.png.jpg.jpeg.tiff.bmp.gif np.ndarray TensorSpec 入力はテンソルのシェイプと一致するように再シェイプされます (使用できる場合)。 使用できるシグネチャがない場合、型 np.uint8 のテンソルが推論されます。 詳細については、「画像を処理する MLflow モデルに関する考慮事項」を参照してください。

警告

入力データにサポートされていないファイルがあると、ジョブが失敗する可能性があります。 その場合、次のようなエラーが表示されます: ERROR:azureml:Error processing input file: '/mnt/batch/tasks/.../a-given-file.avro'. File type 'avro' is not supported. (ERROR:azureml: 入力ファイルの処理エラー: '/mnt/batch/tasks/.../a-given-file.avro'。ファイルの種類 'avro' はサポートされていません。)

MLflow モデルに対するシグネチャの適用について理解する

入力のデータ型はバッチ デプロイ ジョブによって適用されますが、データの読み取りには、使用できる MLflow モデルのシグネチャが使われます。 その結果、データ入力はモデル シグネチャに示された型に準拠します。 データを想定どおりに解析できない場合、ジョブは次のようなエラーで失敗します: ERROR:azureml:Error processing input file: '/mnt/batch/tasks/.../a-given-file.csv'. Exception: invalid literal for int() with base 10: 'value'. (ERROR:azureml: 入力ファイルの処理エラー: '/mnt/batch/tasks/.../a-given-file.csv'。例外: ベース 10 の int() の無効なリテラル: 'value'")。

ヒント

MLflow モデルのシグネチャは省略可能ですが、使用を強くお勧めします。 これらは、データ互換性の問題を早期に検出するための便利な方法を提供します。 シグネチャを使ってモデルのログを記録する方法の詳細については、「カスタムのシグネチャ、環境、またはサンプルを使ったモデルのログ記録」を参照してください。

MLflow モデルに関連付けられた MLmodel ファイルを開くことで、モデルのシグネチャを調べることができます。 MLflow におけるシグネチャの機能に関する詳細については、「MLflow のシグネチャ」を参照してください。

フレーバーのサポートを調べる

バッチ デプロイは、フレーバーが pyfunc の MLflow モデルのデプロイのみをサポートします。 別のフレーバーをデプロイするには、「スコアリング スクリプトを使用してモデルのデプロイをカスタマイズする」を参照してください。

スコアリング スクリプトを使用してモデル デプロイをカスタマイズする

デプロイ定義にスコアリング スクリプトを指定することなく、MLflow モデルをバッチ エンドポイントにデプロイできます。 ただし、推論の実行をカスタマイズするために、このファイル (一般的に "バッチ ドライバー" と呼ばれます) を指定することもできます。

通常、このワークフローは次のシナリオで選択します。

  • MLflow デプロイのバッチ デプロイではサポートされていないファイルの種類を処理する。
  • 特定のフレーバーを使用して mlflow.<flavor>.load() 関数で読み込むなど、モデルの実行方法をカスタマイズする。
  • モデル自体で完了していない場合に、スコアリング ルーチンで前処理または後処理を完了する。
  • 画像を表すテンソル グラフなど、表形式のデータで適切に表示されないモデルの表示を調整する。
  • メモリの制約により各ファイルを一度に処理できないため、モデルがチャンク単位でデータを読み取れるようにする。

重要

MLflow のモデル デプロイに対してスコアリング スクリプトを示すには、デプロイが実行される環境も指定する必要があります。

スコアリング スクリプトを使用する

カスタム スコアリング スクリプトを使用して MLflow モデルをデプロイするには、次の手順に従います。

  1. MLflow モデルが置かれているフォルダーを特定します。

    1. Azure Machine Learning ポータルで、[モデル] に移動します。

    2. デプロイするモデルを選択し、[成果物] タブを選択します。

    3. 表示されたフォルダーを書き留めます。 モデルの登録時にこのフォルダーが示されました。

      モデル成果物が配置されているフォルダーを示すスクリーンショット。

  2. スコアリング スクリプトを作成します。 前のフォルダー名 modelinit() 関数にどのように含まれているかに注目してください。

    deployment-custom/code/batch_driver.py

    # Copyright (c) Microsoft. All rights reserved.
    # Licensed under the MIT license.
    
    import os
    import glob
    import mlflow
    import pandas as pd
    import logging
    
    
    def init():
        global model
        global model_input_types
        global model_output_names
    
        # AZUREML_MODEL_DIR is an environment variable created during deployment
        # It is the path to the model folder
        # Please provide your model's folder name if there's one
        model_path = glob.glob(os.environ["AZUREML_MODEL_DIR"] + "/*/")[0]
    
        # Load the model, it's input types and output names
        model = mlflow.pyfunc.load(model_path)
        if model.metadata and model.metadata.signature:
            if model.metadata.signature.inputs:
                model_input_types = dict(
                    zip(
                        model.metadata.signature.inputs.input_names(),
                        model.metadata.signature.inputs.pandas_types(),
                    )
                )
            if model.metadata.signature.outputs:
                if model.metadata.signature.outputs.has_input_names():
                    model_output_names = model.metadata.signature.outputs.input_names()
                elif len(model.metadata.signature.outputs.input_names()) == 1:
                    model_output_names = ["prediction"]
        else:
            logging.warning(
                "Model doesn't contain a signature. Input data types won't be enforced."
            )
    
    
    def run(mini_batch):
        print(f"run method start: {__file__}, run({len(mini_batch)} files)")
    
        data = pd.concat(
            map(
                lambda fp: pd.read_csv(fp).assign(filename=os.path.basename(fp)), mini_batch
            )
        )
    
        if model_input_types:
            data = data.astype(model_input_types)
    
        # Predict over the input data, minus the column filename which is not part of the model.
        pred = model.predict(data.drop("filename", axis=1))
    
        if pred is not pd.DataFrame:
            if not model_output_names:
                model_output_names = ["pred_col" + str(i) for i in range(pred.shape[1])]
            pred = pd.DataFrame(pred, columns=model_output_names)
    
        return pd.concat([data, pred], axis=1)
    
  3. スコアリング スクリプトを実行できる環境を作成します。 この例のモデルは MLflow であるため、conda の要件もモデル パッケージで指定されています。 MLflow モデルと含まれるファイルの詳細については、「MLmodel 形式」を参照してください。

    この手順では、ファイルの conda 依存関係を使って環境を構築します。 バッチ デプロイに必要な azureml-core パッケージも含める必要があります。

    ヒント

    モデルが既にモデル レジストリに登録されている場合は、モデルに関連付けられている conda.yml ファイルをダウンロードしてコピーできます。 このファイルは、Azure Machine Learning スタジオ[モデル]>一覧からモデルを選択>[成果物] にあります。 ルート フォルダーで、conda.yml ファイルを選択し、[ダウンロード] を選択するか、その内容をコピーします。

    重要

    この例では、 /heart-classifier-mlflow/environment/conda.yamlで指定された conda 環境を使用します。 このファイルは、元の MLflow conda 依存関係ファイルを組み合わせ、azureml-core パッケージを追加することによって作成されました。 モデルから直接 conda.yml ファイルを使用することはできません。

    環境定義は、匿名環境としてデプロイ定義自体に含まれます。 デプロイで次の行を確認できます。

    environment:
      name: batch-mlflow-xgboost
      image: mcr.microsoft.com/azureml/openmpi4.1.0-ubuntu20.04:latest
      conda_file: environment/conda.yaml
    
  4. デプロイを構成します。

    作成されたエンドポイントの下に新しいデプロイを作成するには、次のコード スニペットに示すような YAML 構成を作成します。 追加のプロパティについては、完全なバッチ エンドポイント YAML スキーマを確認してください。

    deployment-custom/deployment.yml

    $schema: https://azuremlschemas.azureedge.net/latest/modelBatchDeployment.schema.json
    endpoint_name: heart-classifier-batch
    name: classifier-xgboost-custom
    description: A heart condition classifier based on XGBoost
    type: model
    model: azureml:heart-classifier-mlflow@latest
    environment:
      name: batch-mlflow-xgboost
      image: mcr.microsoft.com/azureml/openmpi4.1.0-ubuntu20.04:latest
      conda_file: environment/conda.yaml
    code_configuration:
      code: code
      scoring_script: batch_driver.py
    compute: azureml:batch-cluster
    resources:
      instance_count: 2
    settings:
      max_concurrency_per_instance: 2
      mini_batch_size: 2
      output_action: append_row
      output_file_name: predictions.csv
      retry_settings:
        max_retries: 3
        timeout: 300
      error_threshold: -1
      logging_level: info
    
  5. デプロイを作成します。

    次のコードを実行します。

    az ml batch-deployment create --file deployment-custom/deployment.yml --endpoint-name $ENDPOINT_NAME
    

これで、バッチ エンドポイントを使用する準備ができました。

リソースをクリーンアップする

演習を完了したら、不要になったリソースを削除します。

次のコードを実行して、バッチ エンドポイントおよび基礎となるすべてのデプロイを削除します。

az ml batch-endpoint delete --name $ENDPOINT_NAME --yes

このコマンドでバッチ スコアリング ジョブは削除されません。