Azure で ML Ops をやってみる ～実践編～

#目次
1. はじめに
1. 今回利用するサービス
1. 今回利用するGitHub リポジトリ
1. 実践編
1. 最後に

#はじめに
この記事は株式会社ナレッジコミュニケーションが運営する 
[クラウドAI by ナレコム Advent Calendar 2021](https://qiita.com/advent-calendar/2021/knowcom-cloudai) の12日目にあたる記事になります。

こんにちは！
前回のパートで、機械学習モデルを運用する上での課題と、MLOps の概念について触れました。

https://qiita.com/banana-877/items/9e035d67c679aa87c983

こちらの記事では、どのように Azure サービスを用いて MLOps を実践するのか、手順などをまとめていきたいと思います。

#Azure で MLOps ライフサイクルを実践するためのベストプラクティス
下記の図の5点が、Azure サービスで優れた MLOps 基盤を作るためのベストプラクティスを示した図になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1091796/76680d87-6629-7a51-2a8e-6efb9152f045.png)

1. **再利用できるパイプラインでモデルを作成する**
    * モデリングに利用するデータセットの選択、各種パラメータの設定などもひとまとめにして、モデル作成のプロセスをパイプライン化します。
1. **モデル登録の自動化**
    * イベント駆動型で本番稼働するモデルを変えられるように、メタ情報も含めてモデルのバージョン管理を行います。
1. **監査証左の自動化**
    * テストコードも含めてパイプラインで一元管理します。
1. **モニタリングをともなうデプロイ**
    * 機械学習モデルの再トレーニングのタイミングを見極めるために重要になっていきます。
1. **データドリフトの検知**
    * ドリフトに周期性がみられる場合にはスケジュールベースでのリモデルも考えられますが、基本的にはドリフトの状況を見て再トレーニングを行います。

#今回利用する GitHub リポジトリ
今回利用する Github リポジトリは以下の URL です。

https://github.com/microsoft/MLOpsPython/blob/master/docs/getting_started.md

#実践編
##今回実装するアーキテクチャ図
今回実装する範囲は、以下のアーキテクチャ図の赤枠部分になります。
次項から、実装に移りたいと思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1091796/6eacba67-4c27-f144-1b33-0118a6b122e7.png)

##Azure Pipelineの設定　
###Azure Pipeline設定
Azure Machine Learningとインフラ環境を構築していきます。
以下のアーキテクチャ図の赤枠部分を構成していきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1091796/55e10b36-bafa-d89c-31d7-cbef9a2f73aa.png)

今回のメイン作業スペース、Azure DevOps を開きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1091796/4fd947e8-9e8f-f47a-b51a-8da699d704ff.png)

Azure DevOps 左サイドメニューから Pipelines をクリックします。
今回は大きく分けて3つのパイプラインを構築していきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1091796/fcd82d7b-e386-896c-969a-6a31e9ba2bfc.png)

**1つ目のパイプライン AML-Iac**
Azure Machine Learningを含めた　インフラ環境を構築するためのパイプライン
**2つ目のパイプライン Model Train Register CI**
機械学習モデルの作成・及び登録を行うようなパイプライン
**3つ目のパイプライン Model Deploy CD**
Container Instance 、AKS にデプロイするような CD のパイプライン

###フォークしたリポジトリ
GitHubからリポジトリをフォークします。
フォークしたリポジトリはAzure DevOpsのReposから確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1091796/c7cd378e-3b97-e666-7e09-a774a30419bb.png)

各パイプラインは、例えばモデルの作成を開くと、
diabetes_regression-ci.yml
モデル実行時に利用するような python のスクリプト、
下の階層で利用するような YAML が定義されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1091796/808452a0-cf53-61e8-75d0-777b1c4881da.png)

###変数定義
次に、パイプライン上の変数を設定して行きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1091796/fbf72cd4-631e-b476-45b7-6223b2a48ad6.png)

Pipelines > Library と進みまして、変数のグループを作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1091796/624ac0d7-e1e5-1f94-6bd2-9b12a933dec7.png)

下記画面から、変数名と各種変数を設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1091796/d42cdfc4-f28b-3d3a-feb7-af8d57799959.png)

今回追加した変数は9個です。

* ACI_DEPLOYMENT_NAME / AKS_DEPLOYMENT_NAME
    * これらはそれぞれ ACI と AKS のデプロイの名称になっています。
    
*  AKS_COMPUTER_NAME
    *  推論クラスターの名称で、こちらは Azure Machine Learning側で設定します。

* Azure_RM_SVC_CONNECTION
    * こちらは、Azure パイプラインが Azure Resource Manager を介して、Azure Machine Learning ワークスペースと関連リソースを作成するための接続線です。

* BASE_NAME
    * リソースに名前をつけるためのプレフィックスになっています。

* LOCATION
    * Azure Devops のリソースロケーションを設定しています。

* RESOURCE_GROUP
    * 新規作成するAzure Machine Learning のリソースグループ名を定義しています。

* WORKSPACE_NAME
    * 作成するAzure Machine Learning のワークスペース名を定義しています。

* WORKSPACE_SVC_CONNECTION
    * こちらは、Azure パイプラインが　Azure Machine Learning ワークスペースとの接続を行うためのコネクションです。
    
変数の追加が終わりましたら、次にコネクションを作成していきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1091796/752ce34c-8c15-509b-33cb-ece9abc19c68.png)

###ワークスペース用　コネクションの作成
Azure DevOpsからAzure Machine Learning ワークスペースの展開用のコネクションを作成します。

* Project Settings > サービスコネクションをクリックします。
    * Connection Type には Azure Resource Manager を選択します。
    * 認証方式については、デフォルトのサービスプリンシパルにしておきます。今回はスコープレベルはサブスクリプションとしまして、Resource Group はブランクのままで行います。
    * サービスコネクションネームについては、先ほど変数のところで設定したazure-rm-csv-connection　パラメーターを入れます。

こちらで保存していただくと設定が完了です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1091796/80859b2e-8737-849a-7336-ea90e97f8864.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1091796/a70d8322-f40e-2347-06a1-2803f4cd9556.png)

##Azure Machine Learningとインフラ環境を構築するためのパイプライン構成
Azure Machine Learning とその周辺サービスのインフラを展開するパイプラインを実装していきます。

Pipelines から新規作成をします。
今回利用する YAML ファイルが保存されているReposGitを選択します。
Pipelines > New Pipelines > Azure Repos Git

複数のタイプからパイプラインを選べますが、
今回は existing Azure Pipeline YAML ファイルを選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1091796/4b625223-5144-4aff-8d5c-c7c663cc3afc.png)

こちらはインフラの展開用の YAML ファイルを選択し、Countine をクリックします。> こちらのYAML ファイルが選択されますので、この状態で問題なければ、Run をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1091796/41a51b74-3ec9-0a3b-dc34-c816c7a97a46.png)

###パイプライン実行完了
パイプラインの実行が完了しますとこちらの画面に遷移します。
ジョブを選択しますと、それぞれの工程の実行履歴がこちらに出力されます。
エラーが起こった場合には、ジョブからエラーコードを確認できます。実際にはこちらのエラーコードを見て対処しつつ、パイプラインの実装を進めていくと言う形になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1091796/6696b6e1-c8f0-b168-78d9-790d38f548e6.png)

###実装確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1091796/cec05fe2-ef9a-e327-e44e-ca45cab67906.png)
実際に展開されたリソースグループを見てみますと、Application Insight、コンテナレジストリ、ストレージ、Azure ML ワークスペースと、
これらを連携するための Key Vault が作成されていることが分かります。
こちらでAzure Pipelinesの設定が完了しました。

##1つ目のパイプライン構成　Azure Machine Learning (AML) Model Training CI パイプライン構成
以下のアーキテクチャ図の赤枠部分を構成していきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1091796/9920c534-4d33-d222-e06c-4cf79873a9ce.png)

機械学習モデルの作成・及び登録を行うようなパイプライン構成をします。
Azure DevOps コンソールで作業を進める前に、Azure ML のパイプラインを Azure Pipeline から実行できるようにするエクステンションを入れる必要があります。

###Azure Machine Learning 拡張機能を Azure DevOps にインストール
このURLからAzure Machine Learning 拡張機能を Azure DevOps にインストールできます。

https://marketplace.visualstudio.com/items?itemName=ms-air-aiagility.vss-services-azureml

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1091796/5ce5a1e3-71c9-07d2-8484-7fd8a599b9f4.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1091796/377c67f6-1e65-0547-3379-eb64629e38e5.png)
拡張機能をインストールする DevOps Organizations を選択し、今回はインストール済みとなっていますが、インストールをクリックします。

###Azure Machine Learning ワークスペースとの接続
次に、Azure Machine Learning ワークスペースとの接続を構成して行きます
Project Setting > サービスコネクション > 
先ほどと同様に Azure Resource マネージャーサービスプリンシパルを選択、設定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1091796/2b877a81-68a7-30a4-b64b-1715617e9209.png)

今度はスコープレベルを Machine Learningワークスペースにします。
そして最初のパイプラインで作成した Resource Group、およびワークスペースを選択し、Services Connection Name には、ライブラリで定義した変数　ws-csv-connection のパラメーターを入れ、セーブをします。
これでコネクションの設定は完了です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1091796/5ffe7c94-b0ed-8ef6-bb12-d3cae6b9271f.png)

###機械学習モデルの CI パイプライン実装

以上の構成で Azure Resource のセットアップやサービス接続の構成が完了しましたので、機械学習モデルの CI パイプラインを実装します。

パイプラインから新規作成をクリック、こちらも先ほどの Azure Machine Learning とその周辺サービスのインフラを展開するパイプライン構築と同じように Azure Repos の対象のリポジトリを選択し、Azure Pipeline YAML ファイルを選択します。
そして CI パイプラインの定義がされている YAML を選択しパイプラインの実行をします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1091796/5468ffb4-9ee0-0688-610d-71b368a1fbd8.png)

###パイプラインの実行が完了
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1091796/3d991bb6-6987-e52b-255f-a1d010f94367.png)
先ほどの Azure Machine Learning とその周辺サービスのインフラを展開するパイプライン構築と同じように Job からログを確認できます

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1091796/9bf80475-b4db-7cc7-8f03-46bdafe7ac75.png)
アーティファクトをクリックしますと、

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1091796/2499385f-9a84-d3d1-159a-48b54a6a2c62.png)
実際のパイプラインの成果物をこちらで確認することができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1091796/f4a68258-bf48-c021-7ee1-be949e291cd9.png)
そしてこの後構築する CD パイプラインにおいて、
今回実行したパイプラインの名称を参照しますので、
こちらで Model-Train-Register-CI に名前を変更しておきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1091796/628a9c9a-463b-245f-9b32-1375051219f2.png)
Azure Machine Learning ワークスペースに移動で、先ほど作成したパイプラインの結果を確認できます。

##2つ目のパイプライン実装 Azure Container Instance (ACI) CD パイプライン構成

Azure Container Instance への CD パイプラインを実装します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1091796/cec4f4bf-55d0-4665-97cd-eed425f1a939.png)
こちらのアーキテクチャ図のこちらの部分を構成していきます

CIパイプラインで作成したアーティファクトを用いて、Azure Container Instance にデプロイするパイプラインを実行します。

パイプライン > 先ほどのパイプライン構築と同じ手順で、Azure Container Instance への CD パイプラインを構築します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1091796/adb2f092-860d-1774-f569-758e7ece371a.png)
Azure Repos の対象のリポジトリを選択し、
Azure Pipeline YAML ファイルを選択します。
今回は Regression-cd という YAMLファイルを選択します。
こちらでコンティニューを押すと、パイプラインが実行されます。

###パイプライン実行完了
パイプラインの実行が完了すると、この画面に遷移します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1091796/7d62374a-3bfd-6314-a10a-2d05e1ca9c5b.png)
AKS の設定がされていない場合には、パイプラインの Deploy to AKS > こちらの工程はスキップされます。なので、現状 ACI のみにデプロイされている状態です。

また、基本的には、最新のモデルをデプロイしますが、特定のバージョンのモデルをデプロイしたいという場合もあるかと思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1091796/4a0e457d-cd4a-06c1-b664-517621410715.png)

その場合には Deploy to ACIから
Parse json を選択、こちらからモデルのIDを明示することで、
ACI にデプロイされるモデルを変更することが出来ます。

次に、Azure Machine Learning ワークスペースから、AKS 上の推論コンテナを用意します。

##AKS 上の推論コンテナを用意
Azure Kubernetes Services (AKS) クラスター構成をします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1091796/cb166a40-0538-56c6-7467-9e717bf3137e.png)
こちらのアーキテクチャ図のこちらの部分を構成していきます

###Azure Kubernetes Services (AKS) クラスター構成
Azure Kubernetes Services (AKS) クラスター構成をします。
Azure Machine Learning Studioに移動します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1091796/60ac5287-ea50-affb-dfcb-48e56b89b13f.png)

コンピューティング > 推論クラスター > 新規作成をクリックします。
コンテナのリージョンを 東日本（Japan East）に設定します。
クラスタで使用するVMのサイズ、こちらはds2で設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1091796/9abac84e-e782-7a84-7080-b2e839fd43d5.png)

コンピューティング名は Azure DevOps で設定した変数名の　mlops4-inferenc　パラメーターと同じにします。

コンピューティング名を入力したら、作成をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1091796/7c993445-fd5f-e127-4d20-0611642d786e.png)

##3つ目のパイプライン構成　Azure Kubernetes Services (AKS) CD パイプライン構成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1091796/a0b37f12-acf6-df2f-28e7-5a396fce41e0.png)
アーキテクチャ図のこちらの部分を構成していきます

作成した本番用推論クラスタに CI パイプラインで作成した機械学習モデルをデプロイする Pipeline を実行していきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1091796/fc80599b-b21e-5deb-95bb-5027ebe8ae12.png)
アジュールコンテナインスタンスにモデルをデプロイしたときのパイプラインを再利用します。
こちらで Run New をクリックします。

###パイプライン実行完了
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1091796/de959372-a646-d275-0c13-7a1b03439c86.png)
処理が完了しますとこのように AKS のデプロイが完了します。


##Azure Machine Learning の Data Drift Monitor 機能
最後に Azure Machine Learning の Data Drift Monitor 機能でドリフトを検知できるような仕組みを作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1091796/fc513e42-3a13-b215-78ec-08dc371c900a.png)
こちらのアーキテクチャ図のこちらの部分を構成していきます

ターゲットのデータセットを監視して、データ誤差の割合が設定されたしきい値を上回る場合にメール アラートを送信するなどの設定が行えます。

**ドリフトを検知**
推論時点でのデータが学習時点のものと許容範囲を超えて変化することをデータドリフトといい、モデルの推論精度の低下などの影響を及ぼし、機械学習モデルの劣化を引き起こします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1091796/9d153d15-5450-1529-0f7f-6812a787485e.png)

ドリフト検知機能を作成する場合、2種類のデータセットが必要になります。
・モデルの学習に利用したデータセット
・実際の値を含むデータセット　が必要です。
　・実際の値を含むデータセットには、時系列カラムが必要になります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1091796/0b980da6-a883-2079-ca89-94cebf89c71d.png)

データセットモニター（プレビュー）をクリックし、モニターの作成をします。
まず、機械学習の結果を含むデータセットを選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1091796/86d87490-3e82-f037-27d4-709a151fc94c.png)
次に、Baseline Data Set、比較対象のデータセットはモデルの作成に利用したデータセットを選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1091796/c2e56b5c-b13e-7273-7556-29feb4f2fd71.png)
・モニターの名前を入力
・機能から、モニタリングしたい指標を選択
・コンピューティング先を設定

・データセットに対するモニタリングの頻度、データ誤差の割合のしきい値の設定、
アラートメール通知先の設定が行えます。

こちらで設定が完了です。作成をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1091796/d01b3170-c072-881e-1c3f-4239ad83d0aa.png)

ドリフトのトラッキングはこのようなダッシュボードで監視可能です。
データサイエンティスト以外のエンジニアもトラッキングしたい場合には、Azure Application Insight と連携するのがいいと思います。
以上で、Azure で MLOps 実装パートを完了します。

#最後に
ここまでご覧いただき、ありがとうございました！
機械学習モデルの運用に困ったら、ぜひ MLOps を取り入れてみるといいかなと思います。