コマンドラインでの機械学習 (AzureML + GitHub Actions)
機械学習のモデル学習とデプロイのプロセスを自動化すべく、Azure Machine Learning のコマンドライン機能 Azure Machine Learning CLI
で実装する方法をご紹介します。
Azure Machine Learning CLI
は Azure CLI の拡張機能です。Azure Machine Learning の様々な機能を実行することができます。Azure Machine Learning は GUI である Azure Machine Learning studio、Python SDK、R SDK のインタフェースに加えて、今回取り上げる Azure CLI もサポートしています。
Azure CLI は、MLOps などでの自動化プロセスを実装するときに重宝されると思います。
事前準備
コード
GitHub にサンプルコードを公開しました。
konabuta/azureml-mlops
データ準備 (Azure ML Dataset)
学習データを予め準備しておきます。今回は糖尿病に関するサンプルデータ diabetes.csv を利用します。
まず Azure Machine Learning studio ml.azure.com にアクセスします。
早速 diabetes.csv を Dataset として登録します。diabetesData という名前にしておきます。
ウィザードに従っていきます。無事データの登録が完了し、diabetesData のデータを開くとこのような画面が出てきます。
Python環境の定義 (Azure ML Environment)
Azure Machine Learning では Python の環境情報 (pip,conda, DockerImage) を管理することができます。Azure Machine Learning の Compute Cluster でモデル学習するときは、Kubernetes 上で API として推論環境を構築するときに、予め作成した Environment を利用してくれます。Environment は、Python のパッケージと Docker イメージの管理機能です。
Azure Machine Learning Workspace に接続します。
from azureml.core import Workspace
ws = Workspace.from_config()
print(ws.name, ws.resource_group, ws.location, ws.subscription_id, sep = '\n')
今回は pip, conda のパッケージを指定して Environment を作成します。
from azureml.core import Environment
env = Environment.from_conda_specification(
name="diabetes-env",
file_path="../environments/diabetes-env.yml"
)
ここで利用している titanic_env.yml の中身をみてみます。
name: diabetes-env
channels:
- defaults
- anaconda
- conda-forge
dependencies:
- python=3.6
- pip
- notebook
- ipykernel
- pip:
- interpret
- matplotlib
- azureml-defaults==1.19.0
- azureml-core==1.19.0
- azureml-widgets==1.19.0
計算クラスター環境 Compute cluster
モデル学習を実行するときに GitHub Actions のエージェント上で Python を動かすのは当然ながら色々辛いので、Azure Machine Learning の計算クラスター環境である Compute Cluster を利用します。Azure Machine Learning studio から作成していきます。
仮想マシンのスペックを選択します。今回はデータが小さいので 4 コアあれば十分でしょう。
コンピューティング名は cpuclusters
として進めます。最小ノード数と最大ノード数は 1 以上を設定します。
実行構成ファイル
これが一番曲者かと思います。モデル学習で利用するのですが、先ほど作成した Envionment、Dataset などモデル学習の実行の設定情報を定義します。.runconfig
ファイルを作成する方法は色々あるのですが、手動作成するのは辛いです。Microsoft 公式のサンプル集に便利なコード generate-runconfig.py
がありましたので、そちらを参考に実行構成ファイルを生成します。
python setup/generate-runconfig.py
これを実行すると .azureml
フォルダに diabetes.runconfig
という実行構成ファイルが出来上がります。モデル学習時に利用するので大切にとっておきます。
generate-runconfig.py
の中では、モデル学習寺に利用する Environment と計算クラスター環境の名前を指定しています。
from azureml.core import RunConfiguration, Workspace, Environment
ws = Workspace.from_config()
conda_env = Environment.get(ws, 'diabetes-env')
compute_name = 'cpuclusters'
run_config = RunConfiguration()
run_config.framework = 'python'
run_config.environment = conda_env
run_config.target = compute_name
run_config.save(name='diabetes.runconfig')
学習コード
最近個人的にハマっている Explainable Boosting Machines (EBM) を用いてモデルを構築します。実験管理機能の Azure Machine Learning Experiment でメトリックを記録したいので Azure ML Python SDK のメソッドがちょくちょく入っています。
from azureml.core import Workspace, Dataset
from azureml.core.run import Run
from interpret.glassbox import ExplainableBoostingRegressor
from interpret import preserve
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error
import numpy as np
import pandas as pd
import os
import joblib
# メトリック記録開始
run = Run.get_context()
# Workspace のオブジェクト
ws = run.experiment.workspace
# データの準備 (クラウドのストレージのマウント、データダウンロードも可能)
df = Dataset.get_by_name(ws, 'diabetesData').to_pandas_dataframe()
X = df.drop(['Y'], axis=1)
y = df['Y'].values
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=0)
# ハイパーパラメータ
interactions = 10
run.log("interactions", interactions)
# モデル学習
ebm = ExplainableBoostingRegressor(interactions=interactions)
ebm.fit(X_train, y_train)
# モデル精度
preds = ebm.predict(X_test)
mse = mean_squared_error(y_test, preds)
print("mse:", mse)
run.log("mse", mse)
# 結果保存
os.makedirs('outputs', exist_ok=True)
os.makedirs('outputs/html', exist_ok=True)
ebm_global = ebm.explain_global(name='EBM')
preserve(ebm_global, file_name="outputs/html/global-importance.html")
for i in ebm_global.selector.Name:
#print(i)
preserve(ebm_global, i, file_name="outputs/html/"+i+".html")
# モデルファイルの保存
model_name = "diabetes-model.pkl"
joblib.dump(value=ebm, filename='outputs/' + model_name)
手動実行
いきなり GitHub Actions に Azure CLI が動くパイプラインを実装するのは不安なので、まずはインタラクティブに Azure CLI を使ってモデル学習・モデルデプロイを実行していきます。
Azure CLI 実行環境
Azure CLI が動作する環境を準備します。手っ取り早いのは Azure Machine Learning の Compute Instances です。予め Azure CLI と Azure Machine Learning CLI 拡張機能がインストールされています。
その他には
- Azure Cloud Shell
- 自分でインストールする
- Azure Cloud Shell コンテナーを利用する
などの方法が考えられます。自分の開発環境に合っているものを選択してください。
Azure Machine Learning CLI 拡張機能のインストール
Compute Instances 以外の実行環境を選択した場合、デフォルトの Azure CLI に Azure MLの拡張機能が入っていないのでインストールします。
az extension add -n azure-cli-ml
Azure Machine Learning Workspace への接続
まず Azure へログインします。
az login
次に、Azure Machine Learning Workspace への接続情報を取得します。
az ml folder attach -w <ワークスペース名> -g <リソースグループ名>
これを実行すると直下に .azureml
フォルダが作成され、配下に接続情報が書かれた config.json
が出力されます。az ml
コマンドを実行するときはこの接続情報をみて、Azure Machine Learning Workspace を紐付けます。
モデル学習
では、モデル学習を始めます。
az ml run submit-script -c diabetes -e diabetes-exp --source-directory train -t runoutput.json train-diabetes.py
-t runoutput.json
は実験名や runid などのメタデータを runoutput.json
に出力するオプションで、後続の処理のインプットになるので忘れないようにしましょう。
Azure Machine Learnint studio でメトリックを確認しておきます。
また、outputs/html
に変数重要度と各変数の値を予測値との関係を表すチャートを html 形式で出力しています。ダウンロードして確認してみてください。
モデル登録
先ほどのモデル学習は Compute Cluster で実行し、outputs/titanic_model.pkl
にモデルを出力しました。そのファイルを Azure Machine Learning にモデル登録します。先ほど出力した runout.json
から対象となる Experiment を判断しています。
az ml model register -n diabetes-model -f runoutput.json --asset-path "outputs/diabetes-model.pkl" -t registeredmodel.json
登録したモデルは Azure Machine Learning studio からも確認できます。
デプロイ
Azure Container Instances にモデルをデプロイします。
az ml model deploy -n diabetes-stage -f registeredmodel.json --ic deploy/inferenceConfig.json --dc deploy/aciDeploymentConfig.yml -e diabetes-env --overwrite
オプション -f registeredmodel.json
で、前工程のモデル登録のメタデータ (デプロイ対象のモデル名、バージョンetc) を取得しています。
inferenceConfig.json
と aciDeploymentConfig.yml
の中身をみておきます。
inferenceConfig.json
推論環境で実行する Python スクリプトを指定します。
{
"entryScript": "score.py",
"sourceDirectory": "deploy",
}
※ 現在この中に environment
を書くことはできず、az
コマンドの中で指定する必要があります (-e diabetes-env
の部分)。
aciDeploymentConfig.yml
今回は Azure Container Instances にデプロイします。そのスペック (cpu, memory) を指定します。
containerResourceRequirements:
cpu: 1
memoryInGB: 1
computeType: ACI
といきなり ACI にデプロイするコマンドをお見せしましたが、本来はローカルで Debug しながら進めると良いです。
※ 参考
製品ドキュメント: ローカルでのモデル デプロイのトラブルシューティング
GitHub Actions の実装
これで準備万端です!GitHub Actions のワークフローを作成していきます。GitHub Action for Azure CLI をメインに利用していきます。
ワークフロー
実装しているステージをステップの概要です。
シンプルに 3 つの Job から構成しています。
- build : モデル開発
- staging : デプロイ (ステージング)
- production : デプロイ (本番)
コード
もっとスマートな書き方もあるかもしれないですが、私はこんな感じで yml ファイルを書きました。
name: MLOps-CICD
on:
push:
branches: [ main ]
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Azure Login
uses: azure/login@v1
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
- name: Azure CLI Action
uses: Azure/cli@1.0.4
with:
inlineScript: az account show -o table
- name: Check Azure Subscription
run: az account show -o table
- name: AzureML CLI Extension
run: az extension add -n azure-cli-ml
- name: Attach AzureML Workspace
run: az ml folder attach -w azureml -g azureml
- name: Model Training
run: az ml run submit-script -c diabetes -e diabetes-exp --source-directory train -t runoutput.json train-diabetes.py
- name: Model Registry
run: az ml model register -n diabetes-model -f runoutput.json --asset-path "outputs/diabetes-model.pkl" -t registeredmodel.json
- name: Store Metadata
uses: actions/upload-artifact@v2
with:
name: metadata-train
path: |
runoutput.json
registeredmodel.json
staging:
runs-on: ubuntu-latest
needs: [build]
steps:
- uses: actions/checkout@v2
- name: Azure Login
uses: azure/login@v1
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
- name: Azure CLI Action
uses: Azure/cli@1.0.4
with:
inlineScript: az account show -o table
- name: Download Metadata (From Training)
uses: actions/download-artifact@v2
with:
name: metadata-train
path: .
- name: AzureML CLI Extension
run: az extension add -n azure-cli-ml
- name: Deploy to ACI
run: az ml model deploy -n diabetes-stage -f registeredmodel.json --ic deploy/inferenceConfig.json --dc deploy/aciDeploymentConfig.yml -e diabetes-env --overwrite
production:
runs-on: ubuntu-latest
needs: [staging]
steps:
- uses: actions/checkout@v2
- name: Azure Login
uses: azure/login@v1
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
- name: Azure CLI Action
uses: Azure/cli@1.0.4
with:
inlineScript: az account show -o table
- name: Download Metadata (From Training)
uses: actions/download-artifact@v2
with:
name: metadata-train
path: .
- name: AzureML CLI Extension
run: az extension add -n azure-cli-ml
- name: Deploy to ACI
run: az ml model deploy -n diabetes-production -f registeredmodel.json --ic deploy/inferenceConfig.json --dc deploy/aciDeploymentConfig.yml -e diabetes-env --overwrite
Job の間でのメタデータの受け渡しは、アーティファクトを利用しています。actions/upload-artifact と actions/download-artifact で実装しました。
※ 参考
ワークフロー データをアーティファクトとして保存する
おまけ
Azure DevOps Pipeline でも同様のフローを作ることができます。
GitHub Actions がホストする Agent は Azure Pipeline の Fork であるとのことで、yaml の書き方はそこそこ変更が必要ですが仲は良さそうです。
"GitHub hosts Linux and Windows runners on Standard_DS2_v2 virtual machines in Microsoft Azure with the GitHub Actions runner application installed. The GitHub-hosted runner application is a fork of the Azure Pipelines Agent."
まとめ
Azure CLI の Azure Machine Learning 拡張機能を使って、モデル学習・推論環境構築のプロセスを GitHub Actions で実行することができました。
今回はシンプルなケースでしたが、モデル学習のフローが複雑な場合には Azure Machine Learning Pipeline を利用した方が良いかもしれません。仕事でゴリゴリ触っているので、いつか記事にまとめたいと思います。
参考情報
-
Azure Machine Learning ドキュメント
https://docs.microsoft.com/ja-JP/azure/machine-learning/ -
MLOps サンプル集
https://github.com/microsoft/MLOps -
Azure ML CLI チュートリアル
https://docs.microsoft.com/ja-JP/azure/machine-learning/tutorial-train-deploy-model-cli -
GitHub Actions ドキュメント
https://docs.github.com/ja/free-pro-team@latest/actions
Discussion