Azure Machine Learning SDK で機械学習パイプラインを作成して管理する

適用対象:Python SDK azureml v1

この記事では、Azure Machine Learning SDK を使用して、機械学習パイプラインを作成して実行する方法について説明します。 ML パイプラインを使用して、さまざまな ML フェーズをつなぎ合わせるするワークフローを作成します。 その後、後でアクセスしたり、他のユーザーと共有したりするために、パイプラインを公開します。 ML パイプラインを追跡して、実際にモデルがどのように実行されているかを確認し、データ ドリフトを検出します。 ML パイプラインは、バッチ スコアリングのシナリオ、さまざまなコンピューティングの使用、ステップの再実行ではなく再利用、他のユーザーとの ML ワークフローの共有に最適です。

この記事はチュートリアルではありません。 最初のパイプラインを作成する方法に関するガイダンスについては、「チュートリアル:バッチ スコアリング用の Azure Machine Learning パイプラインを作成する」、または「Python の Azure Machine Learning パイプラインで自動 ML を使用する」を参照してください。

ML タスクの CI/CD オートメーションには Azure パイプラインと呼ばれる別の種類のパイプラインを使用できますが、その種類のパイプラインはワークスペース内には格納されません。 これらの異なるパイプラインを比較してください

作成した ML パイプラインは、Azure Machine Learning ワークスペースのメンバーであれば見ることができます。

ML パイプラインはコンピューティング先で実行します (「Azure Machine Learning でのコンピューティング先とは」を参照)。 パイプラインでは、サポートされている Azure Storage の場所に対してデータを読み取ったり書き込んだりすることができます。

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

前提条件

まず、ワークスペースをアタッチします。

import azureml.core
from azureml.core import Workspace, Datastore

ws = Workspace.from_config()

機械学習リソースをセットアップする

ML パイプラインの実行に必要なリソースを作成します。

  • パイプラインの手順で必要なデータへのアクセスに使用されるデータストアを設定します。

  • データストアに存在する永続データまたはデータストアでアクセス可能な永続データを指し示すように、Dataset オブジェクトを構成します。 パイプラインの手順間で一時データを渡すために OutputFileDatasetConfig オブジェクトを構成します。

  • パイプラインの手順が実行されるコンピューティング先を設定します。

データストアをセットアップする

データストアには、パイプラインでアクセスするデータが格納されます。 各ワークスペースに既定のデータストアがあります。 データストアをさらに登録することも可能です。

ワークスペースを作成すると、Azure FilesAzure Blob Storage がワークスペースに接続されます。 既定のデータストアが、Azure Blob Storage に接続するために登録されています。 詳細については、Azure Files、Azure BLOB、Azure ディスクの使い分けに関するページを参照してください。

# Default datastore 
def_data_store = ws.get_default_datastore()

# Get the blob storage associated with the workspace
def_blob_store = Datastore(ws, "workspaceblobstore")

# Get file storage associated with the workspace
def_file_store = Datastore(ws, "workspacefilestore")

通常、ステップではデータが消費され、出力データが生成されます。 ステップでは、モデルなどのデータ、モデル ファイルと依存ファイルを含むディレクトリ、一時データが作成されることがあります。 このデータは、パイプラインの後続の他のステップで使用できます。 パイプラインをデータに接続する方法の詳細については、データへのアクセス方法およびデータセットの登録方法に関する記事を参照してください。

Dataset オブジェクトと OutputFileDatasetConfig オブジェクトを使用してデータを構成する

パイプラインにデータを提供する方法には、データセット オブジェクトを使用することをお勧めします。 Dataset オブジェクトでは、データストアに存在するデータ、データストアからアクセス可能なデータ、または Web URL でアクセス可能なデータが指し示されています。 Dataset クラスは抽象クラスであるため、FileDataset (1 つ以上のファイルを参照)、または区切られたデータ列を含む 1 つ以上のファイルによって作成される TabularDataset のいずれかのインスタンスを作成します。

Dataset は、from_filefrom_delimited_files などのメソッドを使用して作成します。

from azureml.core import Dataset

my_dataset = Dataset.File.from_files([(def_blob_store, 'train-images/')])

中間データ (またはステップの出力) は、OutputFileDatasetConfig オブジェクトによって表されます。 ステップの出力として output_data1 が作成されます。 このデータは、必要に応じて register_on_complete を呼び出して、データセットとして登録できます。 あるステップで OutputFileDatasetConfig を作成し、別のステップでそれを入力として使用する場合、ステップ間のデータの依存関係によって、パイプラインで暗黙的な実行順序が作成されます。

OutputFileDatasetConfig オブジェクトはディレクトリを返し、既定では、ワークスペースの既定のデータストアに出力を書き込みます。

from azureml.data import OutputFileDatasetConfig

output_data1 = OutputFileDatasetConfig(destination = (datastore, 'outputdataset/{run-id}'))
output_data_dataset = output_data1.register_on_complete(name = 'prepared_output_data')

重要

OutputFileDatasetConfig を使用して格納した中間データは、Azure では自動的に削除されません。 パイプラインの実行の最後で中間データが削除されるようプログラムするか、短いデータ保持ポリシーのデータストアを使用するか、手動で定期的にクリーンアップする必要があります。

ヒント

アップロードするファイルは、手持ちのジョブに関連するものに限定してください。 データ ディレクトリ内のファイルに変更があった場合は、再利用が指定されていても、次回のパイプライン実行時にステップを再実行する理由としてみなされます。

コンピューティング ターゲットを設定する

Azure Machine Learning での "コンピューティング" (または "コンピューティング先") という用語は、機械学習パイプラインで計算ステップを実行するマシンまたはクラスターのことです。 コンピューティング先の完全な一覧については、モデルのトレーニング用のコンピューティング先に関するセクションを参照してください。コンピューティング先を作成してワークスペースにアタッチする方法については、コンピューティング先の作成に関するページを参照してください。 コンピューティング先を作成またはアタッチするプロセスは、モデルをトレーニングするときも、パイプラインのステップを実行するときも同じです。 コンピューティング先を作成してアタッチした後、パイプラインのステップでは ComputeTarget オブジェクトを使用します。

重要

コンピューティング先での管理操作の実行は、リモート ジョブの内部からはサポートされていません。 機械学習パイプラインはリモート ジョブとして送信されるため、パイプラインの内部からはコンピューティング先での管理操作を使用しないでください。

Azure Machine Learning コンピューティング

ステップを実行するための Azure Machine Learning コンピューティングを作成できます。 他のコンピューティング先のコードも似ていますが、種類に応じてパラメーターが多少異なります。

from azureml.core.compute import ComputeTarget, AmlCompute

compute_name = "aml-compute"
vm_size = "STANDARD_NC6"
if compute_name in ws.compute_targets:
    compute_target = ws.compute_targets[compute_name]
    if compute_target and type(compute_target) is AmlCompute:
        print('Found compute target: ' + compute_name)
else:
    print('Creating a new compute target...')
    provisioning_config = AmlCompute.provisioning_configuration(vm_size=vm_size,  # STANDARD_NC6 is GPU-enabled
                                                                min_nodes=0,
                                                                max_nodes=4)
    # create the compute target
    compute_target = ComputeTarget.create(
        ws, compute_name, provisioning_config)

    # Can poll for a minimum number of nodes and for a specific timeout.
    # If no min node count is provided it will use the scale settings for the cluster
    compute_target.wait_for_completion(
        show_output=True, min_node_count=None, timeout_in_minutes=20)

    # For a more detailed view of current cluster status, use the 'status' property
    print(compute_target.status.serialize())

トレーニングの実行環境を構成する

次のステップでは、リモート トレーニングの実行に、トレーニング ステップで必要なすべての依存関係があることを確認します。 依存関係とランタイム コンテキストは、RunConfiguration オブジェクトを作成して構成することによって設定されます。

from azureml.core.runconfig import RunConfiguration
from azureml.core.conda_dependencies import CondaDependencies
from azureml.core import Environment 

aml_run_config = RunConfiguration()
# `compute_target` as defined in "Azure Machine Learning compute" section above
aml_run_config.target = compute_target

USE_CURATED_ENV = True
if USE_CURATED_ENV :
    curated_environment = Environment.get(workspace=ws, name="AzureML-sklearn-0.24-ubuntu18.04-py37-cpu")
    aml_run_config.environment = curated_environment
else:
    aml_run_config.environment.python.user_managed_dependencies = False
    
    # Add some packages relied on by data prep step
    aml_run_config.environment.python.conda_dependencies = CondaDependencies.create(
        conda_packages=['pandas','scikit-learn'], 
        pip_packages=['azureml-sdk', 'azureml-dataset-runtime[fuse,pandas]'], 
        pin_sdk_version=False)

上記のコードは、依存関係を処理するための 2 つのオプションを示しています。 表示されているとおり、USE_CURATED_ENV = True の場合、その構成はキュレートされた環境に基づいています。 キュレートされた環境は、共通の相互依存ライブラリを使用して "事前作成" されているため、より迅速にオンラインにできます。 キュレートされた環境には、Microsoft Container Registry にあらかじめビルドされた Docker イメージが用意されています。 詳細については、「Azure Machine Learning のキュレーションされた環境」を参照してください。

USE_CURATED_ENVFalse に変更した場合にたどるパスは、依存関係を明示的に設定するためのパターンを示します。 このシナリオでは、新しいカスタム Docker イメージが作成され、リソース グループ内の Azure Container Registry に登録されます (「Azure のプライベート Docker コンテナー レジストリの概要」を参照してください)。 このイメージのビルドと登録には数分かかることがあります。

パイプラインのステップを構築する

コンピューティング リソースと環境を作成したら、パイプラインのステップを定義する準備は完了です。 Azure Machine Learning SDK を介して使用できる組み込みの手順は多数あります。azureml.pipeline.steps パッケージのリファレンス ドキュメントを参照してください。 最も柔軟性の高いクラスは、Python スクリプトを実行する PythonScriptStep です。

from azureml.pipeline.steps import PythonScriptStep
dataprep_source_dir = "./dataprep_src"
entry_point = "prepare.py"
# `my_dataset` as defined above
ds_input = my_dataset.as_named_input('input1')

# `output_data1`, `compute_target`, `aml_run_config` as defined above
data_prep_step = PythonScriptStep(
    script_name=entry_point,
    source_directory=dataprep_source_dir,
    arguments=["--input", ds_input.as_download(), "--output", output_data1],
    compute_target=compute_target,
    runconfig=aml_run_config,
    allow_reuse=True
)

上記のコードには、一般的な初期パイプライン ステップが表示されます。 データ準備コードはサブディレクトリにあります (この例では、ディレクトリ "./dataprep.src" にある "prepare.py")。 パイプライン作成プロセスの一環として、このディレクトリが圧縮され、compute_target にアップロードされ、script_nameの値として指定されたスクリプトがステップによって実行されます。

arguments の値によって、ステップの入力と出力が指定されます。 上の例で、ベースライン データは my_dataset データセットです。 対応するデータはコードにより as_download() と指定されているので、コンピューティング リソースにダウンロードされます。 スクリプト prepare.py により、目下のタスクに適したデータ変換タスクが行われ、データが OutputFileDatasetConfig 型の output_data1 に出力されます。 詳細については、「ML パイプラインのステップ間でのデータの移動 (Python)」を参照してください。 このステップは、構成 aml_run_config を使用して compute_target によって定義されたコンピューターで実行されます。

共同環境でパイプラインを使用する際は、前の結果 (allow_reuse) の再利用が鍵となります。不要な再実行を除去することで機敏性が提供されるからです。 ステップの script_name、inputs、およびパラメーターが同じままのときは、再利用が既定の動作になります。 再利用が許可された場合、前回の実行の結果はすぐに次のステップに送信されます。 allow_reuseFalse に設定されている場合は、パイプライン実行中、このステップの新規実行が常に生成されます。

1 つのステップでパイプラインを作成することも可能ですが、ほとんどの場合は、プロセス全体をいくつかのステップに分割することを選択します。 たとえば、データの準備、トレーニング、モデルの比較、およびデプロイ用のステップを用意します。 たとえば、上記で data_prep_step を指定したら、次のステップはトレーニングとなることが想定できます。

train_source_dir = "./train_src"
train_entry_point = "train.py"

training_results = OutputFileDatasetConfig(name = "training_results",
    destination = def_blob_store)

    
train_step = PythonScriptStep(
    script_name=train_entry_point,
    source_directory=train_source_dir,
    arguments=["--prepped_data", output_data1.as_input(), "--training_results", training_results],
    compute_target=compute_target,
    runconfig=aml_run_config,
    allow_reuse=True
)

上記のコードは、データの準備のステップのコードとよく似ています。 トレーニングのコードは、データの準備のコードとは別のディレクトリにあります。 データの準備のステップの OutputFileDatasetConfig 出力である output_data1 は、トレーニング ステップへの "入力" として使用されます。 新しい OutputFileDatasetConfig オブジェクトである training_results が作成され、これによって、その後の比較またはデプロイのステップの結果が保持されます。

その他のコード例については、2 ステップの ML パイプラインを構築する方法に関するページと、実行完了時にデータ ストアにデータを書き戻す方法に関するページを参照してください。

ステップを定義した後は、それらのステップの一部またはすべてを使用してパイプラインをビルドします。

注意

ステップを定義するとき、またはパイプラインを構築するときに、ファイルまたはデータが Azure Machine Learning にアップロードされることはありません。 ファイルは、Experiment.submit() を呼び出すときにアップロードされます。

# list of steps to run (`compare_step` definition not shown)
compare_models = [data_prep_step, train_step, compare_step]

from azureml.pipeline.core import Pipeline

# Build the pipeline
pipeline1 = Pipeline(workspace=ws, steps=[compare_models])

データセットを使用する

Azure Blob ストレージ、Azure Files、Azure Data Lake Storage Gen1、Azure Data Lake Storage Gen2、Azure SQL Database、および Azure Database for PostgreSQL から作成されたデータセットは、任意のパイプライン ステップへの入力として使用できます。 DataTransferStep または DatabricksStep に出力を書き込むことができます。また、特定のデータストアにデータを書き込む場合は、OutputFileDatasetConfig を使用します。

重要

OutputFileDatasetConfig を使用してデータストアに出力データを書き戻すことができるのは、Azure BLOB、Azure ファイル共有、ADLS Gen 1、および Gen 2 データストアだけです。

dataset_consuming_step = PythonScriptStep(
    script_name="iris_train.py",
    inputs=[iris_tabular_dataset.as_named_input("iris_data")],
    compute_target=compute_target,
    source_directory=project_folder
)

その後、Run.input_datasets ディクショナリを使用して、パイプライン内のデータセットを取得します。

# iris_train.py
from azureml.core import Run, Dataset

run_context = Run.get_context()
iris_dataset = run_context.input_datasets['iris_data']
dataframe = iris_dataset.to_pandas_dataframe()

Run.get_context() の行を強調表示します。 この関数では、進行中の実験用の実行を表す Run を取得します。 上記のサンプルでは、登録されたデータセットを取得するために使用しています。 Run オブジェクトのもう 1 つの一般的な用途は、実験自体と実験が存在するワークスペースの両方を取得することです。

# Within a PythonScriptStep

ws = Run.get_context().experiment.workspace

データを渡したり、データにアクセスしたりするための別の方法などの詳細については、「ML パイプラインのステップ間でのデータの移動 (Python)」を参照してください。

キャッシュと再利用

パイプラインの動作を最適化およびカスタマイズするために、キャッシュと再利用に関連するいくつかのことを実行できます。 たとえば、次のようなことを選択できます。

  • ステップ定義中に allow_reuse=False を設定して、既定のステップ実行出力の再利用をオフにします。 共同環境でパイプラインを使用する際は再利用が鍵となります。不要な再実行を除去することで機敏性が提供されるからです。 ただし、再利用しないことも選択できます。
  • pipeline_run = exp.submit(pipeline, regenerate_outputs=True) を使用して、1 回の実行で全ステップの出力の再生成を強制します

既定では、ステップの allow_reuse が有効になり、ステップの定義に指定されている source_directory がハッシュ化されます。 したがって、ある特定のステップのスクリプトが同じ (script_name、入力、およびパラメーター) で、かつ source_directory でそれ以外に何も変更されていない場合、前のステップ実行の出力が再利用されて、ジョブはコンピューティングに送信されず、代わりに、前の実行の結果が次のステップで即時使用可能になります。

step = PythonScriptStep(name="Hello World",
                        script_name="hello_world.py",
                        compute_target=aml_compute,
                        source_directory=source_directory,
                        allow_reuse=False,
                        hash_paths=['hello_world.ipynb'])

注意

データ入力の名前が変更された場合、基になるデータが変更されない場合でも、ステップは再実行されます。 入力データ (data.as_input(name=...)) の name フィールドは明示的に設定する必要があります。 この値を明示的に設定しない場合、name フィールドはランダムな guid に設定され、ステップの結果は再利用されません。

パイプラインを送信する

パイプラインを送信すると、Azure Machine Learning によって各ステップの依存関係がチェックされ、指定したソース ディレクトリのスナップショットがアップロードされます。 ソース ディレクトリを指定していない場合は、現在のローカル ディレクトリがアップロードされます。 スナップショットは、ご利用のワークスペースにも実験の一部として保存されます。

重要

不要なファイルがスナップショットに含まれないようにするには、無視ファイル (.gitignore または .amlignore) を作成します。 除外するファイルとディレクトリをこのファイルに追加します。 このファイル内で使用する構文の詳細については、.gitignore構文とパターンを参照してください。 .amlignore ファイルでは同じ構文を使用します。 "両方のファイルが存在する場合は、.amlignore ファイルが使用され、.gitignore ファイルは使用されません。 "

詳細については、「スナップショット」を参照してください。

from azureml.core import Experiment

# Submit the pipeline to be run
pipeline_run1 = Experiment(ws, 'Compare_Models_Exp').submit(pipeline1)
pipeline_run1.wait_for_completion()

初めてパイプラインを実行すると、Azure Machine Learning で次のことが行われます。

  • ワークスペースに関連付けられた BLOB ストレージからコンピューティング先に、プロジェクトのスナップショットをダウンロードします。

  • パイプラインの各ステップに対応した Docker イメージをビルドします。

  • 各ステップの Docker イメージをコンテナー レジストリからコンピューティング先にダウンロードします。

  • Dataset オブジェクトと OutputFileDatasetConfig オブジェクトへのアクセスを構成します。 as_mount() アクセス モードでは、FUSE は仮想アクセスを提供するために使用されます。 マウントがサポートされていない場合、またはユーザーがアクセスを as_upload() として指定した場合は、代わりにデータがコンピューティング先にコピーされます。

  • ステップの定義で指定されているコンピューティング先で、ステップを実行します。

  • ログ、stdout と stderr、メトリック、ステップによって指定されている出力などの成果物を作成します。 その後、これらの成果物がアップロードされて、ユーザーの既定のデータストアに保持されます。

Diagram of running an experiment as a pipeline

詳細については、「Experiment class」リファレンスを参照してください。

推論時に変化する引数にパイプライン パラメーターを使用する

パイプライン内の個々のステップへの引数が、開発とトレーニングの期間 (トレーニングの速度や勢い、データや構成ファイルへのパスなど) と関係する場合があります。 ただし、モデルが配置されている場合、推論している引数 (つまり、モデルで回答するために作成したクエリ) を動的に渡したい場合があります。 これらの引数の型は、パイプライン パラメーターにする必要があります。 これを Python で行うには、次のコード スニペットのとおり、azureml.pipeline.core.PipelineParameter クラスを使用します。

from azureml.pipeline.core import PipelineParameter

pipeline_param = PipelineParameter(name="pipeline_arg", default_value="default_val")
train_step = PythonScriptStep(script_name="train.py",
                            arguments=["--param1", pipeline_param],
                            target=compute_target,
                            source_directory=project_folder)

Python 環境でパイプライン パラメーターを操作する方法

上記の「トレーニングの実行環境を構成する」で説明したとおり、環境の状態と Python ライブラリの依存関係は、Environment オブジェクトを使用して指定します。 一般的に、名前、および必要に応じてバージョンを参照することによって、既存の Environment を指定できます。

aml_run_config = RunConfiguration()
aml_run_config.environment.name = 'MyEnvironment'
aml_run_config.environment.version = '1.0'

ただし、PipelineParameter オブジェクトを使用してパイプラインのステップの実行時に変数を動的に設定する場合は、既存の Environment を参照するこの手法を使用することはできません。 代わりに、PipelineParameter オブジェクトを使用する場合は、RunConfigurationenvironment フィールドを Environment オブジェクトに設定する必要があります。 このような Environment に、外部の Python パッケージへの依存関係が適切に設定されていることを確実にする必要があります。

パイプラインの結果を表示する

すべてのパイプラインとその実行の詳細の一覧を、Studio で表示します。

  1. Azure Machine Learning Studio にサインインします。

  2. ワークスペースを表示します

  3. 左側で [パイプライン] を選択し、すべてのパイプラインの実行を表示します。 list of machine learning pipelines

  4. 実行結果を表示する特定のパイプラインを選択します。

Git の追跡と統合

ソース ディレクトリがローカル Git リポジトリであるトレーニング実行を開始すると、リポジトリに関する情報が実行履歴に格納されます。 詳細については、「Azure Machine Learning との Git 統合」を参照してください。

次のステップ