Azure Machine Learningからの機械学習モデルのデプロイ(Local/ACI/AKS)

# 本記事の目的

先日、Azure Machine Learningで開発した機械学習モデルを初めてデプロイした。

Azure Machine Learning自体使い慣れていなかったので苦労したが、最終的には[こちらの記事](https://qiita.com/ryokita/items/25f2a376e94e6bee6db4#2-%E3%83%A2%E3%83%87%E3%83%AB%E3%81%AE%E3%83%87%E3%83%97%E3%83%AD%E3%82%A4)で書いたように、ACIにデプロイしてPowerAppsからPowerAutomate経由でAPIを叩く形で利用できるようになった。

今回モデルのデプロイするにあたって勉強したところや躓いたところを残しておく。

# デプロイ先の選択肢
Azure Machine Learningではデプロイ先として次の3つの選択肢がある。
基本的に下に行くほど機能はリッチだが高価。

1. Local
2. Azure Container Instance(ACI)
3. Azure Kubernetes Services(AKS)

### Local
基本的にテスト目的での利用。

Notebookを実行しているコンピューティングインスタンスから、同じVM上にモデルをデプロイする。他のリソースを利用するわけではないので、特に追加のコストは発生しない。

モデルができたらとりあえずローカルにデプロイして、API応答がうまくいくかのテストにのみ利用していた。

```python:local_deploy.ipynb
from azureml.core.webservice import LocalWebservice
# This is optional, if not provided Docker will choose a random unused port.
deployment_config = LocalWebservice.deploy_configuration(port=6789)
local_service = Model.deploy(ws, "test", [model], inference_config, deployment_config)
local_service.wait_for_deployment()
```

### Azure Container Instance
簡易的なデプロイで問題ない場合に利用。

今回の開発ではモデルが比較的軽量で冗長構成も必要なかったため、最終的にACIでデプロイした。

開発途中、ACIにデプロイしたエンドポイントにrequests.post()で問合せをした際に、なぜか502 Bad Gatewayのエラーが返ってくるという事象があった。どうやらACI側の負荷が問題となっていたようで、ACIのメモリサイズを上げることで解消できたが、もし解決できなければAKSを利用していた。（AKSでは全く問題なく動いていた）

負荷と費用の観点から見ると、まずはACIのメモリサイズを上げることで対応、それでも対応ができない場合はAKSに変更する、という流れになりそう。なお[公式ドキュメント](https://docs.microsoft.com/ja-jp/azure/machine-learning/how-to-deploy-azure-container-instance#deploy-to-aci)によるとACIでのモデルのサイズは1GB未満が推奨されているので、基本的にこれ以上であればAKSを利用することになる。

またACIにデプロイした時のコンテナインスタンスの課金で、分かりづらい点がある。

1. コンテナインスタンスの費用はメモリとvCPUのサイズによって決まる
2. メモリは小数点第二位で切り上げされるのに対し、vCPUは小数点第一位で切り上げされる
3. ACI上には明示的に作成したコンテナの他に、「azureml-fe-aci」というコンテナが自動生成される
4. 「azureml-fe-aci」のコンテナサイズはメモリ0.5GB、vCPU 0.1である

「azureml-fe-aci」は推論実行要求を受け付けるフロントエンドポイントで、自動的に生成される。
![ACI.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/596092/5d87cab8-8f25-92a2-7ce4-3196d4a3312e.jpeg)
つまり、自身が明示的に作成したコンテナサイズが例えばメモリ1GB、vCPUが1.0だとすると、「azureml-fe-aci」と合計でメモリ1.5GB、vCPU 1.1となる。この時、vCPUは小数点第一位の切り上げなので、vCPU 2.0分の課金となってしまう。作成するコンテナサイズは0.9 vCPUとか1.9 vCPUとかにした方が良い。

```python:aci_deploy.ipynb
from azureml.core.webservice import AciWebservice, Webservice
from azureml.core.model import Model
deployment_config = AciWebservice.deploy_configuration(cpu_cores = 1, memory_gb = 1)
service = Model.deploy(ws, "aciservice", [model], inference_config, deployment_config)
service.wait_for_deployment(show_output = True)
print(service.state)
```

### Azure Kubernetes Services(AKS)
スケール可能な本番環境向けの利用。

高速な応答時間、負荷に応じた自動スケーリング、認証機能など高性能。さらにIPアドレスの範囲によるアクセス制限やロールベースのアクセス制御も行える。ただしACIと比較してコストは高くなる。

自動スケーリングや認証機能は本番リリースする場合には必要だと感じたが、今回はPoC目的のモデル開発＆リリースということでコスト面を重視してACIを選択した。なお、利用しない時間帯は[Azure Automationを使ってAKSを停止する](https://zenn.dev/08thse/articles/04-auto-start-aks-by-azure-runbook)といったこともできるらしい。

AKSで利用する推論クラスタはGUIで作成することができる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/596092/754d87f4-a5a6-83cd-399e-726d9da4c053.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/596092/c6166227-ae7e-09e2-d634-4c3ee5d70fa3.png)


```python:aks_deploy.ipynb
from azureml.core.webservice import AksWebservice, Webservice
from azureml.core.model import Model
from azureml.core.compute import AksCompute
aks_target = AksCompute(ws,"myaks")
# If deploying to a cluster configured for dev/test, ensure that it was created with enough
# cores and memory to handle this deployment configuration. Note that memory is also used by
# things such as dependencies and AML components.
deployment_config = AksWebservice.deploy_configuration(cpu_cores = 1, memory_gb = 1)
service = Model.deploy(ws, "myservice", [model], inference_config, deployment_config, aks_target)
service.wait_for_deployment(show_output = True)
print(service.state)
print(service.get_logs())
```

# おわりに
Azure MLでは機械学習のワークフローはAzure Machine Learning SDKを使って実行しますが、公式ドキュメント以外の「やってみた」系の情報がWeb上であまり見つからず、また私自身コーディング自体にも不慣れなところが多かったため、わりと苦労しました。（Microsoft社のサポートの方々に相当助けられました...感謝です！）

AKSやコンテナといった知識もなかったためモデルのデプロイまで実装できるか不安でしたが、Azure Machine Learningの機能を活用を利用することでなんとか実現できました。特にデプロイ先について、Local/ACI/AKSとコードを少し変更するだけで簡単に切り替えることもできたのは、とても便利で感動しました。

機械学習モデルの開発からデプロイまで、Azure MLのNotebookで全て完結できるのは便利だと思うので、引き続き勉強しながら利用していきたいと思います。