🐷

コマンドラインでの機械学習 (AzureML + GitHub Actions)

2021/01/05に公開

機械学習のモデル学習とデプロイのプロセスを自動化すべく、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 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.jsonaciDeploymentConfig.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 で実装しました。

※ 参考
ワークフロー データをアーティファクトとして保存する
https://docs.github.com/ja/free-pro-team@latest/actions/guides/storing-workflow-data-as-artifacts

おまけ

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."
https://docs.github.com/en/free-pro-team@latest/actions/reference/specifications-for-github-hosted-runners#cloud-hosts-for-github-hosted-runners

まとめ

Azure CLI の Azure Machine Learning 拡張機能を使って、モデル学習・推論環境構築のプロセスを GitHub Actions で実行することができました。

今回はシンプルなケースでしたが、モデル学習のフローが複雑な場合には Azure Machine Learning Pipeline を利用した方が良いかもしれません。仕事でゴリゴリ触っているので、いつか記事にまとめたいと思います。

参考情報

Discussion