次の方法で共有


Azure Machine Learning を使用して大規模な TensorFlow モデルをトレーニングする

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

この記事では、Azure Machine Learning Python SDK v2 を使用して、大規模な TensorFlow トレーニング スクリプトを実行する方法について説明します。

この記事のコード例では、ディープ ニューラル ネットワーク (DNN) を使用して、手書き数字を分類するために TensorFlow モデルをトレーニングし、モデルを登録して、オンライン エンドポイントにデプロイします。

TensorFlow モデルを開発する場合でも、既存のモデルをクラウドに持ち込む場合でも、Azure Machine Learning のエラスティック クラウド コンピューティング リソースを使用して、オープンソースのトレーニング ジョブをスケールアウトできます。 Azure Machine Learning を使用して、運用レベルのモデルをビルド、デプロイ、バージョン管理、および監視することができます。

前提条件

この記事を利用するには、次の操作を行う必要があります。

  • Azure サブスクリプションにアクセスします。 アカウントがまだない場合は、無料のアカウントを作成してください。
  • この記事のコードは、Azure Machine Learning コンピューティング インスタンスまたは独自の Jupyter Notebook のいずれかで実行します。
    • Azure Machine Learning コンピューティング インスタンス - ダウンロードやインストールは必要ありません
      • 作業を開始するために必要なリソースを作成する」というチュートリアルを完了して、SDK とサンプル リポジトリが事前に読み込まれた専用のノートブック サーバーを作成します。
      • ノートブック サーバー上のディープ ラーニングの samples フォルダーで、v2 > sdk > python > jobs > single-step > tensorflow > train-hyperparameter-tune-deploy-with-tensorflow の順にディレクトリを移動して、完成した展開済みノートブックを見つけます。
    • Jupyter Notebook サーバー
  • 次のファイルをダウンロードします。

このガイドの完成した Jupyter Notebook バージョンは、GitHub サンプル ページにもあります。

この記事のコードを実行して GPU クラスターを作成する前に、ワークスペースのクォータの引き上げを要求する必要があります。

ジョブをセットアップする

このセクションでは、必要な Python パッケージを読み込み、ワークスペースに接続し、コマンド ジョブを実行するコンピューティング リソースを作成し、ジョブを実行する環境を作成することで、トレーニング用のジョブを設定します。

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

まず、Azure Machine Learning ワークスペースに接続する必要があります。 Azure Machine Learning ワークスペースは、サービス用の最上位のリソースです。 Azure Machine Learning を使用するときに作成する、すべての成果物を操作するための一元的な場所が提供されます。

ここでは、DefaultAzureCredential を使ってワークスペースへのアクセスを取得しています。 この資格情報を使うと、ほとんどの Azure SDK 認証シナリオに対応できます。

DefaultAzureCredential でうまくいかない場合は、他に使用可能な資格情報について、azure-identity reference documentation または Set up authentication を参照してください。

# Handle to the workspace
from azure.ai.ml import MLClient

# Authentication package
from azure.identity import DefaultAzureCredential

credential = DefaultAzureCredential()

ブラウザーを使用してサインインと認証を行う場合は、次のコードのコメントを解除し、代わりに使用する必要があります。

# Handle to the workspace
# from azure.ai.ml import MLClient

# Authentication package
# from azure.identity import InteractiveBrowserCredential
# credential = InteractiveBrowserCredential()

次に、サブスクリプション ID、リソース グループ名、ワークスペース名を指定して、ワークスペースへのハンドルを取得します。 これらのパラメーターを見つけるには、次の手順を実行します。

  1. Azure Machine Learning スタジオ ツール バーの右上隅にあるワークスペース名を探します。
  2. ワークスペース名を選択して、リソース グループとサブスクリプション ID を表示します。
  3. リソース グループとサブスクリプション ID の値をコードにコピーします。
# Get a handle to the workspace
ml_client = MLClient(
    credential=credential,
    subscription_id="<SUBSCRIPTION_ID>",
    resource_group_name="<RESOURCE_GROUP>",
    workspace_name="<AML_WORKSPACE_NAME>",
)

このスクリプトの実行結果は、他のリソースとジョブを管理するために使用するワークスペース ハンドルになります。

Note

  • MLClient を作成しても、クライアントはワークスペースに接続されません。 クライアントの初期化は遅延型なので、初めて呼び出す必要が生じるときまで待機します。 この記事では、これはコンピューティングの作成時に発生します。

コンピューティング リソースを作成する

Azure Machine Learning には、ジョブを実行するためのコンピューティング リソースが必要です。 このリソースには、Linux または Windows OS の単一または複数ノードのマシン、または Spark などの特定のコンピューティング ファブリックを指定できます。

次のスクリプト例では、Linux compute cluster をプロビジョニングします。 VM のサイズと価格の完全な一覧については、Azure Machine Learning pricing ページを参照してください。 この例には GPU クラスターが必要なので、STANDARD_NC6 モデルを選択して Azure Machine Learning コンピューティングを作成してみましょう。

from azure.ai.ml.entities import AmlCompute

gpu_compute_target = "gpu-cluster"

try:
    # let's see if the compute target already exists
    gpu_cluster = ml_client.compute.get(gpu_compute_target)
    print(
        f"You already have a cluster named {gpu_compute_target}, we'll reuse it as is."
    )

except Exception:
    print("Creating a new gpu compute target...")

    # Let's create the Azure ML compute object with the intended parameters
    gpu_cluster = AmlCompute(
        # Name assigned to the compute cluster
        name="gpu-cluster",
        # Azure ML Compute is the on-demand VM service
        type="amlcompute",
        # VM Family
        size="STANDARD_NC6s_v3",
        # Minimum running nodes when there is no job running
        min_instances=0,
        # Nodes in cluster
        max_instances=4,
        # How many seconds will the node running after the job termination
        idle_time_before_scale_down=180,
        # Dedicated or LowPriority. The latter is cheaper but there is a chance of job termination
        tier="Dedicated",
    )

    # Now, we pass the object to MLClient's create_or_update method
    gpu_cluster = ml_client.begin_create_or_update(gpu_cluster).result()

print(
    f"AMLCompute with name {gpu_cluster.name} is created, the compute size is {gpu_cluster.size}"
)

ジョブ環境を作成する

Azure Machine Learning ジョブを実行するには、環境が必要です。 Azure Machine Learning 環境では、コンピューティング リソースで機械学習トレーニング スクリプトを実行するために必要な依存関係 (ソフトウェア ランタイムやライブラリなど) がカプセル化されます。 この環境は、ローカル コンピューター上の Python 環境に似ています。

Azure Machine Learning を使用すると、キュレーションされた (または既製の) 環境 (一般的なトレーニングと推論のシナリオに役立つ) を使用することも、Docker イメージまたは Conda 構成を使用してカスタム環境を作成することもできます。

この記事では、キュレーションされた Azure Machine Learning 環境 AzureML-tensorflow-2.7-ubuntu20.04-py38-cuda11-gpu を再利用します。 @latest ディレクティブを使って、この環境の最新バージョンを使用します。

curated_env_name = "AzureML-tensorflow-2.12-cuda11@latest"

トレーニング ジョブを構成して送信する

このセクションでは、まずトレーニング用のデータを紹介します。 次に、提供したトレーニング スクリプトを使用して、トレーニング ジョブを実行する方法について説明します。 トレーニング スクリプトを実行するためのコマンドを構成して、トレーニング ジョブをビルドする方法について説明します。 次に、トレーニング ジョブを送信して Azure Machine Learning で実行します。

トレーニング データを取得する

修正された国立標準技術研究所 (MNIST) データベースの手書き数字のデータを使用します。 このデータは、Yan LeCun の Web サイトから取得され、Azure ストレージ アカウントに格納されます。

web_path = "wasbs://datasets@azuremlexamples.blob.core.windows.net/mnist/"

MNIST データセットの詳細については、Yan LeCun の Web サイトを参照してください。

トレーニング スクリプトを準備する

この記事では、トレーニング スクリプト tf_mnist.py を提供しました。 実際には、コードを変更しなくても、あらゆるカスタム トレーニング スクリプトをそのまま Azure Machine Learning で実行できるはずです。

提供されているトレーニング スクリプトは次の処理を実行します。

  • データの前処理を処理し、データをテスト データとトレーニング データに分割する
  • データを使用してモデルをトレーニングする
  • 出力モデルを返す。

パイプラインの実行中は、MLFlow を使用してパラメーターとメトリックをログに記録します。 MLFlow 追跡を有効にする方法については、「MLflow を使用して ML の実験とモデルを追跡する」を参照してください。

トレーニング スクリプト tf_mnist.pyでは、単純なディープ ニューラル ネットワーク (DNN) を作成します。 この DNN には次の情報があります。

  • 28 * 28 = 784 ニューロンを持つ入力層。 各ニューロンは画像ピクセルを表します。
  • 2 つの隠れ層。 最初の隠れ層には 300 個のニューロンがあり、2 番目の隠れ層には 100 個のニューロンがあります。
  • 10 ニューロンを持つ出力層。 各ニューロンは、0 から 9 の対象となるラベルを表します。

入力層に 784 個のニューロン、2 つの隠れ層、および出力層に 10 個のニューロンを有するディープ ニューラル ネットワークを示す図。

トレーニング ジョブを作成する

ジョブの実行に必要なすべての資産が揃ったので、次は Azure Machine Learning Python SDK v2 を使ってジョブを作成します。 この例では、command を作成します。

Azure Machine Learning command は、クラウドでトレーニング コードを実行するために必要なすべての詳細を指定するリソースです。 これらの詳細には、入力と出力、使用するハードウェアの種類、インストールするソフトウェア、コードの実行方法が含まれます。 command には、1 つのコマンドを実行するための情報が含まれています。

コマンドを構成する

汎用 command を使用してトレーニング スクリプトを実行し、目的のタスクを実行します。 トレーニング ジョブの構成の詳細を指定する Command オブジェクトを作成します。

from azure.ai.ml import command
from azure.ai.ml import UserIdentityConfiguration
from azure.ai.ml import Input

web_path = "wasbs://datasets@azuremlexamples.blob.core.windows.net/mnist/"

job = command(
    inputs=dict(
        data_folder=Input(type="uri_folder", path=web_path),
        batch_size=64,
        first_layer_neurons=256,
        second_layer_neurons=128,
        learning_rate=0.01,
    ),
    compute=gpu_compute_target,
    environment=curated_env_name,
    code="./src/",
    command="python tf_mnist.py --data-folder ${{inputs.data_folder}} --batch-size ${{inputs.batch_size}} --first-layer-neurons ${{inputs.first_layer_neurons}} --second-layer-neurons ${{inputs.second_layer_neurons}} --learning-rate ${{inputs.learning_rate}}",
    experiment_name="tf-dnn-image-classify",
    display_name="tensorflow-classify-mnist-digit-images-with-dnn",
)
  • このコマンドの入力には、データの場所、バッチ サイズ、1 番目と 2 番目のレイヤーのニューロンの数、学習率が含まれます。 Web パスが入力として直接渡されていることに注意してください。

  • パラメーター値については次のとおりです。

    • このコマンドを実行するために作成したコンピューティング クラスター gpu_compute_target = "gpu-cluster" を指定する
    • 前に宣言したキュレーションされた環境 curated_env_name を指定する
    • コマンド ライン アクション自体を構成する。この場合、コマンドは python tf_mnist.py です。 コマンドの入力と出力には ${{ ... }} 表記法を使用してアクセスできます。
    • 表示名や実験名などのメタデータを構成する。ここで、実験は特定のプロジェクトで行われるすべてのイテレーションのコンテナーです。 同じ実験名で送信されたすべてのジョブは、Azure Machine Learning スタジオ上ではすべて隣り合わせに表示されます。
  • この例では、UserIdentity を使用してコマンドを実行します。 ユーザー ID を使用すると、コマンドは ID を使用してジョブを実行し、BLOB からデータにアクセスすることを意味します。

ジョブを送信する

次に、Azure Machine Learning で実行するジョブを送信します。 今回は ml_client.jobs に対して create_or_update を使います。

ml_client.jobs.create_or_update(job)

完了すると、ジョブは (トレーニングの結果として) モデルをワークスペースに登録し、Azure Machine Learning スタジオでジョブを表示するためのリンクを出力します。

警告

Azure Machine Learning では、ソース ディレクトリ全体をコピーすることで、トレーニング スクリプトが実行されます。 アップロードしたくない機密データがある場合は、.ignore ファイルを使用するか、ソース ディレクトリに含めないようにします。

ジョブ実行中の動作

ジョブの実行は、以下の段階を経て実施されます。

  • 準備:Docker イメージは、定義されている環境に従って作成されます。 イメージはワークスペースのコンテナー レジストリにアップロードされ、後で実行するためにキャッシュされます。 ログもジョブ履歴にストリーミングされ、表示して進行状況を監視できます。 キュレーションされた環境が指定されている場合は、そのキュレーションされた環境を補足するキャッシュ済みのイメージが使用されます。

  • スケーリング: 実行に現在使用可能な数より多くのノードが必要な場合、クラスターはスケールアップを試みます。

  • 実行中: スクリプト フォルダー src 内のすべてのスクリプトがコンピューティング先にアップロードされ、データ ストアがマウントまたはコピーされて、スクリプトが実行されます。 stdout からの出力と ./logs フォルダーがジョブ履歴にストリーミングされるので、ジョブの監視のために使用できます。

モデルのハイパーパラメーターの調整

これで、SDK を使用して TensorFlow トレーニングを実行する方法を確認したので、モデルの精度をさらに向上させることができるかどうかを見てみましょう。 Azure Machine Learning の sweep 機能を使用して、モデルのハイパーパラメーターを調整して最適化できます。

モデルのハイパーパラメーターを調整するには、トレーニング中に検索するパラメーター空間を定義します。 これを行うには、トレーニング ジョブに渡されるパラメーター (batch_sizefirst_layer_neuronssecond_layer_neurons、および learning_rate) の一部を azure.ml.sweep パッケージからの特別な入力に置き換えます。

from azure.ai.ml.sweep import Choice, LogUniform

# we will reuse the command_job created before. we call it as a function so that we can apply inputs
# we do not apply the 'iris_csv' input again -- we will just use what was already defined earlier
job_for_sweep = job(
    batch_size=Choice(values=[32, 64, 128]),
    first_layer_neurons=Choice(values=[16, 64, 128, 256, 512]),
    second_layer_neurons=Choice(values=[16, 64, 256, 512]),
    learning_rate=LogUniform(min_value=-6, max_value=-1),
)

次に、監視する主要メトリックや使用するサンプリング アルゴリズムなど、いくつかのスイープ固有のパラメーターを使用して、コマンド ジョブのスイープを構成します。

次のコードでは、ランダム サンプリングを使用して、主要メトリック validation_acc を最大化するために、さまざまな構成セットのハイパーパラメーターを試します。

また、早期終了ポリシー BanditPolicy も定義します。 このポリシーは、2 回の反復ごとにジョブをチェックすることによって動作します。 主要メトリック validation_acc が上位 10% の範囲外の場合、Azure Machine Learning はジョブを終了します。 これにより、モデルでは、ターゲット メトリックへの到達を支援する見込みがないハイパーパラメーターの探索を回避します。

from azure.ai.ml.sweep import BanditPolicy

sweep_job = job_for_sweep.sweep(
    compute=gpu_compute_target,
    sampling_algorithm="random",
    primary_metric="validation_acc",
    goal="Maximize",
    max_total_trials=8,
    max_concurrent_trials=4,
    early_termination_policy=BanditPolicy(slack_factor=0.1, evaluation_interval=2),
)

これで、以前と同様にこのジョブを送信できます。 今回は、トレーニング ジョブをスイープするスイープ ジョブを実行します。

returned_sweep_job = ml_client.create_or_update(sweep_job)

# stream the output and wait until the job is finished
ml_client.jobs.stream(returned_sweep_job.name)

# refresh the latest status of the job after streaming
returned_sweep_job = ml_client.jobs.get(name=returned_sweep_job.name)

ジョブの実行中に表示されるスタジオ ユーザー インターフェイス リンクを使用して、ジョブを監視できます。

最適なモデルを見つけて登録する

すべての実行が完了すると、最も高い精度でモデルを生成した実行を見つけることができます。

from azure.ai.ml.entities import Model

if returned_sweep_job.status == "Completed":

    # First let us get the run which gave us the best result
    best_run = returned_sweep_job.properties["best_child_run_id"]

    # lets get the model from this run
    model = Model(
        # the script stores the model as "model"
        path="azureml://jobs/{}/outputs/artifacts/paths/outputs/model/".format(
            best_run
        ),
        name="run-model-example",
        description="Model created from run.",
        type="custom_model",
    )

else:
    print(
        "Sweep job status: {}. Please wait until it completes".format(
            returned_sweep_job.status
        )
    )

その後、このモデルを登録できます。

registered_model = ml_client.models.create_or_update(model=model)

モデルをオンライン エンドポイントとしてデプロイする

モデルを登録したら、オンライン エンドポイント (つまり、Azure クラウドの Web サービス) としてデプロイできます。

通常、機械学習サービスをデプロイするには、以下のものが必要です。

  • デプロイするモデル資産。 これらの資産には、トレーニング ジョブに既に登録したモデルのファイルとメタデータが含まれます。
  • サービスとして実行するコード。 コードは、特定の入力要求 (エントリ スクリプト) でモデルを実行します。 このエントリ スクリプトは、デプロイされた Web サービスに送信されたデータを受け取り、それをモデルに渡します。 モデルがデータを処理した後、スクリプトはモデルの応答をクライアントに返します。 スクリプトはこのモデルに固有で、モデルが受け入れ、返すデータを理解する必要があります。 MLFlow モデルを使用すると、Azure Machine Learning によってこのスクリプトが自動的に作成されます。

デプロイの詳細については、「Python SDK v2 を使用して、マネージド オンライン エンドポイントに機械学習モデルをデプロイしてスコアリングする」を参照してください。

新しいオンライン エンドポイントを作成する

モデルをデプロイする最初の手順として、オンライン エンドポイントを作成する必要があります。 エンドポイント名は、Azure リージョン全体で一意である必要があります。 この記事では、汎用一意識別子 (UUID) を使用して一意の名前を作成します。

import uuid

# Creating a unique name for the endpoint
online_endpoint_name = "tff-dnn-endpoint-" + str(uuid.uuid4())[:8]
from azure.ai.ml.entities import (
    ManagedOnlineEndpoint,
    ManagedOnlineDeployment,
    Model,
    Environment,
)

# create an online endpoint
endpoint = ManagedOnlineEndpoint(
    name=online_endpoint_name,
    description="Classify handwritten digits using a deep neural network (DNN) using TensorFlow",
    auth_mode="key",
)

endpoint = ml_client.begin_create_or_update(endpoint).result()

print(f"Endpint {endpoint.name} provisioning state: {endpoint.provisioning_state}")

エンドポイントを作成したら、次のようにして取得できます:

endpoint = ml_client.online_endpoints.get(name=online_endpoint_name)

print(
    f'Endpint "{endpoint.name}" with provisioning state "{endpoint.provisioning_state}" is retrieved'
)

モデルをエンドポイントにデプロイする

エンドポイントを作成したら、エントリ スクリプトを使用してモデルをデプロイできます。 1 つのエンドポイントに複数のデプロイを設定できます。 ルールを使用すると、エンドポイントはトラフィックをこれらのデプロイに転送できます。

次のコードでは、受信トラフィックの 100% を処理する 1 つのデプロイを作成します。 デプロイに任意の色名 (tff-blue) を使用します。 デプロイには、tff-greentff-red などの他の名前を使用することもできます。 エンドポイントにモデルをデプロイするコードでは、次の処理が行われます。

  • 前に登録したモデルの最適なバージョンをデプロイする
  • score.py ファイルを使用してモデルにスコアを付けする
  • 推論を実行するために (前に宣言した) 同じキュレーション環境を使用する
model = registered_model

from azure.ai.ml.entities import CodeConfiguration

# create an online deployment.
blue_deployment = ManagedOnlineDeployment(
    name="tff-blue",
    endpoint_name=online_endpoint_name,
    model=model,
    code_configuration=CodeConfiguration(code="./src", scoring_script="score.py"),
    environment=curated_env_name,
    instance_type="Standard_DS3_v2",
    instance_count=1,
)

blue_deployment = ml_client.begin_create_or_update(blue_deployment).result()

Note

このデプロイが完了するまでに少し時間がかかると想定してください。

サンプル クエリを使用してデプロイをテストする

エンドポイントにモデルをデプロイしたら、エンドポイントの invoke メソッドを使用して、デプロイされたモデルの出力を予測できます。 推論を実行するには、request フォルダーのサンプル要求ファイル sample-request.json を使用します。

# # predict using the deployed model
result = ml_client.online_endpoints.invoke(
    endpoint_name=online_endpoint_name,
    request_file="./request/sample-request.json",
    deployment_name="tff-blue",
)

次に、返された予測を出力し、入力イメージと共にプロットできます。 正しく分類されていないサンプルを強調表示するには、赤いフォントの色と反転画像 (黒の場合は白) を使用します。

# compare actual value vs. the predicted values:
import matplotlib.pyplot as plt

i = 0
plt.figure(figsize=(20, 1))

for s in sample_indices:
    plt.subplot(1, n, i + 1)
    plt.axhline("")
    plt.axvline("")

    # use different color for misclassified sample
    font_color = "red" if y_test[s] != result[i] else "black"
    clr_map = plt.cm.gray if y_test[s] != result[i] else plt.cm.Greys

    plt.text(x=10, y=-10, s=result[i], fontsize=18, color=font_color)
    plt.imshow(X_test[s].reshape(28, 28), cmap=clr_map)

    i = i + 1
plt.show()

Note

モデルの精度は高いので、必要に応じて、不適切な分類のサンプルが表示されるまでセルを何度か実行します。

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

エンドポイントを使用しない場合は、削除してリソースの使用を停止します。 他のデプロイがエンドポイントを使っていないことを確認してから削除してください。

ml_client.online_endpoints.begin_delete(name=online_endpoint_name)

Note

このクリーンアップが完了するまでに少し時間がかかると想定してください。

次の手順

この記事では、TensorFlow モデルのトレーニングと登録を行いました。 また、モデルをオンライン エンドポイントにデプロイしました。 Azure Machine Learning の詳細については、以下の他の記事をご覧ください。