MLflow on Databricksを試してみた

## 動作環境
* 今回 lightGBMを利用するので、記事作成時点（2020年11月）で最新RuntimeのDatabricks 7.4MLを利用しています

### 追加の外部ライブラリをインストールしたい場合
* クラスターの `Libraries` タブからインストールすることが可能です（7.4MLは既にlightGBMがインストール済み）
![libraries.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23102/7ceb99f9-d84d-f211-5832-b21564e2919d.png)

### MLflow Trackingでモデルの評価をする
* irisデータセットをlightGBMで学習させてみる。Databricksクラスターを起動後、Notebook上で以下のサンプルコードを実行してみます
  * 以下では、自動トラッキングの有効化（`mlflow.lightgbm.autolog()`)をしているため、自動的にパラメータとメトリックがトラッキングされます。

```python
from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score, log_loss
import lightgbm as lgb

import mlflow
import mlflow.lightgbm
def train(learning_rate, colsample_bytree, subsample):

  # データ準備
  iris = datasets.load_iris()
  X = iris.data
  y = iris.target
  X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

  # lightgbmの形式にする
  train_set = lgb.Dataset(X_train, label=y_train)
  
  # 自動トラッキング
  mlflow.lightgbm.autolog()
  
  with mlflow.start_run():

      # モデルを学習する
      params = {
          "objective": "multiclass",
          "num_class": 3,
          "learning_rate": learning_rate,
          "metric": "multi_logloss",
          "colsample_bytree": colsample_bytree,
          "subsample": subsample,
          "seed": 42,
      }
      model = lgb.train(
          params, train_set, num_boost_round=10, valid_sets=[train_set], valid_names=["train"]
      )

      # モデルの評価
      y_proba = model.predict(X_test)
      y_pred = y_proba.argmax(axis=1)
      loss = log_loss(y_test, y_proba)
      acc = accuracy_score(y_test, y_pred)

      # log metrics
      mlflow.log_metrics({"log_loss": loss, "accuracy": acc})
```

* 何回かパラメータを変更して実行してみます

```
train(0.1, 1.0, 1.0)
train(0.2, 0.8, 0.9)
train(0.4, 0.7, 0.8)
```

* Notebookの右上の ①`Experiment`アイコンをクリックすると実験結果②が表示されます
![mlflow_experiment.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23102/2ebb845d-3a72-1178-b332-3b8af7be290b.png)

* ③のボタンをクリックすると実験結果一覧画面が表示されます
![mlflow_experiment_list.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23102/992c1ec5-2e91-87df-0b41-81da726ae5ea.png)

* 実験結果を全選択①して、`Compare`②ボタンを押下すると実験結果の比較画面が表示されます（パラメータの差分と評価指標が一覧で比較することができる） 
![mlflow_experiment_compare.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23102/3bc58804-da5c-f370-7c25-c05d31da02ec.png)

### Model Registryにモデルを登録する
* MLflow Model Registry on Databricksは、モデルのバージョン、ステージ遷移（ステージングから本番への移行）、モデルの説明等をDatabricksのファイルシステム上で管理するモデルレジストリです
* 先ほどのモデル評価結果の比較画面のRunIDをクリックしてモデル詳細画面を表示します
* `Artifacts`の中の`Register Model`ボタンをクリックすることで `Model Registry`へ登録するこができます
![mlflow_register_model.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23102/d76ef165-b86d-6aca-d117-32004799fd73.png)
* 既存のモデル名を指定（version up）もしくは新規モデル名を入力します
![mlflow_register_iris_model.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23102/3af58ef0-1f44-542f-0f66-226b4aa47c17.png)
* 登録されたモデルは `Models`タブから確認することができます
![mlflow_registered_models.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23102/a2aaeb0c-bac7-4775-bafe-59b1e74fcad7.png)

### Model Servingを利用して推論APIを立ち上げる
* `MLflow Model Serving`は モデルレジストリのモデルに対して有効にすると固有の単一ノードクラスタを自動的に作成されて、RESTエンドポイントとして利用することができます。モデルレジストリのバージョンとステージに基づいて自動的にデプロイされます

#### Modelのステージを変更する
* 今回登録したモデルは`version 2`、ステージは`None`となっています。これからステージを`Production`へ変更する要求をします
* モデルレジストリ画面から`version 2`のモデル詳細画面に遷移して `Stage: None`①をクリックして、`Request transition to -> Production`②をクリックします
![mlflow_request_transition.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23102/68a067ef-ecf4-4fb3-cb97-c2db0d563073.png)

* 別のユーザーのモデル詳細画面ではステージ変更要求が表示されています
![mlflow_approve.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23102/69e44aff-732b-7f1a-f36d-98c42dd135a5.png)

* 承認するとステージを変更することができます
![approve_comment.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23102/090946c6-9f9d-11cf-fdb0-2f93b36aa1cf.png)

#### Model Servingを有効にする
* モデルレジストリのモデル詳細画面の`Serving`タブから`Enable Serving`ボタンをクリックすることで有効化することができます
![mlflow_enable_serving.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23102/186b20d0-1127-f8bc-3150-63c312325a4e.png)

* しばらくするとモデルバージョン、ステージ毎にRESTエンドポイントが起動されたことを確認できます
![mlflow_serving_endpoint.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23102/50d7fc16-a7ae-636a-76b9-0fd7c9ac5cf6.png)

#### クライアント側からAPIを利用する
* クライアント側からAPIにアクセスするために、セキュリティトークンを払い出してもらう必要があります
  * 管理者アカウントの`User Setting`画面から`Access Tokens`タブから作成することができます
![mlflow_generate_token.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23102/d74e53ab-ba0c-f9a1-bc58-8f782135da8c.png)


* curlからAPIを利用してみます

```bash
export DATABRICKS_TOKEN={トークン}

cat <<EOF > ./data.json
 [
   {
     "sepal length(cm)": 4.6,
     "sepal width(cm)": 3.6,
     "petal length(cm)": 1,
     "petal width(cm)": 0.2
   }
 ]
 EOF

curl \
  -u token:$DATABRICKS_TOKEN \
  -H "Content-Type: application/json; format=pandas-records" \
  -d@data.json \
  https://dbc-xxxxxxxxxxxxx.cloud.databricks.com/model/iris_model/Production/invocations
[[0.9877602676352799, 0.006085719008512947, 0.006154013356207185]]
```

#### 最後に
* 今回はMLflowをDatabricksのNotebook上から利用できる機能について解説をしてみました。まだまだ紹介できていない機能もあるので、次回まとめてみたいと思います。