はじめに
Azure AutoMLでトレーニングしたモデルのmetricsをPython SDK v1 / v2の2パターンで取得してみます。
モデル自体はSDK V2でトレーニングしたものを使います。
トレーニングについては過去の記事にあるので、ぜひご参照ください。
【タスク】
- 分類:【Python SDK v2】Azure AutoMLをPythonからトレーニング
- 回帰:【Azure AutoML】回帰タスクをPythonから行ってみた(トレーニング~推論まで)
- 時系列:【Azure AutoML】時系列予測をPythonで行う
環境
- OS Windows 10(NVIDIA GTX 1650Ti,16GB RAM, i5-10300H CPU)
- Visual Studio Code 1.73.1
- Python 3.8 / 3.9
- AzureML Python SDK v1 / v2
Python SDK V1のmetrics取得する方法
SDK V2でトレーニングしたモデルからmetricsを取得します。
V1の場合は、get_metrics
関数を使うと簡単にできます。
from azureml.core import Workspace
from azureml.train.automl.run import AutoMLRun
import pandas as pd
ws = Workspace.from_config()
experiment = ws.experiments['<実験名>']
automl_run = AutoMLRun(experiment, run_id = '<ジョブID>')
best_model, _ = automl_run.get_output()
print(best_model.get_metrics())
結果
V2で作ったモデルを無理やりV1でmetrics取得しようとしているせいか、Warningがめちゃくちゃ出ますが、次のようにmetricsが色々返ってきました。
{'mean_absolute_percentage_error': 17.41204188234799, 'explained_variance': 0.738272704815586, 'mean_absolute_error': 2126.4896950718503, 'normalized_median_absolute_error': 0.03536353076485475, 'r2_score': 0.719627939723515, 'root_mean_squared_error': 2978.0824945509294, 'median_absolute_error': 1424.513746269879, 'normalized_root_mean_squared_log_error': 0.10514941989299778, 'normalized_root_mean_squared_error': 0.0739308498721744, 'root_mean_squared_log_error': 0.22949649762141444, 'normalized_mean_absolute_error': 0.05279007236661164, 'spearman_correlation': 0.8992768077701008, 'predicted_true': 'aml://artifactId/ExperimentRun/dcid.gray_iron_drsmn87sp0_0/predicted_true', 'residuals': 'aml://artifactId/ExperimentRun/dcid.gray_iron_drsmn87sp0_0/residuals'}
Exception ignored in: <function _Win32Helper.__del__ at 0x000002671874F4C0>
Traceback (most recent call last):
File "C:\Users\anaconda3\envs\azml38v1\lib\site-packages\azureml\automl\runtime\shared\win32_helper.py", line 246, in __del__
TypeError: catching classes that do not inherit from BaseException is not allowed
最後にTypeErrorも出ますが、なんとかmetricsを読み込むことはできました!!
続いて、素直にV2からmetricsを取得してみます。
Python SDK V2の場合
SDK V2の場合はMLFlowを使います。
参考サイト:
まずはmlflowとazureml-mlflowをインストールします。
pip install mlflow azureml-mlflow
最初にワークスペースへの接続をし、MLFlowで実験を追跡するためにトラッキングURLを取得します。
その次にトレーニングしたジョブ(親ジョブ)からベストモデルを取得し、metricsを得るという流れになります。
import mlflow
from azure.identity import DefaultAzureCredential
from azure.ai.ml import MLClient
from mlflow.tracking.client import MlflowClient
import pandas as pd
# workspace
credential = DefaultAzureCredential(exclude_shared_token_cache_credential=True)
subscription_id="<サブスクリプションID>"
resource_group="<リソースグループ>"
workspace_name="<ワークスペース名>"
ml_client = MLClient(credential, subscription_id, resource_group, workspace_name)
# Obtain the tracking URL from MLClient
MLFLOW_TRACKING_URI = ml_client.workspaces.get(
name=ml_client.workspace_name
).mlflow_tracking_uri
print(MLFLOW_TRACKING_URI)
mlflow.set_tracking_uri(MLFLOW_TRACKING_URI)
print("\nCurrent tracking uri: {}".format(mlflow.get_tracking_uri()))
# Initialize MLFlow client
mlflow_client = MlflowClient()
job_name='<ジョブID>'
# Get the parent run
mlflow_parent_run = mlflow_client.get_run(job_name)
print("Parent Run: ")
print(mlflow_parent_run)
print(mlflow_parent_run.data.tags)
best_child_run_id = mlflow_parent_run.data.tags["automl_best_child_run_id"]
print("Found best child run id: ", best_child_run_id)
best_run = mlflow_client.get_run(best_child_run_id)
print("Best child run: ")
print(best_run)
ワークスペースへの接続・ジョブIDを入力するだけで実行できます。
結果
親ジョブのmetrics・ベストモデルのmetricsが返ってきました。
Parent Run:
<Run: data=<RunData: metrics={'AUC_macro': 0.5537367792751098,
'AUC_micro': 0.8053648205456106,
'AUC_weighted': 0.5537367792751098,
'accuracy': 0.7873917952578096,
'average_precision_score_macro': 0.5301345560931308,
'average_precision_score_micro': 0.7764476136917231,
'average_precision_score_weighted': 0.6946791650615354,
'balanced_accuracy': 0.5,
'f1_score_macro': 0.44051441816730164,
'f1_score_micro': 0.7873917952578096,
'f1_score_weighted': 0.6937547541810158,
'log_loss': 0.5174726757985704,
'matthews_correlation': 0.0,
'norm_macro_recall': 0.0,
'precision_score_macro': 0.3936958976289048,
'precision_score_micro': 0.7873917952578096,
'precision_score_weighted': 0.6200497715962933,
'recall_score_macro': 0.5,
'recall_score_micro': 0.7873917952578096,
'recall_score_weighted': 0.7873917952578096,
'weighted_accuracy': 0.9318802438597572}, params={}, tags={'automl_best_child_run_id': 'hungry_chain_dyhsn2rnyj_3',
'fit_time_000': '0.5580559999999999;4.332179999999999;3;8',
'iteration_000': '0;1;2;3',
'mlflow.rootRunId': 'hungry_chain_dyhsn2rnyj',
'mlflow.runName': 'hungry_chain_dyhsn2rnyj',
'mlflow.user': '',
'model_explain_best_run_child_id': 'hungry_chain_dyhsn2rnyj_3',
'model_explain_run': 'best_run',
'predicted_cost_000': '0;0;0;0',
'run_algorithm_000': 'LightGBM;XGBoostClassifier;VotingEnsemble;StackEnsemble',
'run_preprocessor_000': 'MaxAbsScaler;MaxAbsScaler;;',
'score_000': '0.7861874294316898;0.7775310500564546;0.7863379751599548;0.7873917952578096',
'training_percent_000': '100;100;100;100'}>, info=<RunInfo: artifact_uri='azureml://japaneast.api.azureml.ms/mlflow/v2.0/subscriptions/XXX/resourceGroups/XXX/providers/Microsoft.MachineLearningServices/workspaces/XXX/experiments/febdb527-437a-4d38-8d26-7cb8528691ae/runs/hungry_chain_dyhsn2rnyj/artifacts', end_time=1683513330904, experiment_id='febdb527-437a-4d38-8d26-7cb8528691ae', lifecycle_stage='active', run_id='hungry_chain_dyhsn2rnyj', run_name='hungry_chain_dyhsn2rnyj', run_uuid='hungry_chain_dyhsn2rnyj', start_time=1683512458707, status='FINISHED', user_id='XXX'>>
{'model_explain_run': 'best_run', 'score_000': '0.7861874294316898;0.7775310500564546;0.7863379751599548;0.7873917952578096', 'predicted_cost_000': '0;0;0;0', 'fit_time_000': '0.5580559999999999;4.332179999999999;3;8', 'training_percent_000': '100;100;100;100', 'iteration_000': '0;1;2;3', 'run_preprocessor_000': 'MaxAbsScaler;MaxAbsScaler;;', 'run_algorithm_000': 'LightGBM;XGBoostClassifier;VotingEnsemble;StackEnsemble', 'automl_best_child_run_id': 'hungry_chain_dyhsn2rnyj_3', 'model_explain_best_run_child_id': 'hungry_chain_dyhsn2rnyj_3', 'mlflow.rootRunId': 'hungry_chain_dyhsn2rnyj', 'mlflow.runName': 'hungry_chain_dyhsn2rnyj', 'mlflow.user': 'XXX'}
Found best child run id: hungry_chain_dyhsn2rnyj_3
Best child run:
<Run: data=<RunData: metrics={'AUC_macro': 0.5537367792751098,
'AUC_micro': 0.8053648205456106,
'AUC_weighted': 0.5537367792751098,
'accuracy': 0.7873917952578096,
'average_precision_score_macro': 0.5301345560931308,
'average_precision_score_micro': 0.7764476136917231,
'average_precision_score_weighted': 0.6946791650615354,
'balanced_accuracy': 0.5,
'f1_score_macro': 0.44051441816730164,
'f1_score_micro': 0.7873917952578096,
'f1_score_weighted': 0.6937547541810158,
'log_loss': 0.5174726757985704,
'matthews_correlation': 0.0,
'norm_macro_recall': 0.0,
'precision_score_macro': 0.3936958976289048,
'precision_score_micro': 0.7873917952578096,
'precision_score_weighted': 0.6200497715962933,
'recall_score_macro': 0.5,
'recall_score_micro': 0.7873917952578096,
'recall_score_weighted': 0.7873917952578096,
'weighted_accuracy': 0.9318802438597572}, params={}, tags={'mlflow.parentRunId': 'hungry_chain_dyhsn2rnyj',
'mlflow.rootRunId': 'hungry_chain_dyhsn2rnyj',
'mlflow.runName': 'kind_snake_g0p4zj5j',
'mlflow.source.name': 'automl_driver.py',
'mlflow.source.type': 'JOB',
'mlflow.user': 'XXX',
'model_explain_run_id': 'hungry_chain_dyhsn2rnyj_ModelExplain',
'model_explanation': 'True'}>, info=<RunInfo: artifact_uri='azureml://japaneast.api.azureml.ms/mlflow/v2.0/subscriptions/XXX/resourceGroups/XXX/providers/Microsoft.MachineLearningServices/workspaces/XXX/experiments/febdb527-437a-4d38-8d26-7cb8528691ae/runs/hungry_chain_dyhsn2rnyj_3/artifacts', end_time=1683513329701, experiment_id='febdb527-437a-4d38-8d26-7cb8528691ae', lifecycle_stage='active', run_id='hungry_chain_dyhsn2rnyj_3', run_name='kind_snake_g0p4zj5j', run_uuid='hungry_chain_dyhsn2rnyj_3', start_time=1683513268867, status='FINISHED', user_id='XXX'>>
親ジョブ・ベストモデルのmetricsともに取得することができました。
ここからmetricsだけ取り出すには、下記をコードの最後に貼り付けます。
data = best_run.data.metrics
res = json.dumps(data)
print(res)
結果はこうなりました。
{
"AUC_weighted": 0.5537367792751098,
"AUC_micro": 0.8053648205456106,
"average_precision_score_macro": 0.5301345560931308,
"matthews_correlation": 0,
"weighted_accuracy": 0.9318802438597572,
"norm_macro_recall": 0,
"log_loss": 0.5174726757985704,
"f1_score_weighted": 0.6937547541810158,
"balanced_accuracy": 0.5,
"recall_score_macro": 0.5,
"precision_score_weighted": 0.6200497715962933,
"f1_score_macro": 0.44051441816730164,
"average_precision_score_micro": 0.7764476136917231,
"precision_score_macro": 0.3936958976289048,
"f1_score_micro": 0.7873917952578096,
"recall_score_weighted": 0.7873917952578096,
"AUC_macro": 0.5537367792751098,
"average_precision_score_weighted": 0.6946791650615354,
"accuracy": 0.7873917952578096,
"precision_score_micro": 0.7873917952578096,
"recall_score_micro": 0.7873917952578096
}