Unity Catalogにおけるモデルライフサイクルの管理

[Manage model lifecycle in Unity Catalog \| Databricks on AWS](https://docs.databricks.com/machine-learning/manage-model-lifecycle/index.html)[2023/7/3時点]の翻訳です。

:::note warn
本書は抄訳であり内容の正確性を保証するものではありません。正確な内容に関しては原文を参照ください。
:::

:::note info
**プレビュー**
本機能は[パブリックプレビュー](https://docs.databricks.com/release-notes/release-types.html)です。
:::

本書では、MLモデルの完全なライフサイクルを管理する機械学習ワークフローの一部として、Unity Catalogにおけるモデルをどのように活用するのかを説明します。Databricksでは、[Unity Catalog](https://docs.gcp.databricks.com/data-governance/unity-catalog/index.html)内でホスティングバージョンのMLflowモデルレジストリを提供します。Unity Catalogのモデルは、集中管理されるアクセスコントロール、監査、リネージ、ワークスペース横断でのモデル検索のようなUnity CatalogのメリットをMLモデルに拡張します。Unity Catalogのモデルは、オープンソースMLflow Pythonクライアントと互換性があります。

Unity Catalogのモデルのキーとなる機能には以下のようなものがあります:

- モデルに対する名前空間やガバナンスを提供するので、環境、プロジェクト、チームレベルでモデルをグルーピング、コントロールすることができます(プロダクションモデルに対してデータサイエンティストに対して読み取り専用アクセスを付与)。
- 時系列順のモデルリネージ(ある時点でどのMLflowエクスペリンとMLflowランがモデルを作成したのか)
- [モデルサービング](https://docs.databricks.com/machine-learning/model-serving/index.html)
- モデルのバージョン管理
- エイリアス経由でのモデルデプロイメント。例えば、お使いの`prod`カタログ内でモデルの「チャンピオン」バージョンにマーク。

本書には、Unity Catalog UIにおけるモデルと、APIの両方の手順が含まれています。

モデルレジストリのコンセプトの概要については、[Databricks MLflowガイド](https://qiita.com/taka_yayoi/items/1a4e82f7e20c56ba4f72)をご覧ください。

:::note
**注意**
本書では、モデルのコントロールとデプロイメントに推奨するUnity Catalogのモデルを説明します。クラシックのモデルレジストリのドキュメントに関しては、[DatabricksにおけるMLflowモデルレジストリ](https://qiita.com/taka_yayoi/items/e7a4bec6420eb7069995)をご覧ください。ワークスペースのモデルレジストリからUnity Catalogへのアップグレードガイドについては、[モデルとワークフローのUnity Catalogへの移行](#モデルとワークフローのunity-catalogへの移行)をご覧ください。
:::

# 要件

1. ワークスペースでUnity Catalogが有効化されていること。Unity Catalogメタストアの作成、ワークスペースでの有効化、カタログの作成に関しては、[Unity Catalogを使い始める](https://qiita.com/taka_yayoi/items/3f2df6ddea81521ee786)をご覧ください。Unity Catalogが有効化されていなくても、クラシックの[ワークスペースモデルレジストリ](https://qiita.com/taka_yayoi/items/e7a4bec6420eb7069995)を使うことが可能です。
1. 権限継承をサポートしているUnity Catalogメタストアにワークスペースがアタッチされていること。2022/8/25以降に作成されたすべてのメタストアではサポートされています。古いメタストアを実行している場合には、[ドキュメント](https://qiita.com/taka_yayoi/items/473a4b5924d46ff1b145)に従ってアップグレードしてください。
1. [Unity Catalogにアクセスできるクラスター](https://docs.databricks.com/data-governance/unity-catalog/compute.html)でコマンドを実行できる権限を持っていること。
1. 新規登録モデルを作成するには、スキーマに対する`CREATE_MODEL`権限、スキーマとその上位のカタログに対する`USE SCHEMA`と`USE CATALOG`権限が必要です。`CREATE_MODEL`は、データエクスプローラUIや以下のように[SQL GRANT command](https://docs.databricks.com/sql/language-manual/security-grant.html)を用いて付与できる新たなスキーマレベルの権限です。

    ```sql:SQL
    GRANT CREATE_MODEL ON SCHEMA <schema-name> TO <principal>
    ```

# Unity Catalogへのトレーニングワークロードのアップグレード

このセクションでは、既存のトレーニングワークロードのUnity Catalogへのアップグレード手順を説明します。

## MLflow Pythonクライアントのインストール

必要となるMLflow PythonクライアントはDatabricksランタイム13.2 ML以降には含まれています。それより前のバージョンでは、必要バージョンをインストールするためにノートブックの一番初めで以下のコードを実行してください。

```py
%pip install --upgrade "mlflow-skinny[databricks]>=2.4.1"
dbutils.library.restartPython()
```

## Unity CatalogのモデルにアクセスするようにMLフロークライアントを設定

デフォルトでは、MLflow PythonクライアントはDatabricksワークスペースのモデルレジストリにモデルを作成します。Unity Catalogのモデルにアップグレードするには、MLflowクライアントを設定します:

```py:Python
import mlflow
mlflow.set_registry_uri("databricks-uc")
```

## Unity Catalog互換のモデルをトレーニング、登録

**権限が必要:** 新規登録モデルを作成するには、対象スキーマに対する`CREATE_MODEL`、`USE SCHEMA`権限、上位のカタログに対する`USE CATALOG`権限が必要です。登録モデルの下に新規モデルバージョンを作成するには、登録モデルのオーナーであり、それを格納するスキーマとカタログに対する`USE SCHEMA`と`USE CATALOG`権限が必要です。

UCにおけるMLモデルバージョンには[モデルのシグネチャ](https://mlflow.org/docs/latest/models.html#model-signature)が必要です。お使いのモデルトレーニングワークロードでモデルのシグネチャを登録していない場合、以下のいずれかを行うことができます:

1. 著名な多数のMLフレームワークでモデルをシグネチャとともに自動で記録する[Databricks autologging](https://docs.databricks.com/mlflow/databricks-autologging.html)を活用する。サポートされるフレームワークについては、[MLflow docs](https://mlflow.org/docs/latest/tracking.html#automatic-logging)をご覧ください。
1. お使いのモデルのシグネチャを推定するために[mlflow\.models\.infer\_signature](https://mlflow.org/docs/latest/python_api/mlflow.models.html#mlflow.models.infer_signature)を使い、`mlflow.<flavor>.log_model`に渡す。

そして、MLflow APIにモデルの3レベル名称を、`<catalog>.<schema>.<model>`の書式で引き渡します。以下のサンプルでは、`prod`カタログ配下の`ml_team`スキーマにモデルを作成してアクセスしています。

## オートロギングを用いたUnity Catalogへのモデル登録

```py:Python
from sklearn import datasets
from sklearn.ensemble import RandomForestClassifier

# Train a sklearn model on the iris dataset
X, y = datasets.load_iris(return_X_y=True, as_frame=True)
clf = RandomForestClassifier(max_depth=7)
clf.fit(X, y)

# Note that the UC model name follows the pattern
# <catalog_name>.<schema_name>.<model_name>, corresponding to
# the catalog, schema, and registered model name
# in Unity Catalog under which to create the version
# The registered model will be created if it doesn't already exist
autolog_run = mlflow.last_active_run()
model_uri = "runs:/{}/model".format(autolog_run.info.run_id)
mlflow.register_model(model_uri, "prod.ml_team.iris_model")
```

## 手動で指定したシグネチャを用いたUnity Catalogへのモデル登録

```py:Python
from sklearn import datasets
from sklearn.ensemble import RandomForestClassifier
from mlflow.models.signature import infer_signature

with mlflow.start_run():
    # Train a sklearn model on the iris dataset
    X, y = datasets.load_iris(return_X_y=True, as_frame=True)
    clf = RandomForestClassifier(max_depth=7)
    clf.fit(X, y)
    signature = infer_signature(X, y)
    # Log the model and register it as a new version in UC
    mlflow.sklearn.log_model(
        sk_model=clf,
        artifact_path="model",
        signature=signature,
        registered_model_name="prod.ml_team.iris_model",
    )
```

# UIでモデルを参照する

**権限が必要:** UIで登録モデルやモデルバージョンを参照するには、登録モデルに対する`EXECUTE`権限、モデルを格納するスキーマとカタログに対する`USE SCHEMA`と`USE CATALOG`権限が必要です。

[Data Explorer](https://docs.databricks.com/data/index.html)を用いて、Unity Catalogの登録モデルやモデルバージョンを参照、管理することができます。

# モデルへのアクセスのコントロール

Unity Catalogに登録されたモデルへのアクセス制御については、[Unity Catalogにおける権限およびセキュリティ保護可能オブジェクト](https://qiita.com/taka_yayoi/items/57dfb4d1c5908c1f5d9e)をご覧ください。

# エイリアスを用いたモデルロールアウトの管理

モデルのエイリアスによって、登録モデルにおいて特定のバージョンに変更可能で名前付きの参照を割り当てることができます。

あなたのモデルトレーニングワークフローの特定の環境に、どのモデルバージョンがデプロイされているのかを指定するためにエイリアスを活用することができます。例えば、エイリアスを用いてプロダクショントラフィックの大部分に対応すべき現行の「チャンピオン」モデルを指定することができます。そして、「チャンピオン」バージョンを用いて予測を行うなど、そのエイリアスをターゲットとする推論ワークロードを記述することができます。以下のワークフローではこのアプローチをデモしています。

# エイリアスによるデプロイメントモデルのマーク

**権限が必要:** 登録モデルのオーナーであること、モデルを格納するスキーマとカタログに対する`USE SCHEMA`と`USE CATALOG`権限が必要です。

上述したモデルトレーニングの例では、`prod`カタログ配下で新規モデルバージョンを作成し、登録モデルに登録します。そして、新たにトレーニングしたモデルバージョンを「チャンピオン」エイリアスをポイントするように更新し、後段の推論ワークロードでプロダクションのトラフィックに対する予測をこのモデルバージョンを使うべきだということを示しています:

```py:Python
from mlflow import MlflowClient
client = MlflowClient()
client.set_registered_model_alias("prod.ml_team.iris_model", "Champion", 1)
```

# 推論モデルのロード

## 推論ワークロードにおけるエイリアスによるモデルバージョンの利用

**権限が必要:** 登録モデルに対する`EXECUTE`権限、モデルを格納するスキーマとカタログに対する`USE SCHEMA`と`USE CATALOG`権限が必要です。

エイリアスを用いてモデルバージョンを参照するバッチ推論ワークロードを記述することができます。例えば、以下のスニペットでは「チャンピオン」モデルバージョンをロードし、バッチ推論に適用しています。「チャンピオン」バージョンが新規モデルバージョンを参照するようにアップデートされると、バッチ推論ワークロードでは次の実行の際に自動でそれをピックアップするようになります。これによって、お使いのバッチ推論ワークロードからモデルのデプロイメントを分離することができます。

```py:Python
import mlflow.pyfunc
model_version_uri = "models:/prod.ml_team.iris_model@Champion"
champion_version = mlflow.pyfunc.load_model(model_version_uri)
champion_version.predict(test_x)
```

また、[model serving REST API](https://docs.databricks.com/machine-learning/model-serving/create-manage-serving-endpoints.html#modify-the-compute-configuration-of-an-endpoint)を用いて、エイリアスを用いてモデルバージョンを取得し、そのバージョンをサービングするようにモデルサービングエンドポイントをアップデートするデプロイメントワークフローを記述することができます:

```py:Python
import mlflow
import requests
client = mlflow.tracking.MlflowClient()
champion_version = client.get_model_version_by_alias("prod.ml_team.iris_model", "Champion")
# Update endpoint to serve the current "Champion" version
requests.request(...)
```

[エイリアス削除](https://mlflow.org/docs/latest/python_api/mlflow.client.html#mlflow.client.MlflowClient.delete_registered_model_alias)のAPIを含むMLflowドキュメントでエイリアスを操作するクライアントAPIのフルセットを参照ください。

## 推論ワークロードにおけるバージョン番号によるモデルバージョンの利用

また、バージョン番号を用いてモデルバージョンをロードすることができます:

```py:Python
import mlflow.pyfunc
# Load version 1 of the model "prod.ml_team.iris_model"
model_version_uri = "models:/prod.ml_team.iris_model/1"
first_version = mlflow.pyfunc.load_model(model_version_uri)
first_version.predict(test_x)
```

# ワークスペース横断でモデルを共有

適切な権限を持っている限り、任意のワークスペースからUnity Catalogのモデルにアクセスすることができます。例えば、新規に開発したモデルとプロダクションのベースラインの比較を促進するために、開発用ワークスペースで`prod`カタログからモデルにアクセスすることができます。

作成した登録モデル上で他のユーザーとコラボレーション(書き込み権限の共有)するためには、自分自身とコラボレーションしたいユーザーを含むグループにモデルのオーナーシップを許可しなくてはなりません。また、コラボレーターはモデルを含むカタログとスキーマに対する`USE CATALOG`と`USE SCHEMA`権限が必要です。詳細は[Unity Catalogにおける権限およびセキュリティ保護可能オブジェクト](https://qiita.com/taka_yayoi/items/57dfb4d1c5908c1f5d9e)をご覧ください。

# モデルあるいはモデルバージョンに注釈をつける

**権限が必要:** モデルを格納するスキーマとカタログに対する`USE SCHEMA`と`USE CATALOG`権限が必要です。

モデルやモデルバージョンに注釈することで、情報を提供することができます。例えば、使用する方法論やアルゴリズムに関する問題や情報の概要を含めることができます。

## UIを用いたモデルあるいはモデルバージョンへの注釈

[How to add markdown comments to data objects](https://docs.databricks.com/data/markdown-data-comments.html#how-to-add-markdown-comments-to-data-objects)をご覧ください。

## APIを用いたモデルあるいはモデルバージョンへの注釈

登録モデルの説明を更新するには、MLflow Client APIの`update_registered_model()`メソッドを活用します:

```py:Python
client = MlflowClient()
client.update_registered_model(
  name="<model-name>",
  description="<description>"
)
```

モデルバージョンの説明を更新するには、MLflow Client APIの`update_model_version()`メソッドを活用します:

```py:Python
client = MlflowClient()
client.update_model_version(
  name="<model-name>",
  version=<model-version>,
  description="<description>"
)
```

# モデルの名称変更(APIのみ)

**権限が必要:** 登録モデルのオーナーであり、登録モデルを格納するスキーマに対する`CREATE_MODEL`権限、それを格納するスキーマとカタログに対する`USE SCHEMA`と`USE CATALOG`権限が必要です。

登録モデルの名前を変更するには、MLflow Client APIの`rename_registered_model()`メソッドを活用します:

```py:Python
client=MlflowClient()
client.rename_registered_model("<model-name>", "<new-model-name>")
```

# モデルやモデルバージョンの削除

**権限が必要:** 登録モデルのオーナーであり、それを格納するスキーマとカタログに対する`USE SCHEMA`と`USE CATALOG`権限が必要です。

[データエクスプローラのUI](https://docs.databricks.com/data/explore-models.html)、あるいはAPIを用いて登録モデル内のモデルバージョン、登録モデルを削除することができます。

## APIによるモデル、モデルバージョンの削除

:::note alert
**警告！**
このアクションを取り消すことはできません。モデルを削除すると、削除モデルに関連づけられているUnity Catalogで格納されているすべてのモデルアーティファクトと、すべてのメタデータが削除されます。
:::

### モデルバージョンの削除

モデルバージョンを削除するには、MLflow Client APIの`delete_model_version()`メソッドを使用します:

```py:Python
# Delete versions 1,2, and 3 of the model
client = MlflowClient()
versions=[1, 2, 3]
for version in versions:
  client.delete_model_version(name="<model-name>", version=version)
```

### モデルの削除

モデルを削除するには、MLflow Client APIの`delete_registered_model()`メソッドを使用します:

```py:Python
client = MlflowClient()
client.delete_registered_model(name="<model-name>")
```

# モデルの一覧、検索

MLflowの[search\_registered\_models\(\)](https://mlflow.org/docs/latest/python_api/mlflow.client.html#mlflow.client.MlflowClient.search_registered_models) Python APIを用いてUnity Catalogの登録モデルを一覧することができます:

```py:Python
client=MlflowClient()
client.search_registered_models()
```

また、`search_model_versions()`モデルを用いて、特定のモデル名で検索し、バージョンの詳細を一覧することができます:

```py:Python
from pprint import pprint

client=MlflowClient()
[pprint(mv) for mv in client.search_model_versions("name='<model-name>'")]
```

# サンプル

このサンプルでは、機械学習アプリケーションを構築するために、どのようにUnity Catalogのモデルを活用するのかを説明しています。

[Models in Unity Catalog example](https://docs.databricks.com/mlflow/models-in-uc-example.html)

# モデルとワークフローのUnity Catalogへの移行

お使いのモデルやワークフローをどのようにUnity Catalogに移行するのかの詳細については、[Upgrade ML workflows and models to Unity Catalog](https://docs.databricks.com/machine-learning/manage-model-lifecycle/upgrade-to-uc/index.html)をご覧ください。

### Databricksクイックスタートガイド

[Databricksクイックスタートガイド](https://www.amazon.co.jp/dp/B09V1YXFVQ/)


### Databricks無料トライアル

[Databricks無料トライアル](https://databricks.com/jp/try-databricks)