ユーザ企業でのAIシステム開発の内製化（Azure ML × Power Platform）

# 本記事の目的
ユーザ企業（非IT/AI企業）であっても、社内でデータサイエンティストや機械学習エンジニア（本記事では区別せず「AIエンジニア」と呼ぶ）の育成に力を入れている企業は増えている。データが貴重な経営資源と言われる中で、そのデータを外部に出すことなく、またデータに関する背景知識もある社内人材がスピード感を持ってデータサイエンスに取り組めるメリットは確かに大きい。

外部ベンダーへのプロジェクト発注となると、権利関係等を含む契約締結など、何かと時間がかかりスピーディに動きづらくなる可能性もある。もし簡易的な概念検証（PoCレベル）のための実装だけでも社内で開発を完結できれば、企業の競争力向上に大きく寄与するはずだ。

一方で、ユーザ企業でのAIシステム開発の内製化には難しさもある。私の所属する組織でも、簡易的なPoCプロジェクトであってもアプリケーション化（UI/UX）が求められる場合にはなかなか内製化が難しかった。今回、Microsoft社の「Azure Machine Learning Service」「Power Platform」を実際に利用してみて、AIシステム内製化の実現手段のひとつとして使えそうな手ごたえを得たので、備忘も兼ねて記事に残す。

結論だけ先に書くと

###本記事の結論

- Azure Machine Learning Serviceで、開発したAIモデルのデプロイが比較的簡単にできる
- Power Platformで、アプリケーション開発が「利用部門側で」比較的簡単にできる
- これらを組み合わせることで、社内でうまく役割分担をしながら、AIシステム開発内製化のハードルを下げることができそう


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/596092/f8b250ff-2fec-b1a7-4f52-0194cc6274f4.png)




# なぜAIシステム開発の内製化が難しいか

AIシステム開発の内製化が難しい理由のひとつは、その構成要素が多いことにあると思う。AIシステムを開発してリリースしようとすると、少なくとも下の図に示すような要素が必要になる。必要となる技術スタックの幅が広いため、自社のチーム内で要素を網羅することが難しい。

＜AIシステム開発の要素＞
1. AIモデルを適切に構築・学習して開発する（AIエンジニア的な要素）
2. 開発したAIモデルをデプロイする実行環境を構築する（データエンジニア的な要素）
3. AIモデルを利用したアプリ（GUI）を開発する（アプリケーションエンジニア的な要素）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/596092/e857bec2-d5ed-f814-dd9a-6a4d39aea6e4.png)



各企業でAIエンジニアの育成が進んでいるが、AIエンジニアが一般に得意とするのは1番目のAIモデル開発の部分であって、2や3の領域はどちらかと言えば従来のITエンジニアが得意とするスキルのように思える。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/596092/75f9dca4-8a86-c911-a7ad-6e41eb701da3.png)

もちろん、一部のAIエンジニアはdjangoやflask（またはより簡易的にはStreamlitなど）を用いたアプリケーション開発のスキルまで保有している。ところがアプリケーションは画面設計をはじめとして継続的な修正改善が求められる可能性が高いため、ここにAIエンジニアが関わりはじめると「AIモデル構築・開発」に使える時間がどんどん奪われてしまう。やはりAIエンジニアはAIモデルの開発に注力し、ユーザインターフェイスの開発は基本的に担わないようにしたい。

以上を踏まえると、上記の1~3をどのように社内人材で分担して担えるか、というのが内製化のカギになるように思う。

# AIシステム内製化のための組織体制
内製化を行う場合に、どのような組織体制で分業を進めるべきかについて考えてみた。記事タイトルにあるように、Microsoft社のAzure Machine Learning × Power Platformをフル活用することを前提としている。

簡単に書けば、以下のような考え方である。

- AIモデルを開発し、そのモデルを稼働させるための環境を構築しデプロイする（AI APIの提供）までをAIエンジニアが行い、
- 開発されたAI APIを使いながら、アプリケーション（特に画面設計部分）は現場のニーズを汲んで実務部門で開発する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/596092/e5be2432-d630-5583-c895-a30bfdf65e98.png)


従来型のシステム（緻密な要件定義を実施後、ウォーターフォール開発を行い、高品質なソフトウェアを長期間利用し続ける）と比較すると、AIシステムの寿命は短い傾向がある。したがってAIシステム開発においては「いかに高速に開発・リリースできるか」という観点がより重要だ。この点、Azure Machine Learning ServiceやPower Platformを用いた開発は相性が良いと思う。

# AIシステムの内製開発の流れ
実際にAzure Machine Learning ServiceとPower Platform(Power Apps, Power Automate)を利用して、簡単なAIの開発からリリースまでのシナリオを確認する。ここでは画像分類AIをベースに考える。

実際のところ画像分類だけであれば、Microsoft Custom Vision Serviceなどを使うことで、ユーザ側で作りこみをせずに利用することも可能だ。ただ将来的な拡張性や柔軟性も考慮し、自らモデルを構築することを想定する。

以下に構成のイメージを示す。左半分が主にAIエンジニアがAzure Machine Learning Serviceを使って開発を担う部分で、右半分が主に実務ユーザがPower Platformを使って開発を担う部分。以降の章では、各フェーズについて具体的に説明する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/596092/eeef9053-ce16-8179-c4b2-fa366f1b46d8.png)



## 1. AIモデルの開発・構築

社内のAIエンジニアが、Azure Machine Learning Service上でNotebookを用いて開発を行う。Azure Machine Learning Serviceでは「Azure Machine Learning Python SDK」を使うことでログの記録やデプロイ等を行うことができる。またNotebook以外にもAI開発のインターフェイスが2つ（Auto ML, Designer）用意されており、経験の浅いAIエンジニアが開発を担う場合などはこちらも利用できる。

今回は、最も柔軟性が高くローカルからの移行もしやすいメリットを考慮してNotebookを前提に考える。チュートリアルとして画像分類（手書き文字認識）のサンプルコードと説明が公式で用意されている。

- img-classification-part1-training.ipynb

> チュートリアル:MNIST データと scikit-learn を使用して画像の分類モデルをトレーニングする
https://docs.microsoft.com/ja-jp/azure/machine-learning/tutorial-train-models-with-aml

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/596092/7154c6d3-74f3-6473-6e8d-16babe44d721.png)

## 2. モデルのデプロイ

AIモデルのデプロイ手順についても、公式で続編としてサンプルコードが用意されている。

- img-classification-part2-deploy.ipynb

> チュートリアル:Azure Container Instances に画像分類モデルをデプロイする
https://docs.microsoft.com/ja-jp/azure/machine-learning/tutorial-deploy-models-with-aml

利用にあたっては前述した「Azure Machine Learning Python SDK」の使い方を理解する必要があるが、Azure Container Instance(ACI)やAzure Kubernetes Service(AKS)へのデプロイを、Conteinerなどの知識がなくとも比較的簡単に実現することができる。なお上記のサンプルコードではACIへのモデルデプロイを行っている。

### APIの実装で考慮が必要な点
基本的にはサンプルコードがそのまま利用できるのだが、後の利用を考えてAPIの仕様を少し変更しておく。

サンプルコードでは、APIは画像を以下のようなJSON形式で受け取る仕様になっている。（X_test[random_index]は各ピクセルの値を持つnumpy.ndarrayの2次元配列）

```python:img-classification-part2-deploy.ipynb
input_data = "{\"data\": [" + str(list(X_test[random_index])) + "]}"
```

具体的には以下のようなイメージになる。画像に対して各ピクセルの値を並べた形である。
> {"data": [[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.3058823529411765, 0.6196078431372549,...（省略）, 0.0, 0.0, 0.0]]}

一方で後の利用を考えると、base64形式で画像を受け取れるようにしたい。具体的には以下のようなイメージ。
> iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAYAAAByDd+UAAAAAXNSR0IArs4c6QAAAARnQU1BAAC...（省略）

そこでサンプルコードに対して、base64形式からの変換処理を追加しておく。変更箇所はrun()。

```python:score.py
%%writefile score.py
import json
import numpy as np
import os
import pickle
import joblib
import base64
from PIL import Image
from io import BytesIO 

def init():
    global model
    # AZUREML_MODEL_DIR is an environment variable created during deployment.
    # It is the path to the model folder (./azureml-models/$MODEL_NAME/$VERSION)
    # For multiple models, it points to the folder containing all deployed models (./azureml-models)
    model_path = os.path.join(os.getenv('AZUREML_MODEL_DIR'), 'sklearn_mnist_model.pkl')
    model = joblib.load(model_path)

def run(raw_data):
    base64_img_bytes = raw_data.encode('utf-8')
    decoded_image_data = base64.decodebytes(base64_img_bytes)
    img = Image.open(BytesIO(decoded_image_data))
    img_array = [np.asarray(img)[:,:,0].reshape(-1)]
    y_hat = model.predict(img_array)
    # you can return any data type as long as it is JSON-serializable
    return y_hat.tolist()

```

これでbase64形式の画像入力に対して推論を行い結果を返すWeb APIの準備ができた。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/596092/15f89eb8-e18c-db0f-6bc4-e3e7a91fbcad.png)


## 3. Webサービス（API）の呼び出し機能の開発

Power AppsからWeb APIでAIモデルを呼び出したいが、これはPower Automateを利用することでノーコードで実現ができる。Power Automate上で用意されている「Power App から Web サービスを呼び出す」というテンプレートを利用する。

> Power App から Web サービスを呼び出す
https://flow.microsoft.com/ja-jp/galleries/public/templates/edfa8fde25644f149448c8d8cff44699/call-a-web-service-from-a-powerapp/
![web.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/596092/fcf7922c-e2bc-37d5-d690-708d448d1818.png)


やることはシンプルだ。①Power Appsから受け取った値を取得した後、②APIに問合せて結果を取得し、③結果をPower Appsに返す、という流れになる。Power Automate上の3ステップがこれらにそれぞれ対応する。具体的にはAzure Machine Learning Serviceでサービスをデプロイした時に発行されたURL（サンプルコード内のservice.scoring_url）と渡したいデータ（画像をbase64の文字列に直したもの）で問い合わせるだけ。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/596092/4ebf87b9-5a29-a3fd-073f-2bf465f3b5bb.png)

ちなみに返す値はHTTPステップの出力結果を渡したいので、「actions('HTTP').outputs.body」としておく。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/596092/8f6bf242-a588-ea1d-0f59-ec772f5e4e55.png)

## 4. ユーザインターフェイス（UI）の開発
最後に、ユーザが直接利用するアプリケーション部分をPower Appsで開発する。既に述べたように、ここは基本的に実務部門で開発・管理していく体制にしたい。ただしはじめの雛形だけは、APIの仕様を把握しているAIエンジニアの方から提供しても良いと思う。

必要となる画面は、画像のアップロード後にボタンが押下されたときにPower Automateを起動して問合せをして、返ってきた値を表示するというシンプルなもの。Power Automateへのデータの受け渡し方法については以下の動画が分かりやすく参考になるため、ここでは説明を割愛する。

> はじめての PowerApps 第 8 回 - Microsoft Flow の応用編
https://www.youtube.com/watch?v=TD8d9mPrC4k&t=308s

実際にできたアプリのイメージを下で示す。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/596092/5d0a85d8-a0b3-96c0-9883-23591212248b.png)


開発中なのでUIはこれから整えていく必要があるが、最低限の機能として以下が備わっていることが分かると思う。

- 画像をアップロードする
- アップロードした画像をbase64形式に変換する
- 確認用にbase64のエンコード結果を表示する
- URLと画像データ（base64）を使ってAPIを叩く
- APIからの返り値（予測結果）を表示する

今回は分かりやすいようにbase64への変換ボタンとAPIを叩くボタンを別々に用意したが、ユーザとしてはbase64のエンコードされた値に興味はないはずなので、当然これらのボタンは統合しても良い。

なお参考までにbase64 encodingとHttp Requestそれぞれのボタンではそれぞれ以下のように設定した。

```PowerApps:base64decoding
OnSelect = Set( ImageJSON, Substitute(Last(Split(JSON( UploadedImage1.Image, JSONFormat.IncludeBinaryData ), ",")).Result, """", ""))
```

```PowerApps:HTTPRequest
OnSelect = Set(ImageClass, 'PowerAppからWebサービスを呼び出す(mnist)'.Run(URL, ImageJSON))
```

あとはユーザビリティが高くなるように、実務部門ユーザの方で好きなようにアプリの画面を作りこんでいけばよい。

# まとめ
今回は画像分類AIの開発をベースに、AI開発の内製化のシナリオを確認しました。Azure Machine LearningもPower Appsも利用経験が浅く理解しきれていない部分も多いですが、これらを組み合わせることでAI開発の内製化ができる感覚はつかめました。特にPower Appsはユーザサイドでのアプリケーション開発が可能になるため、PoCプロジェクトでのプロト開発などにも気軽に利用しやすく、AIシステム開発プロジェクトの相性が良いと感じました。

多くの企業がAIエンジニア育成にチャレンジしている一方で、折角のAIエンジニア（またはその候補）に本来AIエンジニアにさせるべきでないスコープの仕事をさせたり、そもそもAIエンジニアのスコープ自体が曖昧だったりすることが多いように思えます。そのような環境ではAIエンジニアが専門性を磨く機会を十分に与えられず、離職につながる場合もあると思います。

今回はアプリケーション開発に関わる部分だけを取り上げましたが、AIプロジェクトのタスクは幅広いです。特にAIに未成熟な企業ではAIエンジニアが何でも屋になってしまいやすいと思いますが、少しずつでも自社のAIエンジニアが担うべきスコープを定義して、AIエンジニアが本来の業務に専念できる体制を作って組織全体の生産性を上げられると良いと思いました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/596092/c41a68f4-259a-06cd-9a7b-2ee171da89bd.png)