Azure MLのHello World続き。
今回は、既存の環境を再利用してRunスクリプトを実行してみる。
また、Microsoftが公式で説明するBlobを介した入出力をしてみる。
Azure MLの最小のコード
AzureML上で既存のEnvironment上でExperimentを走らせるコードは以下。
たぶん AzureML上でコードを動かす最小構成。
既存のEnvironmentがなければ先に作る必要がある。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
from azureml.core import Workspace from azureml.core import Environment from azureml.core import Experiment from azureml.core import ScriptRunConfig subscription_id = "<<Subscription_id>>" #you should be owner or contributor resource_group = "<<resource_group_id>>" #you should be owner or contributor workspace_name = "<<workspace_name>>" #your workspace name cluster_name = "<<compute_name>>" #cluster or compute name on which the experiment runs environment_name = "<<environment_name>>" #environment name experiment_name = "<<experiment_name>>" #experiment name # Workspaceを取得する ws = Workspace( workspace_name = workspace_name, subscription_id = subscription_id, resource_group = resource_group ) compute_target=ws.compute_targets[cluster_name] # 作成済みのEnvironmentを取得する registered_env = Environment.get( workspace=ws, name=environment_name ) # Run実行用の構成を作成する src = ScriptRunConfig( source_directory='.', script='./run.py', compute_target=compute_target, environment=registered_env ) # Environment上で実行するExperimentの内容(Run)を定義 run = Experiment( workspace=ws, name=experiment_name ).submit(src) # Runを実行。終わるまで待つ run.wait_for_completion(show_output=True) |
Azure MLが動作する仕組み
AzureMLが用意するパイプラインの仕組みに載せる場合は、StepとPipelineを定義していく。
Stepは独立した処理体系で、Stepごとに環境が用意されて、設定したスクリプトを実行できる。
Step毎にコンテナが作られ初期化処理が走る。
Compute,またはClusterとして指定したコンピュータの上で、
環境として指定したDockerコンテナとミドルウェア・ライブラリコードが動作し、
最終的に設定したスクリプト(Run)が動作する。
Azure ML Studio上のTerminalからComputeにログインできるが、
(恐らく…)ここからRunに指定したスクリプトを直接実行することができるため、
コンテナにログインしているものと思われる。
Azure ML Workspace内のストレージ
Azure MLにおいて、データの入力・出力をAzure Blobコンテナで行う。
Azure MLは、コンピュートとストレージを暗黙的に繋ぐ仕組みでもある。
具体的には、ワークスペースの中で、デフォルトの Blob, AKV, ACR等が設定される。
コンテナ内のコードは、Blobからデータを入力し、処理を行い、結果をBlobに書き戻す、
といった具合に動作する。
コンピュートからBlobにアクセスするのはかったるい、という感じがするが、
以下のドキュメントによると、入力はデータセット、出力はBlobとすることが推奨される。
Azure Machine Learning の実験でファイルを保存する場所と書き込む場所
それぞれ、コンテナ内のファイルシステムにマウントされる、という仕組み。
入力は、Datasetにデータをロードして渡すことが推奨されている。
入力のためのBlobマウント
Datasetにロードされたデータは、as_named_input()により指定した名前でアクセスできるようになる。
さらに、as_mount()によりコンピュートのローカルファイルシステムにマウントされる。
as_mount()はマウント先のパス名を返す。
早速、Titanicデータをマウントして読んでみる。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
# Titanicデータのロード web_paths = ['https://dprepdata.blob.core.windows.net/demo/Titanic.csv'] titanic_ds = Dataset.File.from_files(path = web_paths) input_data= titanic_ds.as_named_input('input').as_mount()# the dataset will be mounted on the remote compute # Run実行用の構成を作成する # TitanicデータをロードしたDatasetのマウント先パスを--input_dataパラメタとして渡す src = ScriptRunConfig( source_directory=source_directory, script=run_script_path, compute_target=compute_target, environment=registered_env, arguments=['--input_data',input_data] ) # Environment上でExperimentを実行する run = Experiment( workspace=ws, name=experiment_name ).submit(src) run.wait_for_completion(show_output=True) |
ここで指定するRunスクリプトは以下。
1 2 3 4 5 6 7 8 9 10 11 |
from libraries import consts import argparse import pandas as pd parser = argparse.ArgumentParser("hogehoge") parser.add_argument("--input_data", type=str, help="input_data argument") args = parser.parse_args() print(args.input_data) df=pd.read_csv(args.input_data) print(df.head()) |
上手くいくと、Runスクリプトはマウント先パスとDataFrameのhead()を出力する。
1 2 3 4 5 6 7 8 9 |
/mnt/azureml/cr/j/8e3c84aa7429451c8082f1fe2972a2c8/cap/data-capability/wd/INPUT_input/Titanic.csv PassengerId Survived Pclass ... Fare Cabin Embarked 0 1 0 3 ... 7.2500 NaN S 1 2 1 1 ... 71.2833 C85 C 2 3 1 3 ... 7.9250 NaN S 3 4 1 1 ... 53.1000 C123 S 4 5 0 3 ... 8.0500 NaN S [5 rows x 12 columns] |
出力のためのBlobマウント
Microsoft公式は、出力用にBlobをマウントする方法の例を書いている。
試しにWorkspaceと紐づくデフォルトBlobのコンテナをマウントしてみる。
get_default_datastore()により、デフォルトBlobを取得できる。
OutputFileDatasetConfig(name,destination) により、
Blobコンテナ以下にあるディレクトリをコンピュートファイルシステムのディレクトリにマウントする。
例えば、以下は、デフォルトBlob以下のikutyというディレクトリをコンピュートのresultsというディレクトリにマウントする。
戻り値はコンピュート上にマウントされたパス。
Runスクリプトに、datapath_outputという引数としてマウントされたパスを渡している。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
# Titanicデータのロード web_paths = ['https://dprepdata.blob.core.windows.net/demo/Titanic.csv'] titanic_ds = Dataset.File.from_files(path = web_paths) input_data= titanic_ds.as_named_input('input').as_mount()# the dataset will be mounted on the remote compute # デフォルトのBlobストアを取得する def_blob_store = ws.get_default_datastore() # Blobストア(コンテナ)以下のディレクトリをコンピュートのディレクトリにマウントする datapath_output = OutputFileDatasetConfig(name="results",destination=(def_blob_store,'ikuty')) # Run実行用の構成を作成する src = ScriptRunConfig( source_directory=source_directory, script=run_script_path, compute_target=compute_target, environment=registered_env, arguments=['--input_data',input_data,'--output_path',datapath_output] ) # Environment上でExperimentを実行する run = Experiment( workspace=ws, name=experiment_name ).submit(src) run.wait_for_completion(show_output=True) |
Runスクリプトは以下。マウントされたBlobコンテナ以下のファイルが渡される。
同時に渡しているTitanicのCSVをBlobコンテナに書いてみる。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
from libraries import consts import argparse import pandas as pd parser = argparse.ArgumentParser("precon") parser.add_argument("--input_data", type=str, help="input_data argument") parser.add_argument("--output_path", type=str, help="output_path argument") args = parser.parse_args() print(args.input_data) df=pd.read_csv(args.input_data) print(df.head()) print(args.output_path) df.to_csv(args.output_path+"/titanic.csv") |
デフォルトBlobのコンテナの下にikutyというディレクトリが作成され、
その中にtitanic.csvというファイルが作られた。
ちなみに、OutputFileDatasetConfig()でマウントした出力先ディレクトリから入力する、
という荒技も出来てしまう。むしろ、その方が見通しが良くなる感じもする。
Microsoftは公式でそう説明していないし、 OutputFileDatasetConfig()という名前が
そもそも出力用を意味していて、やってはいけない感がある。
まとめ
Azure ML上で既存の環境を再利用してRunスクリプトを実行する最小コードを探ってみた。
Microsoftが紹介している入出力の方法を試してみた。
デフォルトBlobストアからファイルを入出力できることを確認した。