Azure Machine Learningのデータドリフト監視機能を使ってみる

こんにちは。今日は、前から気になっていたAzure Machine Learningのデータドリフト検知機能について勉強を進めたので、わかったことなどをまとめておきたいと思います。

Contents

Azure Machine Learningのデータドリフト機能の概要

公式ドキュメントはこちら。

https://learn.microsoft.com/ja-jp/azure/machine-learning/how-to-monitor-datasets?view=azureml-api-1

— 以下、ChatGPTによるまとめ

Azure Machine Learningのデータドリフト機能は、本番環境のデータとモデルが訓練された際のデータとの間に発生する「ドリフト」を検出するためのものだよ。要は、モデルが元々学習したデータと新しく入ってくるデータがどれくらい違うのか、リアルタイムでチェックしてくれるんだ。

その価値は?

  1. 早期発見: データが変わり始めたらすぐに気づける。それで、問題が大きくなる前に対処できる。
  2. 信頼性: モデルの予測が信頼できるかどうか、常に確認できる。
  3. メンテナンス: モデルを時々更新する必要があるけど、いつやるべきかをデータドリフトが教えてくれる。

簡単に言うと、データドリフト機能は、モデルが期待通りに動いているかどうかを確認するための「警告システム」みたいなものだね。データが変わってきたら、それに合わせてモデルも更新しないといけないから、非常に役立つ機能だよ。

データドリフト監視構成の流れ

Azure Machine Learningでデータドリフトを監視するのは、大体以下のようなステップで行うんだ。

  1. ベースラインデータ登録: 最初に、モデルの訓練に使ったデータ(ベースラインデータ)をAzure ML Studioに登録する。
  2. ターゲットデータ登録: 次に、本番環境で入ってくる新しいデータ(ターゲットデータ)もAzureで登録する。
  3. ドリフト検出の設定: どの特徴量を監視するのか、どれくらいの頻度でチェックするのかなど、データドリフトの設定を行う。
  4. アラート設定: ドリフトが一定の閾値を超えた場合に通知が来るようにアラートを設定する。
  5. 監視開始: 以上の設定が完了したら、監視を開始。Azureが自動でデータドリフトをチェックしてくれる。
  6. 結果確認: 定期的にAzure ML Studioで監視結果をチェック。ドリフトが見つかったら、どう対処するかを考える。
  7. モデル更新: データドリフトが確認された場合、新しいデータでモデルを更新する。

このようにベースラインデータとターゲットデータをしっかりと登録しておくことで、より正確なドリフト検出が可能になるんだ。

実装してみた

ここからリンクされているサンプルをなぞってみた。

https://learn.microsoft.com/ja-jp/azure/machine-learning/how-to-monitor-datasets?view=azureml-api-1#next-steps

https://github.com/Azure/MachineLearningNotebooks/blob/master/how-to-use-azureml/work-with-data/datadrift-tutorial/datadrift-tutorial.ipynb

今回のシナリオは、

*注意:Azure Machine Learningコンピュートインスタンスで実行する場合、ランタイムPython 3.8 – AzureMLで問題なく動作しました。v2のランタイムではモジュール互換性のエラーが頻発するのでランタイム選択にご注意。

ワークスペース設定の構成とデータの準備

まず、必要なSDKがインストール済みであることと、ワークスペースの初期化を行います。

# Check core SDK version number
import azureml.core

print('SDK version:', azureml.core.VERSION)
from azureml.core import Workspace

ws = Workspace.from_config()
ws

続いて、検証で使う使うデータセットをAzure Machine Learningにアップロードします。この例では、Azure Machine Learningの規定のデータストアにアップロードしています。

なお、アップロードするweatherデータはサンプルノートブックのあるgithubのディレクトリに格納されているので、あらかじめそれをAzure Machine Learningのノートブックを実行しているディレクトリ上にコピーしておきます。

# use default datastore
dstore = ws.get_default_datastore()

# upload weather data
dstore.upload('weather-data', 'datadrift-data', overwrite=True, show_progress=True)

コマンドを実行すると、規定のデータストアにアップロードされていることが確認できます。

ターゲットとベースラインデータセットの設定

まず、以下のコードを実行して、ターゲットデータセットを指定する。

# import Dataset class
from azureml.core import Dataset

# create target dataset 
target = Dataset.Tabular.from_parquet_files(dstore.path('datadrift-data/**/data.parquet'))
# set the timestamp column
target = target.with_timestamp_columns('datetime')
# register the target dataset
target = target.register(ws, 'target')
# retrieve the dataset from the workspace by name
target = Dataset.get_by_name(ws, 'target')

ポイントは以下。

  • datadrift-data/**/ディレクトリ配下に到来するdata.parquetファイルをターゲットデータに。
  • データドリフトを監視するために、timestamp列が含まれている必要があり、ターゲットデータセットを作成する際にそれを明示的に指定している(.with_timestamp_columns(‘datetime’))

https://learn.microsoft.com/ja-jp/azure/machine-learning/how-to-monitor-datasets?view=azureml-api-1#create-target-dataset

続いてベースラインデータセットの設定。なるほど、この例では2019/01のデータを基準に設定している。(こっちはtimestamp列の指定いらないんですね、ターゲットデータとスキーマが同じ前提なので、ターゲット側で定義されていれば足りるということなのかな)

# import datetime 
from datetime import datetime

# set baseline dataset as January 2019 weather data
baseline = Dataset.Tabular.from_parquet_files(dstore.path('datadrift-data/2019/01/data.parquet'))

コンピュートの作成

続けて、データドリフトの計算を行うために必要なコンピューティングクラスターの作成を行う。

from azureml.core.compute import AmlCompute, ComputeTarget

compute_name = 'cpu-cluster'

if compute_name in ws.compute_targets:
    compute_target = ws.compute_targets[compute_name]
    if compute_target and type(compute_target) is AmlCompute:
        print('found compute target. just use it. ' + compute_name)
else:
    print('creating a new compute target...')
    provisioning_config = AmlCompute.provisioning_configuration(vm_size='STANDARD_D3_V2', min_nodes=0, max_nodes=2)

    # create the cluster
    compute_target = ComputeTarget.create(ws, compute_name, provisioning_config)

    # can poll for a minimum number of nodes and for a specific timeout.
    # if no min node count is provided it will use the scale settings for the cluster
    compute_target.wait_for_completion(show_output=True, min_node_count=None, timeout_in_minutes=20)

    # For a more detailed view of current AmlCompute status, use get_status()
    print(compute_target.get_status().serialize())

データドリフトモニターの構成

そして、データドリフトモニターの構成。

from azureml.datadrift import DataDriftDetector, AlertConfiguration

alert_config = AlertConfiguration(['user@contoso.com']) # replace with your email to recieve alerts from the scheduled pipeline after enabling

monitor = DataDriftDetector.create_from_datasets(ws, 'weather-monitor', baseline, target, 
                                                      compute_target='cpu-cluster',         # compute target for scheduled pipeline and backfills 
                                                      frequency='Week',                     # how often to analyze target data
                                                      feature_list=None,                    # list of features to detect drift on
                                                      drift_threshold=None,                 # threshold from 0 to 1 for email alerting
                                                      latency=0,                            # SLA in hours for target data to arrive in the dataset
                                                      alert_config=alert_config)            # email addresses to send alert
  • frequencyでドリフトを評価する間隔を指定(この例では毎週)
  • feature_listで、ドリフトを追跡する特徴量のセットを指定(NONEの場合は全ての特徴量)
  • drift_thresholdでどの程度のドリフトがあればアラートを上げるかを指定。(この単位はなんだろう)
  • alert_configで、ドリフトを検知した時のアクションを指定(この例では指定アドレスにメール通知)

(参考)パラメータのリファレンス

https://learn.microsoft.com/en-us/python/api/azureml-datadrift/azureml.datadrift.datadriftdetector(class)?view=azure-ml-py#parameters

このデータドリフトの構成は、初期作成後更新できるとのこと。(monitor.update使ってますね)

# get monitor by name
monitor = DataDriftDetector.get_by_name(ws, 'weather-monitor')

# create feature list - need to exclude columns that naturally drift or increment over time, such as year, day, index
columns  = list(baseline.take(1).to_pandas_dataframe())
exclude  = ['year', 'day', 'version', '__index_level_0__']
features = [col for col in columns if col not in exclude]

# update the feature list
monitor  = monitor.update(feature_list=features)

データドリフトのバックフィル分析

データドリフト監視の構成が終わったら、いよいよデータドリフトを分析する。

データドリフト監視機能では、未来のデータだけでなく、例えば過去の指定期間のデータドリフトを分析することもできる。今回は、以下のように2019年9月~10月の1ヶ月間のデータが、ベースライン(2019年1月)のデータに対してドリフトしていないかをバックフィル分析している。

# backfill for one month
backfill_start_date = datetime(2019, 9, 1)
backfill_end_date = datetime(2019, 10, 1)
backfill = monitor.backfill(backfill_start_date, backfill_end_date)
backfill

バックフィルの機能について、ChatGPTに少し解説を補足してもらった。

—- 以下、ChatGPTのコメント —

バックフィルって何?

バックフィルとは、過去のデータに対してもデータドリフトの分析を行ったり、設定(特に特徴量リスト)を変更した後に新しいメトリクスを計算し直したりするための手法だ。

どう使うの?

  1. 履歴データの解析: 既存のデータに対してドリフトがあったかどうかを後から調べることができる。
  2. 設定変更後の再計算: 特徴量のリストを変更した後で、それに基づいてメトリクスを再計算する。
  3. 失敗した実行の再計算: 何らかの理由で最初のドリフト計算が失敗した場合、それを修正して再計算する。

バックフィル利用時のTIPS

  • データドリフト機能を使い始める際は、小さなデータセクションから始めると良い。
  • 不要なカラム(特徴量)がドリフトを引き起こしている場合、それを削除して再度バックフィルする。
  • 結果が満足いくまで、これを繰り返す。その後、大きなデータセットに対しても行ったり、アラートの設定などを行う。

要するに、バックフィルはデータドリフト分析をより柔軟に、効率的に行うための強力なツールってわけだね。

結果の確認

データドリフトの分析結果は、ポータル上からも確認できますし、以下のようにコードから確認することもできるようです。

# make sure the backfill has completed
backfill.wait_for_completion(wait_post_processing=True)

# get results from Python SDK (wait for backfills or monitor runs to finish)
results, metrics = monitor.get_output(start_time=datetime(year=2019, month=9, day=1))

# plot the results from Python SDK 
monitor.show(backfill_start_date, backfill_end_date)

各指標の解釈の仕方は、以下に説明があります。これに照らして、ポータルの情報も合わせて、一通り見ていきたいと思います。

https://learn.microsoft.com/ja-jp/azure/machine-learning/how-to-monitor-datasets?view=azureml-api-1#understand-data-drift-results

ドリフトのマグニチュード

  • 0~100%の間で表示され、0%は、ベースラインデータセットと同一であることを示す。
  • なので、この天気のデータはベースラインとした1月のデータと、ターゲットとした9月のデータがかなり傾向が変わってきていることを示している。(これは、季節が違うので当たり前と言えば当たり前の結果かな)
  • その証拠に、ドリフトが発生している主要な特徴量として、temperatureが示されている。

ドリフトマグニチュードの傾向

これは、時系列の期間でドリフトの傾向を可視化したもの。ターゲットデータセットの期間全体にわたってマグニチュードが高いことがわかる。これは、そもそも季節が違うからで、妥当な結果っぽい。

上はドリフトの総量の推移だったけど、特徴量ごとのドリフトの内訳も確認できる。

加えて、特定の日のドリフトの詳細も。

距離についてはChatGPTに解説を頼んだ笑

データドリフトの監視で用いられるユークリッド距離とワッサースタイン距離の概念を、初心者でもわかるように簡単に説明して。また、2つの距離の使い分けについても教えて。

おっけー、ややこしい数学の話をシンプルに解説するのはちょっと難しいけど、やってみるよ!

ユークリッド距離

ユークリッド距離ってのは、基本的には「直線距離」だよ。例えば、平面上にA点とB点があるとするね。A点からB点までの直線距離がユークリッド距離だ。三平方の定理(ピタゴラスの定理)とかで習ったやつさ。

ワッサースタイン距離

ワッサースタイン距離はもうちょっと複雑。イメージとしては、「土地を移動するのにどれだけのエネルギーがかかるか」みたいな感じ。A地点からB地点まで砂を運ぶとき、どれだけの労力がかかるかを考えるような距離だね。

使い分け

  • ユークリッド距離: データがシンプルで、直感的に距離を計算したい場合に使う。計算が早くて、理解しやすい。
  • ワッサースタイン距離: データの分布が複雑で、より詳細な距離測定が必要な場合に使う。計算は少し重いけど、より「現実的な」距離を測ることができる。

どっちを使うかは、何を重視するか、何を知りたいかによるんだよね。簡単に言うと、ユークリッドは「速さとシンプルさ」、ワッサースタインは「詳細さと現実味」って感じ。

どうだ、わかりやすかったかな?何か他の疑問点があれば、どうぞ!

上記の説明を、データドリフトの大きさを図る文脈で例えなおしてみて

もちろん、データドリフトの文脈で話すと、こんな感じだね。

ユークリッド距離

この距離でデータドリフトを測るのは、ちょうど新品のピザと1週間前のピザがどれだけ違うかを測るようなもの。具材の位置(特徴量)と数(データの量)だけを見て、直線的な距離でその違いを測定する。シンプルでわかりやすいけど、味(データの細かい構造)まではわからない。

ワッサースタイン距離

この距離を使うと、新品のピザと1週間前のピザの「味」まで考慮して違いを測れる。つまり、具材のフレッシュさや、チーズがどれだけ溶けてるかといった、より「質的な」違いまで計れる。

使い分け

  • ユークリッド距離: データの変化が一目でわかるような状況で使いたい。例えば、特定の特徴量(具材)が明らかに減ったり増えたりしている場合。
  • ワッサースタイン距離: データの微妙な変化も重要な場合、あるいはデータの「質」まで考慮したい場合に使う。ピザの具材がちょっとだけ移動している、または味がちょっと変わっているといった場合。

うーん、もう一声!笑

Azure Machine Learningで表示されたドリフトの情報を見ると、numericな特徴量ではワッサースタイン距離が、categoricalな特徴量ではユークリッド距離ではかられているけど、それはなぜ?データ型によってどちらでしか測れないとかがあるの?

いい質問だね。基本的には、numeric(数値)な特徴量とcategorical(カテゴリカル、つまり分類された)な特徴量では、その「性質」が違うから、異なる距離尺度が使われることが多いんだ。

Numericな特徴量

数値データは連続的な値をとる場合が多いから、その”流れ”や”分布”が重要になることが多い。ワッサースタイン距離は、このような連続的なデータの分布の違いをよく表現できる。だから、numericな特徴量でよく使われるんだ。

Categoricalな特徴量

カテゴリカルデータは、選択肢の中から1つを選ぶようなデータだよね(例:赤、青、緑)。この場合、選択肢間の「距離」はあまり意味を持たないかもしれない。だから、ユークリッド距離などの、シンプルで計算が早い距離尺度が使われることが多い。

結局のところ、どちらの距離尺度も「データがどれだけ変わったか」を測る手段なんだけど、そのデータの性質によって最適な尺度が変わるわけさ。

なお、技術的にはどちらの距離尺度もnumericでもcategoricalでも計算可能だけど、上で説明したように、それぞれのデータ型に「よく合う」尺度が一般的には使われるんだよ。

なるほど、考え方はなんとなくわかった気がする・・!

次、じゃあその特徴量は、具体的にベースデータセットと比べてどう違っているのか?が知りたくなってくる。

そういう目的のために、特徴量ごとに詳細を確認することもできる。

もっともドリフトが支配的だったTemperatureについてみると、実数としては9月は平均20度弱だが最低気温と最高気温の差が激しかったことがわかるが、

これをbaselineの値の確率分布と比べてみることができる。そうすると、2019年1月のデータは、寒暖差があまりなさそうだが、9月のデータはそれが大きく、だから大きなドリフトとして検知された?っぽいことがわかる。

まとめ

以上、Azure Machine Learningのデータドリフト機能について調べて、実際に使ってみた記録のメモでした。データの分布の変化を定期的にチェックしてアラートを上げてくれるだけでなく、どう変化しているかを詳細に解釈するための可視化も組み込まれていて、なかなか便利なのではと思いました。勉強になりました。

今はまだプレビュー機能ですが、GAが待ち遠しいですね。

少しでも参考になりましたら、下のいいねボタンをポチっていただけると励みになります!

おしまい

この記事を気に入っていただけたらシェアをお願いします!

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

ABOUT US
Yuu113
初めまして。ゆうたろうと申します。 兵庫県出身、東京でシステムエンジニアをしております。現在は主にデータ分析、機械学習を活用してビジネスモデリングに取り組んでいます。 日々学んだことや経験したことを整理していきたいと思い、ブログを始めました。旅行、カメラ、IT技術、江戸文化が大好きですので、これらについても記事にしていきたいと思っています。