こんにちは。今日は、前から気になっていた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のデータドリフト機能は、本番環境のデータとモデルが訓練された際のデータとの間に発生する「ドリフト」を検出するためのものだよ。要は、モデルが元々学習したデータと新しく入ってくるデータがどれくらい違うのか、リアルタイムでチェックしてくれるんだ。
その価値は?
- 早期発見: データが変わり始めたらすぐに気づける。それで、問題が大きくなる前に対処できる。
- 信頼性: モデルの予測が信頼できるかどうか、常に確認できる。
- メンテナンス: モデルを時々更新する必要があるけど、いつやるべきかをデータドリフトが教えてくれる。
簡単に言うと、データドリフト機能は、モデルが期待通りに動いているかどうかを確認するための「警告システム」みたいなものだね。データが変わってきたら、それに合わせてモデルも更新しないといけないから、非常に役立つ機能だよ。
データドリフト監視構成の流れ
Azure Machine Learningでデータドリフトを監視するのは、大体以下のようなステップで行うんだ。
- ベースラインデータ登録: 最初に、モデルの訓練に使ったデータ(ベースラインデータ)をAzure ML Studioに登録する。
- ターゲットデータ登録: 次に、本番環境で入ってくる新しいデータ(ターゲットデータ)もAzureで登録する。
- ドリフト検出の設定: どの特徴量を監視するのか、どれくらいの頻度でチェックするのかなど、データドリフトの設定を行う。
- アラート設定: ドリフトが一定の閾値を超えた場合に通知が来るようにアラートを設定する。
- 監視開始: 以上の設定が完了したら、監視を開始。Azureが自動でデータドリフトをチェックしてくれる。
- 結果確認: 定期的にAzure ML Studioで監視結果をチェック。ドリフトが見つかったら、どう対処するかを考える。
- モデル更新: データドリフトが確認された場合、新しいデータでモデルを更新する。
このようにベースラインデータとターゲットデータをしっかりと登録しておくことで、より正確なドリフト検出が可能になるんだ。
実装してみた
ここからリンクされているサンプルをなぞってみた。
今回のシナリオは、
*注意: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’))
続いてベースラインデータセットの設定。なるほど、この例では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で、ドリフトを検知した時のアクションを指定(この例では指定アドレスにメール通知)
(参考)パラメータのリファレンス
このデータドリフトの構成は、初期作成後更新できるとのこと。(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のコメント —
バックフィルって何?
バックフィルとは、過去のデータに対してもデータドリフトの分析を行ったり、設定(特に特徴量リスト)を変更した後に新しいメトリクスを計算し直したりするための手法だ。
どう使うの?
- 履歴データの解析: 既存のデータに対してドリフトがあったかどうかを後から調べることができる。
- 設定変更後の再計算: 特徴量のリストを変更した後で、それに基づいてメトリクスを再計算する。
- 失敗した実行の再計算: 何らかの理由で最初のドリフト計算が失敗した場合、それを修正して再計算する。
バックフィル利用時の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)
各指標の解釈の仕方は、以下に説明があります。これに照らして、ポータルの情報も合わせて、一通り見ていきたいと思います。
ドリフトのマグニチュード
- 0~100%の間で表示され、0%は、ベースラインデータセットと同一であることを示す。
- なので、この天気のデータはベースラインとした1月のデータと、ターゲットとした9月のデータがかなり傾向が変わってきていることを示している。(これは、季節が違うので当たり前と言えば当たり前の結果かな)
- その証拠に、ドリフトが発生している主要な特徴量として、temperatureが示されている。
ドリフトマグニチュードの傾向
これは、時系列の期間でドリフトの傾向を可視化したもの。ターゲットデータセットの期間全体にわたってマグニチュードが高いことがわかる。これは、そもそも季節が違うからで、妥当な結果っぽい。
上はドリフトの総量の推移だったけど、特徴量ごとのドリフトの内訳も確認できる。
加えて、特定の日のドリフトの詳細も。
距離についてはChatGPTに解説を頼んだ笑
うーん、もう一声!笑
なるほど、考え方はなんとなくわかった気がする・・!
次、じゃあその特徴量は、具体的にベースデータセットと比べてどう違っているのか?が知りたくなってくる。
そういう目的のために、特徴量ごとに詳細を確認することもできる。
もっともドリフトが支配的だったTemperatureについてみると、実数としては9月は平均20度弱だが最低気温と最高気温の差が激しかったことがわかるが、
これをbaselineの値の確率分布と比べてみることができる。そうすると、2019年1月のデータは、寒暖差があまりなさそうだが、9月のデータはそれが大きく、だから大きなドリフトとして検知された?っぽいことがわかる。
まとめ
以上、Azure Machine Learningのデータドリフト機能について調べて、実際に使ってみた記録のメモでした。データの分布の変化を定期的にチェックしてアラートを上げてくれるだけでなく、どう変化しているかを詳細に解釈するための可視化も組み込まれていて、なかなか便利なのではと思いました。勉強になりました。
今はまだプレビュー機能ですが、GAが待ち遠しいですね。
少しでも参考になりましたら、下のいいねボタンをポチっていただけると励みになります!
おしまい
コメントを残す