📊

MLflow Modelsでデプロイしたモデルを監視する方法

2024/10/09に公開

1. はじめに

概要

MLflow Modelsは、機械学習モデルの管理とデプロイを効率化するための多くの便利な機能を備えています。特に、モデルを含むDockerイメージを自動的にビルドする機能は、迅速なモデルサービングを可能にします。しかし、MLflowによってビルドされたDockerイメージにはカスタマイズの制約があり、特にモデル監視のための追加機能を組み込むことが難しいという課題があります。

本記事では、この問題を解決するためにプロキシサーバーを導入し、ログ収集や監視機能を強化する方法について説明します。また、プロキシサーバーに加え、Promtail、Loki、Grafanaを組み合わせることで、ログの収集と可視化を行う構成を構築します。

問題点

MLflow Modelsの機能を使うと、モデルを含むDockerイメージを自動的にビルドできますが、ここにはいくつかの制約があります。特に、ビルドされたDockerイメージはMLflowによって標準化されているため、イメージのカスタマイズが難しい点が問題となります。

この制約が特に影響を与えるのは、モデル監視のための追加機能を組み込む場合です。例えば、エラーログの収集やパフォーマンスモニタリングなどの機能を追加しようとしても、MLflowが生成するDockerイメージにはそれらの監視ツールを直接組み込むことが難しく、結果としてモデルの運用中に問題が発生しても、その原因を追跡するのが困難になることがあります。

解決策

上記のような問題を克服し、モデル監視機能を追加するためには、標準のDockerイメージに追加するのではなく、外部に監視機能を設ける必要があります。そのための解決策として、プロキシサーバーの導入が有効となります。

プロキシサーバーの導入

プロキシサーバーをモデルサービングの前段に追加することで、モデルへのリクエストをすべて通過させ、そのリクエストをログとして記録できるようにします。この手法は、MLflowのコントリビューターが自身のGitHubリポジトリで提案している信頼性の高い方法になっています。

具体的には、Flaskを用いてプロキシサーバーを構築します。プロキシサーバーが前段にあることで、モデルサービングに対するすべてのリクエストはまずFlaskを通過し、その際に必要な情報(例えばリクエスト内容、レスポンスのステータス、処理時間など)が記録されます。

この方法では、MLflowによってビルドされたDockerイメージ自体を変更する必要がないため、MLflowの標準機能を保ちながら、監視機能を追加することができます。また、ログデータを外部に保存することで、後述するログ収集と可視化のプロセスに進む準備が整います。

構成の概要

本記事では、以下のツールと技術を用いてモデルサービングとモデル監視のシステムを構築する方法を紹介します。

モデルサービング

  • MLflow:機械学習プロジェクト管理ツールで、モデルのトレーニング、保存、モデルイメージのビルドをサポートします。

モデル監視

  • Flask:軽量なWebフレームワークで、プロキシサーバーとして機能し、リクエストのログを収集します。
  • Promtail:ログ収集エージェントで、Flaskから生成されたログを収集します。
  • Loki:ログ管理システムで、収集されたログを保存・インデックス化し、クエリを実行します。
  • Grafana:データ可視化ツールで、Lokiから取得したログデータをダッシュボードとして表示します。

これらのツールを組み合わせることで、モデルのデプロイから監視までを一貫して行うシステムを構築します。次のセクションでは、まずモデルサービングの設定方法について簡単に説明します。

2. モデルサービングの設定

モデルのデプロイ

前提条件

学習済みのモデルがMLflowに登録されていることを前提とします。

イメージのビルド

MLflowは、学習済みのモデルをDockerイメージとして簡単にビルドできるコマンドを提供しています。以下のコマンドを使用して、MLflowに登録されたモデルをDockerイメージとしてビルドします。

mlflow models build-docker -m runs:/<run_id>/model -n <image_name>

ここで、<run_id>はMLflowに登録されたモデルのランID、<image_name>は作成するDockerイメージの名前です。

MLflowの動作にはいくつかの依存関係が必要です。上記のコマンドでは、MLflowが自動的に必要な依存関係をDockerイメージに含めます。特定のモデルフレームワーク(例:TensorFlow、PyTorch)を使用する場合は、それらの依存関係も自動的に含まれます。

Docker上でのモデルサービング

次に、モデルを含むビルド済みイメージをDockerコンテナ上でサービングするため、以下のコマンドでコンテナを起動します。

docker run -p 8080:8080 <image_name>

これで、推論サーバーが起動し、モデルのサービングが可能になります。

推論のテスト

モデルにリクエストを送信し、推論結果を取得できます。
例えば、以下のようにリクエストを送信します。

curl http://localhost:8080/invocations -X POST -H "Content-Type: application/json" --data '{"columns":["feature1", "feature2"], "data":[[value1, value2]]}'

すると、以下のようなレスポンスが返ってきます。

{"predictions": [1]}

リクエストを送信することで推論結果が返ってくるところまで確認できたところでモデルのサービングは完了です。
次のセクションでは、モデル監視の導入方法について詳しく説明します。

3. モデル監視の導入

Docker Composeによる一括起動

以下は、推論サーバー、プロキシサーバー、Promtail、Loki、GrafanaをDocker Composeで一括起動するためのcompose.yamlファイルです。

https://github.com/marcy326/mlflow-grafana/blob/main/compose.yaml

このcompose.yamlファイルを使用して、以下のコマンドでサービスを一括起動します。

docker compose up -d

以下に各設定ファイルの詳細を示します。

Flaskによるプロキシサーバーのセットアップ

Flaskによるプロキシサーバーの作成

Flaskは軽量なWebフレームワークで、プロキシサーバーとして機能し、リクエストのログを収集します。以下のコードは、Flaskを用いたプロキシサーバーの設定例です。
https://github.com/marcy326/mlflow-grafana/blob/main/proxy/proxy_server.py

上記のコードでは、Flaskプロキシサーバーが受け取ったリクエストとモデルサーバーからのレスポンスをログファイルに記録します。これにより、リクエストの内容やモデルの応答を後で分析することができます。

Promtailによるログ収集

Promtailの役割と設定ファイルの作成

Promtailは、ログ収集エージェントであり、Flaskから生成されたログを収集してLokiに送信します。以下のPromtailの設定ファイルを作成することでPromtailの設定を行います。
https://github.com/marcy326/mlflow-grafana/blob/main/promtail-config.yaml

上記の設定ファイルでは、Flaskプロキシサーバーのログファイル(/app/logs/*.log)を指定しています。このファイルはプロキシサーバーにより作成されたログファイルをホストマシンからマウントすることで読み込んでいます。Promtailはこのログファイルを監視し、ログデータをLokiに送信します。

Lokiによるログ管理

Lokiの役割と設定

Lokiは、ログデータを保存・インデックス化し、クエリを実行するためのログ管理システムです。
LokiとPromtailとの連携はPromtail側の設定により行われ、LokiとGrafanaとの連携はGrafana側の設定により行われます。そのためLokiの設定はデフォルトのまま起動します。

Grafanaによるデータ可視化

GrafanaはUIからダッシュボードを設定することができますが、設定ファイルを作成しておくことで起動時に自動でダッシュボードを作成することもできます。今回は設定ファイルにより、プロビジョニングの設定とダッシュボードの定義を行います。

ダッシュボードのプロビジョニング設定

役割: ダッシュボードのプロビジョニングディレクトリを指定し、指定したフォルダ内のJSONファイル(ダッシュボードテンプレート)を自動的にGrafanaに読み込む設定をします。
内容: ダッシュボードの保存場所やバージョン管理の情報などを記載します。

https://github.com/marcy326/mlflow-grafana/blob/main/grafana/dashboard.yml

データソースのプロビジョニング設定

役割: データを取得するためのLokiやPrometheusといったデータソースの接続設定を定義します。これにより、GrafanaのインターフェースからLokiのデータを取得し、ダッシュボードに表示できます。
内容: データソースの名前、種別、URL、認証情報などを記載します。

https://github.com/marcy326/mlflow-grafana/blob/main/grafana/datasource.yml

ダッシュボードの定義

役割: ダッシュボードの具体的な内容(グラフ、メトリクス、ログ表示など)を定義します。これにより、特定のログやメトリクスの監視項目を設定して、グラフやログビューワーなどを配置します。
内容: ダッシュボードのUI構成(パネル、グラフの種類、表示内容)やクエリなどが含まれています。

https://github.com/marcy326/mlflow-grafana/blob/main/grafana/dashboards/model_monitoring_dashboard.json

4. まとめ

本構成のメリット

本記事で紹介した構成は、MLflow Modelsを用いたモデルサービングにおいて、プロキシサーバーを活用することで監視機能を追加しました。この方法の利点は、MLflowの標準機能を活かしながら、外部ツールを組み合わせて柔軟な監視体制を作れることです。

今後の展望

今後の展望としては、これらのツールをさらに活用し、リアルタイムでの異常検知やアラート機能の強化を図ることがあげられます。また、モデルのパフォーマンスを継続的にモニタリングし、必要に応じて自動的にモデルを更新する仕組みを導入することで、より高度な運用が可能になります。これにより、機械学習モデルの信頼性と効率性をさらに向上させることができます。

Discussion