DatabricksにおけるMLOpsワークフロー

[MLOps workflow on Databricks \| Databricks on AWS](https://docs.databricks.com/machine-learning/mlops/mlops-workflow.html) [2022/10/24時点]の翻訳です。

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

本書では、あなたの機械学習(ML)システムのパフォーマンスと長期にわたる効率性を最適化するために、どのようにDatabricksにおけるMLOpsを活用できるのかを説明します。これには、MLOpsアーキテクチャの一般的な推奨事項が含まれており、MLの開発からプロダクションに至るプロセスのモデルとして活用できるDatabricksレイクハウスプラットフォームを用いた一般的なワークフローを説明します。

# MLOpsとは？

MLOpsとは、コード、データ、モデルを管理するための一連のプロセスと自動化されたステップです。これは、DevOps、DataOps、ModelOpsを組み合わせたものです。
![](https://docs.databricks.com/_images/mlops-lakehouse.png)

コード、データ、モデルの様なMLアセットは、厳しいアクセス制限がなく厳密なテストが行われない初期の開発ステージから、中間のテストステージを経て、厳密にコントロールされる最終のプロダクションステージで開発されます。Databricksのレイクハウスプラットフォームを用いることで、統合されたアクセスコントロールを用いて単一のプラットフォームでこれらのアセットを管理することができます。同じプラットフォーム上でデータアプリケーションとMLアプリケーションを開発することができ、データ移動に伴うリスクや遅れを削減することができます。

# MLOpsにおける一般的な推奨事項

このセクションでは、詳細情報へのリンクを含むDatabricksにおけるMLOpsに関する一般的な推奨事項を説明します。

## ステージごとに異なる環境を作成しましょう

実行環境は、モデルやデータが作成され、コードによって活用される場所となります。それぞれの実行環境は、計算インスタンス、ランタイム、ライブラリ、自動化されたジョブから構成されます。

MLコードとモデル開発に対して、ステージ間の移行が明確に定義された別々のステージを設けることをお勧めします。本書で説明するワークフローは、ステージに対する一般的な名称を用いてこのプロセスに従います。

- [開発](#開発ステージ)
- [ステージング](#ステージングステージ)
- [プロダクション](#プロダクションステージ)

## アクセスコントロールとバージョン管理を使いましょう

いかなるソフトウェアオペレーションのプロセスにおいても、アクセスコントロールとバージョン管理はキーのコンポーネントとなります。以下を推奨します。

- **Gitバージョンコントロールを使いましょう。** パイプラインやコードバージョン管理のためにGitに格納されるべきです。MLロジックのステージ間の移行を、コードの開発ブランチから、ステージングブランチ、リリースブランチへの移動と解釈することができます。お使いのGitプロバイダーをインテグレーションし、Databricksワークスペースでノートブックやソースコードを同期するために、[Databricks Repos](https://qiita.com/taka_yayoi/items/b89f199ff0d3a4c16140)をお使いください。また、DatabricksではGit連携、バージョン管理のためにその他のツールも提供しています。[Developer tools and guidance](https://docs.databricks.com/dev-tools/index.html)をご覧下さい。
- **Deltaテーブルを用いたレイクハウスアーキテクチャにデータを格納しましょう。** お使いのクラウドアカウント内の[レイクハウスアーキテクチャ](https://qiita.com/taka_yayoi/items/883b29d4808874427464)にデータを格納すべきです。生のデータと特徴量テーブルの両方が、誰が読み込みでき、誰が編集できるのかを決定するためのアクセスコントロールがなされた[Deltaテーブル](https://docs.databricks.com/delta/index.html)に格納されるべきです。
- **MLflowを用いてモデルとモデル開発を管理しましょう。** モデル開発プロセスを追跡し、コードのスナップショット、モデルのパラメーター、メトリクス、その他のメタデータを保存するために[MLflow](https://qiita.com/taka_yayoi/items/1a4e82f7e20c56ba4f72)を活用することができます。モデルのバージョンとデプロイメントのステータスを管理するために[モデルレジストリ](https://qiita.com/taka_yayoi/items/e7a4bec6420eb7069995)を使いましょう。モデルレジストリは、CDシステムとインテグレーションできる[webhook](https://qiita.com/taka_yayoi/items/33c2c60a4ce2c5d37eee)とAPIを提供し、[モデルのアクセスコントロール](https://qiita.com/taka_yayoi/items/2dd6711b7b254505e4a3#mlflow%E3%83%A2%E3%83%87%E3%83%AB%E3%81%AE%E3%82%A2%E3%82%AF%E3%82%BB%E3%82%B9%E6%A8%A9%E8%A8%AD%E5%AE%9A)を取り扱うことができます。

## モデルではなくコードをデプロイしましょう

ほとんどのシチュエーションでは、ML開発プロセスにおいては、*モデル*ではなく*コード*をある環境から次の環境にプロモーションすることをお勧めします。このようにプロジェクトのアセットを移動することで、ML開発におけるすべてのコードが同じコードレビューとインテグレーションテストプロセスを通過することを確実にします。また、こうすることでモデルのプロダクションバージョンがプロダクションのコードによってトレーニングされることを保証します。選択肢とトレードオフに関する議論については、[Databricksにおける機械学習モデルデプロイメントのパターン](https://qiita.com/taka_yayoi/items/8521f738c9fbb4097d4e)をご覧ください。

# 推奨のMLOpsワークフロー

以下のセクションでは、開発、ステージング、プロダクションという3つのステージそれぞれをカバーする典型的なMLOpsワークフローを説明します。

このセクションでは、典型的なペルソナとして「データサイエンティスト」と「MLエンジニア」という用語を使います。MLOpsワークフローにおける固有のロールや責任範囲は、チームと企業の間で変動します。

# 開発ステージ

開発ステージのフォーカスは実験です。データサイエンティストは特徴量とモデルを開発し、モデルのパフォーマンスを最適化するために実験を行います。開発プロセスのアウトプットは、特徴量計算処理、モデルトレーニング、推論、モニタリングを含むMLパイプラインのコードです。
![](https://docs.databricks.com/_images/mlops-dev-diagram.png)

番号のついているステップは図に表示されている番号と対応しています。

## 1. データソース

開発環境で作業を行うデータサイエンティストは、多くの場合、プロダクションデータに対する読み取りのみのアクセス権を持ちます。データガバナンスの要件を満たすために、いくつかのケースでは、開発環境からはプロダクションデータのミラー、あるいは検閲済みバージョンにのみアクセスできる場合があります。また、データサイエンティストは新たな特徴量や他のデータテーブルを用いた開発、実験を行うために別の開発環境のストレージへの読み書き権限を持ちます。

## 2. 探索的データ分析(EDA)

データサイエンティストは、ノートブック、ビジュアライゼーション、[Databricks SQL](https://docs.databricks.com/sql/index.html)を用いたインタラクティブかつイテレーティブなプロセスの中でデータの探索、分析を行います。

このアドホックなプロセスは、別の実行環境にデプロイされるパイプラインには通常は含まれません。

## 3. コード

MLシステムのすべてのコードはコードリポジトリに格納されます。データサイエンティストはGitプロジェクトの開発ブランチで新規あるいは更新パイプラインを作成します。コードはDatabricks内外で開発することができ、[Databricks Repos](https://qiita.com/taka_yayoi/items/b89f199ff0d3a4c16140)を用いてDatabricksワークスペースと同期されます。

## 4. 特徴量テーブルの更新

モデル開発パイプラインは、生データテーブルと既存の特徴量テーブルから読み込みを行い、[Feature Store](https://qiita.com/taka_yayoi/items/88ddec323537febf7784)のテーブルに書き込みを行います。パイプラインには2つのタスクが含まれます:

1. **データの準備。** データ品質問題をチェックします。
1. **特徴量テーブルの作成、更新。** データサイエンティストは特徴量を作成するためのコードを開発、更新します。これらのパイプラインはFeature Storeや他のレイクハウステーブルから読み込みを行い、開発環境のストレージに特徴量テーブルを書き込みます。そして、データサイエンティストはプロトタイプのモデルを作成するために、これらの開発用特徴量テーブルを使用します。コードがプロダクションにプロモートされると、これらの変更はプロダクションの特徴量低ブルをアップデートします。

    特に別のチームによって所有されている場合、特徴量パイプラインは他のMLパイプラインから別に管理されることも可能です。

## 5. モデルのトレーニング

データサイエンティストは、読み込み専用のプロダクションデータあるいは、非プロダクションデータに対してモデルのトレーニングを行い、その他のパイプラインを開発します。このパイプラインは、開発環境あるいはプロダクション環境の特徴量テーブルを使うことができます。

このパイプラインには2つのタスクがあります:

- **トレーニングとチューニング。** モデルトレーニングのプレオセ右派、特徴量ストアやシルバー、ゴールドレベルのレイクハウステーブルから特徴量を読み込み、MLflowトラッキングサーバーにモデルのパラメーター、メトリクス、アーティファクトを記録します。

    トレーニングとハイパーパラメーターチューニングが完了すると、データサイエンティストはトラッキングサーバーに最終のモデルを保存します。これによって、モデル、入力データ、モデルを生成したコードのリンクが記録されます。

    このトレーニングパイプラインがステージングやプロダクションで実行される際には、MLエンジニアはモデルのURI(あるいはパス)を用いることでモデルをロードし、管理やテストのためにモデルをモデルレジストリにプッシュすることができます。

- **評価。** ホールドアウトデータでテストを行うことでモデルの品質を評価します。これらのテストの結果はMLflowトラッキングサーバーに記録されます。

    皆様の組織のガバナンス要件にモデルに関する追加情報が含まれているのであれば、[MLflowトラッキング](https://qiita.com/taka_yayoi/items/ba0c7f46ff7c3dbf87bb)を用いて保存することができます。典型的なアーティファクトには、平文テキストの説明文やSHAPやLIMEによって生成されるモデルの解釈があります。

## 6. コードのコミット

特徴量生成、トレーニング、推論、その他のパイプラインのコード開発の後で、データサイエンティストかMLエンジニアは、ソースコントロールに開発ブランチの変更をコミットします。

# ステージングステージ

このステージのフォーカスは、プロダクションの準備ができていることを確実にするために、MLパイプラインをテストすることです。このステージでは、モデルトレーニングのコードや特徴量生成パイプライン、推論コードなどを含むすべてのMLパイプラインコードがテストされます。

MLエンジニアは、このステージで実行されるユニットテスト、インテグレーションテストを実装するCIパイプラインを作成します。ステージングプロセスのアウトプットは、プロダクションステージを開始するためにCI/CDシステムを起動するリリースブランチです。
![](https://docs.databricks.com/_images/mlops-staging-diagram.png)

番号のついているステップは図に表示されている番号と対応しています。

ステージング環境には、特徴量テーブルやMLパイプラインをテストするための独自のストレージ領域を持つことができます。このストレージは、一般的には一時的なものであり、テストが完了するまでの間のみ維持されます。また、開発環境からもデバッグの目的でこのデータストレージへのアクセスが必要になる場合があります。

## 1. マージリクエスト

MLエンジニアがソースコントロールのステージングブランチ(普通は「main」ブランチ)にマージリクエストを作成した際に、デプロイメントプロセスがスタートします。マージリクエストが継続的インテグレーション(CI)プロセスを起動します。

## 2. ユニットテスト

CIプロセスは自動でソースコードをビルドし、ユニットテストを起動します。テストが失敗するとマージリクエストは却下されます。ユニットテストはデータや他のサービスとはやり取りしません。

## 3. インテグレーションテスト(CI)

そして、CIプロセスはインテグレーションテストを実行します。インテグレーションテストは全体的に機能が適切に動作することを確実にするために、(特徴量生成、モデルトレーニング、推論、モニタリングを含む)すべてのパイプラインを実行します。ステージング環境は、合理性があるといえるくらいプロダクション環境と類似したものである必要があります。

インテグレーションテストの実行に必要な時間を短縮するために、モデルトレーニングステップはテストの正確性とスピードとのトレードオフとなります。例えば、小規模なデータのサブセットを使うか、より少ないトレーニングイテレーションを実行することも可能です。モデルの用途に応じて、この時点で完全規模の負荷のテストを行うという選択をすることもできます。

ステージングブランチでインテグレーションテストに追加した後は、コードをプロダクションにプロモートすることができます。

## 4. ステージングブランチへのマージ

テストを通過したら、コードをステージングブランチにマージすることができます。テストに失敗したら、CI/CDシステムはユーザーに通知を行い、マージ(プル)リクエストに結果をポストすべきです。

## 5. リリースブランチの作成

プロダクションにコードをデプロイする準備ができたら、MLエンジニアがプロダクションジョブをアップデートするためにCI/CDシステムを起動するリリースブランチを作成します。

# プロダクションステージ

MLエンジニアは、MLパイプラインがデプロイされるプロダクション環境のオーナーシップを持ちます。これらのパイプラインはフレッシュな特徴量の値を計算し、新たなモデルバージョンをトレーニング、テストし、予測結果を後段のテーブルやアプリケーションに公開し、パフォーマンス劣化や不安定性を回避するためにプロセス全体を監視します。

通常、データサイエンティストはプロダクション環境で書き込みや計算資源へのアクセス権を持ちません。しかし、プロダクションにおける問題を特定、診断できる様に、彼らがテストの結果、ログ、モデルのアーティファクト、プロダクションパイプラインのステータスを参照できる様にしておくことが重要です。
![](https://docs.databricks.com/_images/mlops-prod-diagram.png)

番号のついているステップは図に表示されている番号と対応しています。

## 1. 特徴量テーブルの更新

新たなプロダクションデータが利用できる様になると、このパイプラインはそれを取り込み、プロダクションの特徴量テーブルを更新します。このパイプラインはバッチあるいはストリーミングジョブで実行することができ、スケジューリング実行、即時実行、継続実行することができます。

## 2. モデルのトレーニング

完全なプロダクションデータでプロダクションバージョンのモデルをトレーニングし、MLflowモデルレジストリに登録します。このパイプラインは、コードの変更や自動化された再トレーニングジョブによって起動することができます。

このパイプラインには2つのタスクがあります:

- **トレーニングとチューニング。** 開発ステージと同じ様に、MLflowトラッキングサーバーにトレーニングプロセスの記録を自動で記録します。これには、モデルのメトリクス、パラメーター、タグ、モデル自身が含まれます。

    開発の過程で、データサイエンティストは多くのアルゴリズムやハイパーパラメーターをテストします。プロダクションのトレーニングコードでは、最もパフォーマンスの良いオプションのみを考慮することが一般的です。この様にチューニングを限定することで時間を節約し、自動化された再トレーニングのチューニングによる変動を削減することができます。

- **評価。** ホールドアウトされたプロダクションデータを用いて、モデルの品質が評価されます。これらのテスト結果はMLflowトラッキングサーバーに記録されます。このステップでは、開発ステージでデータサイエンティストによって指定された評価メトリクスが使用されます。これらのメトリクスにはカスタムコードが含まれる場合があります。

モデルトレーニングが完了したら、モデルアーティファクトをプロダクション環境の[MLflowモデルレジストリ](https://qiita.com/taka_yayoi/items/e7a4bec6420eb7069995)に登録します。モデルレジストリのステージの初期状態は`None`です。

## 3. 継続的デプロイメント(CD)

CDプロセスが、新たなモデル(モデルレジストリ上では`stage=None`)を取り込んでテストし、テストに成功したらデプロイ(`stage=Production`にプロモート)します。CDは[モデルレジストリのwebhook](https://qiita.com/taka_yayoi/items/33c2c60a4ce2c5d37eee)あるいはお使いのCDシステムで実装することができます。

このパイプラインには3つのタスクがあります:

- **コンプライアンスチェック。** これらのテストは、モデルレジストリからモデルをロードし、あなたの組織が必要とするコンプライアンスチェック(タグやドキュメントなど)を行い、テスト結果に基づいてリクエストを承認あるいは却下します。コンプライアンスに人間の専門性が必要である場合、この自動化ステップは手動によるレビューのために統計情報やビジュアライゼーションを生成します。結果の如何を問わず、タグのメタデータや説明文のコメントを用いて、モデルバージョンの結果をモデルレジストリに記録します。

    手動でステージ移行や移行リクエストを管理するためにMLflowのUIを使うことができます。あるいは、自動化するためにMLflow APIやwebhookを使うことができます。モデルがコンプライアンスチェックを通過したら、移行リクエストは承認され、モデルは`stage=Staging`にプロモートされます。モデルが失敗すると、移行リクエストは却下されモデルはモデルレジストリで`stage=Archived`に移行されます。

- **ステージングとプロダクションの比較。** パフォーマンスの劣化を防ぐために、現行のプロダクションバージョンとステージングにプロモートされたモデルのパフォーマンスを比較すべきです。比較のメトリクスや方法はユースケースに依存し、カナリアデプロイメントやA/Bテストや他の手法を含めることもできます。テストの比較結果はレイクハウスのメトリクステーブルに保存されるべきです。

    これが最初のデプロイメントであり、まだプロダクションバージョンがない場合には、ステージングバージョンをベースラインとしてのビジネス経験則や他の閾値と比較することができます。

- **モデルのプロダクションへの移行のリクエスト。** 候補モデルが比較テストを通過したら、モデルレジストリで`stage=Production`への移行をリクエストすることができます。MLflowを用いて手動、あるいはMLflow APIやwebhookを用いて自動でこれを行うことができます。また、この時点で人間による承認を行うことは良いアイデアです。これが、モデルがプロダクションにリリースされ、既存のビジネスプロセスに組み込まれる前の最後のステップです。コンプライアンスチェック、パフォーマンスの比較、自動化が難しいその他のチェックを検証するための人間によるレビューを含めることもできます。

## 4. オンラインサービング(REST API)

低レーテンシーのユースケースにおいて、オンラインサービングのためにモデルをデプロイするためにMLflowを使うことができます。オプションには、Databricksのモデルサービング、クラウドプロバイダーのサービングエンドポイント、カスタムサービングアプリケーションが含まれます。

サービングシステムは、モデルレジストリからプロダクションのモデルバージョンをロードします。それぞれのリクエストに対して、オンライン特徴量ストアから特徴量を取得し、データのスコアリングを行い、予測結果を返却します。サービングシステムやデータ転送レイヤー、モデルを用いて、リクエストと予測結果を記録することができます。

## 5. 推論: バッチあるいはストリーミング

バッチあるいはストリーミングジョブにおいては、パイプラインがFeature Storeから最新のデータを読み込み、モデルレジストリからプロダクションのmドエルバージョンをロードし、データをスコアリングし、予測結果を返却します。バッチやストリーミング推論は通常、高いスループット、高レーテンシーのユースケースでは最もコスト効率の良い選択肢となります。

通常バッチジョブは、JDBC接続を通じて予測結果をレイクハウスのテーブル、あるいはフラットなファイルに出力します。通常ストリーミングジョブはレイクハウステーブルか、Apahce Kafkaのようなメッセージキューに予測結果を出力します。

## 6. モニタリング

入力データとモデルの予測結果の統計情報(データドリフトやモデルのパフォーマンスなど)、計算処理の性能(エラーやスループット)をモニタリングすべきです。これらのメトリクスに基づいたアラートを作成したり、ダッシュボードに公開することができます。

デプロイメントのモードに関係なく、モデルの入力クエリーや予測結果をDeltaテーブルに記録数rことができます。データドリフトやモデルドリフトを監視するジョブを作成することができ、ダッシュボードにステータスを表示したり、アラートを送信するためにDatabricks SQLを活用することができます。プロダクションの問題を調査するために、データサイエンティストが開発環境でログやメトリクスにアクセスできる様に許可することができます。

このパイプラインには3つのタスクがあります:

- **データの取り込み。** このパイプラインはバッチ、ストリーミング、オンライン推論からログを読み込みます。
- **精度とデータドリフトのチェック。** パイプラインは、入力データ、モデルの予測結果、インフラストラクチャのパフォーマンスに関するメトリクスを計算します。データサイエンティストは、開発過程でデータとモデルのメトリクスを指定し、MLエンジニアがインフラストラクチャのメトリクスを指定します。
- **メトリクスの公開。** パイプラインは分析やレポートのためにレイクハウスのテーブルに書き込みを行います。モデルのパフォーマンスを追跡するためにモニタリングダッシュボードを作成するためにDatabricks SQLを活用し、指定された閾値をメトリクスが上回った際に通知を行うために、モニタリングジョブやダッシュボードツールを使うことができます。

## 7. モデルの再トレーニング

最新データを用いてモデルの再トレーニングを行うスケジュールジョブを作成するか、データやモデルにドリフトを検知した際に再トレーニングを起動するためのモニターをセットアップすることができます。モデルモニタリングメトリクスがパフォーマンスの問題を示した際には、データサイエンティストは開発環境に戻って新たなモデルバージョンを開発する必要があるかもしれません。

:::note
**注意**
モデルモニタリングによって検知された問題をどの様に修正したらいいのかが明確ではないので、完全に自動化されたモデルの再トレーニングはを正しく行うことは困難です。例えば、観測されたデータドリフトによって引き起こされたモデルパフォーマンスの問題は、新規データを用いてモデルを際トレーニングすることで修正できるかもしれませんし、データの新たな信号をエンコードするための追加の(手動の)特徴量開発作業を必要とするかもしれません。
:::

- 定期的に新規データが利用できるのであれば、最新の利用可能なデータに対してモデルのトレーニングコードを実行する[スケジュールジョブ](https://qiita.com/taka_yayoi/items/b3275a1983c51a8bbe1a)を作成することができます。
- モニタリングパイプラインがモデルのパフォーマンス問題を特定し、アラートを送信できるのであれば、再トレーニングを自動で起動する様に設定することができます。自動再トレーニングや再デプロイメントは、パイプラインが到着するデータの分布の変化やモデルパフォーマンスの劣化のようなシチュエーションを検知できるのであれば、最小限の人間の介入でモデルのパフォーマンスを改善できます。

### Databricks 無料トライアル

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