初見 Databricks on GCPを使ってわかったこと

会社のAIプロジェクトの中で、Modelの管理を以下の条件を満たすような条件でしたいと考えてそれにあうMLOpsサービスを探していました。

- 定期的にデータを学習させ得られたModelをバージョニングして管理したい
- それぞれのModelで簡単にDeployしてAPI化させRESTでアクセスできるようにしたい。
- できるだけ管理画面は簡単なUIでありたい。

上記の結果に合うもので、以前Udemyで勉強したこともあって、MLFlowで管理できないかを考えました。

ちなみにMLflowを高速で学べるコースは以下

https://www.udemy.com/course/ml-ops-beginner/

話はさておき、MLflowを選択したとはいえ、更なる以下の課題が発生します。

- AI Modelはサービスの一部で使用し、そのサービス全体はGCPで稼働してるので、MLflow及び学習等もGCPの中で稼働させて管理したい。

- MLFlowを立てるにしても、MLflowで要求されるインフラを用意したりする時間はあまりかけたくない

これを満たすような条件は、MLflowの開発元である、DataBricksをGCPで動かすことでした。
DataBricksを使用することでMLflowをマネージドで使用できます。

https://www.databricks.com/jp

幸いにもDataBricksをGCPで動かすマーケットプレイスがあったので

https://cloud.google.com/databricks?hl=ja

決定したは良いが、コスト感がわからなかったので、

`Databricks on GCP`の2週間のトライアルを申し込んで使い勝手を調べてみました。
`ジョブ$0.07/DBU`など、どれぐらいかがピンと正直きませんでした。

![スクリーンショット 2023-12-21 2.49.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1466470/81d111a1-859d-5e52-2cdf-113c20f7f14b.png)


![スクリーンショット 2023-12-21 2.48.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1466470/0a813ea0-9849-ddae-fd9d-084aff1f5e3c.png)

というわけで、当記事では、`Databricks on GCP`を初心者が使ってみた感想を書いてみたいと思います。

## 最低限成し遂げたいアーキテクチャの構想

学習コードを定期実行処理させるためのDatabricks上での仕組みとかは一旦おいておいて、
最低限の理想系については、
- jupyterNotebookで学習コードを管理
- mlflowにmodelやmetrics情報を送ってmlflowマネージドで管理を行う
- mlflowから推論用endpointを排出する。

![test.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1466470/b318f059-aab8-c4c1-54bb-351ac1ecb965.jpeg)


## スタート

DataBricks on GCPを立ち上げると、最初にworkspaceを立ち上げる。実際にworkspaceを立ち上げるとメールの中にアクセスURLが届く。

![スクリーンショット 2023-12-21 3.05.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1466470/287e0525-549f-0e3a-ca1d-ff625af04da4.png)

URLを開くとworkspaceが開くが、まず、何をしていいかわからないから始まる。
(Pick up where you left offは後から私が追加したもの)

![スクリーンショット 2023-12-21 3.04.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1466470/cb200b89-850d-4403-d1b1-041def917dd5.png)

GCPのconsoleを見たら、DataBricks用のGKE Clusterが出来上がっていた。どうやらこのGKE中でコントロールされるらしい。

![スクリーンショット 2023-12-21 3.09.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1466470/de2c76f8-fb2a-8887-5277-f3bb6d6f5eed.png)

##### まず、何していいかわからない....
youtubeと記事でやりかを調べてみるがよくわからない。というか、説明をしてる記事が少ない。...AIアシスタントとかそうゆうのじゃなくて基本的な使い方についての説明が少なくて困った。

そして行き着いたのがこの記事で一番わかりやすかった。

https://docs.gcp.databricks.com/en/machine-learning/manage-model-lifecycle/workspace-model-registry.html#register-an-existing-logged-model-from-a-notebook

まず、左サイドバーがなんの役割とどのように連携するかがわからなかったので調べ上げたところ、

![スクリーンショット 2023-12-21 3.21.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1466470/0163fc50-3a5f-7c59-dda1-39ac1d59f725.png)

さらに、実際にworkspaceでコードをrunさせるときに、どこのサーバーで動かすかを決定するために`Compute`というところで、instanceを作る。

![スクリーンショット 2023-12-21 3.35.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1466470/9c20f3a3-b8a5-6318-7848-75205c9997ad.png)

##### 基本Computeで立てたinstanceでJupyterのコードを動かすみたい
実際にGKE上の動きとしては、DataBricks GKE Cluster上に指定したスペックのinstanceがGKEのノードとして追加されるみたいです。

![スクリーンショット 2023-12-21 3.37.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1466470/7037e697-75c1-43ce-c2b8-fee61db0556b.png)

追加されたNodeの中に自動でPodがapplyされて、下記のPodが立ち上がるまで、待ちになります。


![スクリーンショット 2023-12-21 3.38.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1466470/b964971d-9408-7d6c-e33f-cd637b7b564c.png)

##### Workspaceで、コードを書いて、書いてる中で実行した時に、発生したmetricsをExperimentsで収集して、Modelsで実際にmodel化してdeployを行うらしい。

実際にworkspaceでnotebookを作って`Compute(Databricks上の指定したスペックのinstanceで動くnode)`を選択する画面

![スクリーンショット 2023-12-21 3.44.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1466470/5b0c446f-a4cd-8841-1935-cb08a164ca1f.png)

##### workspaceとExperimentsの連携は、Workspaceの右バーのMLflowのexperimentsのコピーマークから連携できる。

![空白の図(19).jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1466470/732df8b8-c85f-2380-e284-71de5df249d8.jpeg)

この連携が完了すると、jupternotebookで以下のようなmetircsを送ったときに、Experienceの
DashBoardで可視化されるようになる。

```Python
mlflow.log_param("training_percentage", 70)
mlflow.log_param("dataset shape", training_data.shape)
```

![スクリーンショット 2023-12-21 4.12.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1466470/37e17f02-fae3-c24a-7e65-eae14ea4e095.png)

![スクリーンショット 2023-12-21 4.15.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1466470/a9f2ab5e-b560-bb00-3527-8b14fb6fe0a1.png)

##### Experimentsから、ModelをDeployする
jupyternotebookで、modelのアーキテクチャを以下で送ったら(コードは最後に貼ってあります。)
Experienceでmodelをregisterできるようになります。

```Python
mlflow.sklearn.log_model(classifier, "model")
```

![空白の図(20).jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1466470/2c85fc68-83c8-0111-580b-779322aa05e5.jpeg)

![スクリーンショット 2023-12-21 4.26.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1466470/ccc5c3f8-febb-cbe5-fbfa-527636e92d1b.png)

Legacy ServingというTabよりAPI Endpointを有効化します。


![スクリーンショット 2023-12-21 4.27.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1466470/bf7092f7-ef7f-f07c-7f51-4377ca9e7300.png)

実際にEnableにすると、APIが用意されて、アクセスとmodelごとにできるようになるみたいです。

![スクリーンショット 2023-12-21 4.29.31 1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1466470/1e367476-c6d4-5a7d-07a2-865d9409a44d.png)

##### 一旦ここまで！

次の記事では、定期実行とか実際の運用とか実際のコストとかを書きます。多分

あと、学習後のcomputeを消し忘れるとコストがとんでもないことになるので、消すのは忘れずに

![スクリーンショット 2023-12-21 4.34.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1466470/460424ac-1789-cb6b-8250-24401120b432.png)

次はこちら

https://qiita.com/magisystem0408/items/08ccc90c22c9beba84fb


今回、DataBricks上で、Model-API化するコードは以下で試してみます。

https://github.com/magisystem0408/mi_ops_exer/blob/main/ml_pipeline_mlflow.py

下記のsampleコードをdatabricks上においたときに、肝心のデータ部分である`storepurchasedata.csv`が`workspace/`のnotebookのおいた同ディレクトリに置かないと動かないので注意ください。

```python
import numpy as np
import pandas as pd
import mlflow
import mlflow.sklearn

# mlflow.set_experiment(experiment_name="mlflow demo") 
#NOTE:これは、DataBricksでコピーiconを押したときにやってくれるのでいらない。

training_data = pd.read_csv('storepurchasedata.csv')
print("Loaded training data")

training_data.describe()

mlflow.log_param("training_percentage", 70)
mlflow.log_param("dataset shape", training_data.shape)

X = training_data.iloc[:, :-1].values
y = training_data.iloc[:, -1].values

from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=.70, random_state=0)

from sklearn.preprocessing import StandardScaler

sc = StandardScaler()
X_train = sc.fit_transform(X_train)
X_test = sc.transform(X_test)

print("Completed Feature Scaling")

from sklearn.neighbors import KNeighborsClassifier

# minkowski is for ecledian distance
classifier = KNeighborsClassifier(n_neighbors=5, metric='minkowski', p=2)

# Model training
classifier.fit(X_train, y_train)
print("Model training")

y_pred = classifier.predict(X_test)
y_prob = classifier.predict_proba(X_test)[:, 1]

from sklearn.metrics import confusion_matrix

cm = confusion_matrix(y_test, y_pred)

from sklearn.metrics import accuracy_score

model_accuracy = accuracy_score(y_test, y_pred)
print(model_accuracy)

# send mlflow model_accuracy data
mlflow.log_metric("accuracy", model_accuracy)

# send mlflow modelArch
mlflow.sklearn.log_model(classifier, "model")
```


## 次は、workspace内でのgit管理方法について

https://qiita.com/magisystem0408/items/08ccc90c22c9beba84fb