モデルモニタリングに使用する関数を試してみる
はじめに
こんにちは、クラウドエース データソリューション部のジンです。
クラウドエースの IT エンジニアリングを担う システム開発統括部 の中で、特にデータ基盤構築・分析基盤構築からデータ分析までを含む一貫したデータ課題の解決を専門とするのが データソリューション部 です。
今回は2024年4月4日にリリースされた、BigQuery ML の モデル モニタリング関数 について紹介します。
これらの関数を使用すると、BigQuery ML でトレーニング データとサービング データのデータスキューやデータドリフトを分析できます。
(該当リリースノート:BigQuery release notes - April 04, 2024)
データスキューとデータドリフト
定義
- データスキュー: トレーニングデータの特徴値の分布がサービングデータと大きく異なる場合に発生します。BigQuery ML ではトレーニング時の統計情報を保存しているため、元のトレーニングデータがなくても差異の検出が可能です。
- データドリフト: 特徴データの分布が時間の経過とともに大きく変化する場合に発生します。BigQuery ML では連続したデータスパンでの検出がサポートされ、データの変化に関する通知を受けることが可能です。
モニタリングをするユースケース
- データスキューの基本的なモニタリング
データスキュー検出モデルを迅速に開発および監視し、既存のモニタリング ソリューションと統合するためのきめ細かいデータスキュー統計情報を必要としないシナリオに最適です。
※ モニタリング関数については、後述します。
- データドリフトの基本的なモニタリング
データドリフト検出モデルを迅速に開発および監視し、既存のモニタリング ソリューションと統合するためのきめ細かいデータドリフト統計情報を必要としないシナリオに最適です。
モデルモニタリングに使用する関数
今回公開された関数は以下の 5 つです。
- ML.DESCRIBE_DATA: トレーニングデータまたはサービングデータの記述統計(データの特徴を表現する数値)を計算します。
- ML.VALIDATE_DATA_SKEW: サービングデータの統計情報を計算し、トレーニングデータの統計情報と比較してデータスキューを特定します。
- ML.VALIDATE_DATA_DRIFT: 2 つのサービングデータセットの統計情報を比較し、データドリフトを特定します。
- ML.TFDV_DESCRIBE: 詳細な記述統計を計算します。TensorFlow の tfdv.generate_statistics_from_csv と同様の動作を行います。
- ML.TFDV_VALIDATE: トレーニングデータとサービングデータ、または 2 つのサービングデータの統計情報を比較して異常な差異を特定します。TensorFlow の tfdv.validate_statistics と同様の動作を行います。
モニタリング関数を試してみた
以下では「ペンギン体重予測モデル」を使って、各モニタリング関数の使い方を詳しく紹介します。
「ペンギン体重予測モデル」は、線形回帰モデルを使用し、ペンギンの属性情報に基づいてペンギンの体重を予測します。
トレーニングに使用されるデータはbigquery-public-data.ml_datasets.penguins
となります。
項目名 | 説明 |
---|---|
body_mass_g | ペンギンの体重 |
species | ペンギンの種類 |
island | ペンギンが生息する島 |
culmen_length_mm | ペンギンのくちばしの長さ(ミリメートル) |
culmen_depth_mm | ペンギンのくちばしの高さ(ミリメートル) |
flipper_length_mm | ペンギンの翼の長さ(ミリメートル) |
sex | ペンギンの性別 |
BigQueryで次のクエリを実行して、線形回帰モデルを作成します。
CREATE OR REPLACE MODEL `bqml_tutorial.penguins_model`
OPTIONS
(model_type='linear_reg',
input_label_cols=['body_mass_g']) AS
SELECT
*
FROM
`bigquery-public-data.ml_datasets.penguins`
WHERE
body_mass_g IS NOT NULL;
ML.DESCRIBE_DATA
ML.DESCRIBE_DATA 関数は、テーブルまたはサブクエリの列の記述統計を生成できます。
ペンギン体重予測モデルのデータを例として、この関数を試してみましょう。
SELECT *
FROM ML.DESCRIBE_DATA(
TABLE `bigquery-public-data.ml_datasets.penguins`,
STRUCT(5 AS num_quantiles, 3 AS top_k)
);
上記のコードに使った引数は以下の通りです。
引数名 | 説明 |
---|---|
project_id | プロジェクト ID |
dataset | テーブルを含む BigQuery データセット |
table | 統計を計算するトレーニング データまたはサービング データを含む入力テーブルの名前 |
num_quantiles | 数値列のデータの分布を示す分位数(データを一定の割合で分割する点の値)(デフォルト値は 2) |
top_k | カテゴリ列で最も頻繁に表示される値の数量(デフォルト値は 1) |
num_quantiles
、top_k
の指定について、より粗い分布情報を得たい場合は小さい値を指定し、より細かい分布情報を得たい場合は大きな値を指定します。
※ その他の引数を含む引数一覧は公式ドキュメントをご参照ください。
コードを実行した結果は以下の通りです。
数値列の場合、ペンギンの体重 body_mass_g
を例に挙げると、ML.DESCRIBE_DATA 関数は最小値、最大値、平均値、標準偏差、中央値、および分位値のカスタム数を含む値を生成できます。
カテゴリ列の場合、ML.DESCRIBE_DATA 関数は列内で最も頻繁に表示されるデータと、そのデータが表示される回数を計算できます。
出力項目の説明は以下の通りです。
出力 | 説明 |
---|---|
name | 入力列の名前 |
num_rows | 入力列の合計行数 |
num_nulls | 入力列に含まれる null 値の数 |
num_zeros | 数値、数値配列または数値タイプの場合、列内で見つかった 0 値の数を返します;カテゴリまたはカテゴリ配列の場合、NULL を返します。 |
min | 入力列の最小値 |
max | 入力列の最大値 |
mean | 数値、数値配列または数値タイプの構造体の場合、その列に対して計算された平均値を返します;カテゴリまたはカテゴリ配列の場合、NULL を返します。 |
stdev | 数値、数値配列または数値タイプの構造体の場合、その列に対して計算された標準偏差値を返します;カテゴリまたはカテゴリ配列の場合、NULL を返します。 |
median | 数値、数値配列または数値タイプの構造体の場合、その列に対して計算された中央値を返します;カテゴリまたはカテゴリ配列の場合、NULL を返します。 |
quantiles | 数値、数値配列または数値タイプの構造体の場合、その列に対して計算された分位数を返します;カテゴリまたはカテゴリ配列の場合、NULL を返します。 |
unique | カテゴリまたはカテゴリ配列の場合、unique 値の数を返します;数値、数値配列または数値タイプの構造体の場合、NULL を返します。 |
avg_string_length | カテゴリまたはカテゴリ配列の場合、列内の値の平均文字列長を返します;数値、数値配列または数値タイプの構造体の場合、NULL を返します。 |
num_values | 配列の場合、配列要素の数を返します;配列以外のタイプの場合、列内の値の数を返します。 |
top_values | top_values.value:カテゴリまたはカテゴリ配列の場合、入力列の上位値の 1 つを返します;数値、数値配列または数値タイプの構造体の場合、NULL を返します。 top_values.count:カテゴリまたはカテゴリ配列の場合、関連する上位値の示す回数を返します;数値、数値配列または数値タイプの構造体の場合、NULL を返します。 |
※ その他の出力項目を含む項目一覧は公式ドキュメントをご参照ください。
ML.VALIDATE_DATA_SKEW
ML.VALIDATE_DATA_SKEW 関数は、トレーニングデータの特徴列と一致するサービングデータの特徴列の統計を計算し、モデルの作成時にトレーニングデータに対して計算された統計と比較し、2 つのデータセット間の異常な差異がある部分を特定するのに役立ちます。
以下のコードを実行することで、ビスコー諸島をサービングデータとして使用し、すでに前の章で作成済みである「bqml_tutorial.penguins_model」のトレニングデータとサービングデータのデータスキューを検証してみます。
SELECT *
FROM ML.VALIDATE_DATA_SKEW(
MODEL `bqml_tutorial.penguins_model`,
(
SELECT
*
FROM
`bigquery-public-data.ml_datasets.penguins`
WHERE island = 'Biscoe'),
STRUCT(0.2 AS categorical_default_threshold)
);
実行したコードに使った引数は以下の通りです。
引数名 | 説明 |
---|---|
project_id | プロジェクト ID |
dataset | テーブルを含む BigQuery データセット |
model | モデルの名前 |
table | 統計を計算するサービングデータを含む入力テーブルの名前 |
query_statement | 統計を計算するトレーニングデータまたはサービングデータを生成するクエリ |
categorical_default_threshold | カテゴリおよび配列形式のカテゴリデータの特徴列の異常検出に使用するカスタムしきい値。(値の範囲 [0, 1)、デフォルト値は 0.3) |
※ その他の引数を含む引数一覧は公式ドキュメントをご参照ください。
結果は次の通りです。
出力項目の説明は以下の通りです。
出力 | 説明 |
---|---|
input | 入力した特徴列の名前 |
metric | 特徴列の統計を比較するために使用されるメトリックの名前 |
threshold | トレーニングデータとサービングデータ間の特徴列の統計的差異が異常かどうかを判断するために使用されるしきい値 |
value | サービングデータとトレーニングデータ間の特徴列の統計的差異値 |
is_anomaly | value が threshold より大きい場合は true、threshold より小さい場合は false |
カテゴリしきい値が 0.2 の場合、トレーニングデータと比較したビスコー諸島のペンギンのデータのうち、island
および species
列の value
がカテゴリしきい値より高いため、異常であることがわかります。
ML.VALIDATE_DATA_DRIFT
ML.VALIDATE_DATA_DRIFT 関数は、2 つのサービングデータセットの統計を計算して比較し、2 つのデータセット間に異常な差異があるかどうかを確認します。
次のコードを実行することで、ビスコー諸島とトージャーセン島のデータを 2 つのサービングデータセットとして使用し、2 つのデータセット間の差異を比較します。
SELECT *
FROM ML.VALIDATE_DATA_DRIFT(
(
SELECT
*
FROM
`bigquery-public-data.ml_datasets.penguins`
WHERE island = 'Biscoe'),
(
SELECT
*
FROM
`bigquery-public-data.ml_datasets.penguins`
WHERE island = 'Torgersen'),
STRUCT(0.2 AS categorical_default_threshold)
);
上記のコードに使った引数は以下の通りです。
引数名 | 説明 |
---|---|
project_id | プロジェクト ID |
dataset | テーブルを含む BigQuery データセット |
base_table | 比較のベースラインとして使用するサービングデータの入力テーブルの名前 |
base_query_statement | 比較のベースラインとして使用するサービングデータを生成するクエリ |
study_table | ベースラインと比較するサービングデータを含む入力テーブルの名前 |
study_query_statement | ベースラインと比較するサービングデータを生成するクエリ |
categorical_default_threshold | カテゴリおよび配列形式のカテゴリデータの特徴列の異常検出に使用するカスタムしきい値。(値の範囲 [0, 1)、デフォルト値は 0.3) |
※ その他の引数を含む引数一覧は公式ドキュメントをご参照ください。
コードを実行した結果は次の図の通りです。
出力項目は ML.VALIDATE_DATA_SKEW の出力項目と同様です。
この図に示された結果から、2 つのデータセットの island
列が完全に異なるため、差異値は 1 となっていることが分かります。sex
列を除いて、残りの特徴列の差異値は設定したしきい値よりも高く、島ごとにペンギンの体重関連データに大きな差異があることがわかります。
ML.TFDV_DESCRIBE
ML.TFDV_DESCRIBE 関数は、トレーニングまたはサービングデータのセットに対して詳細な記述統計を計算します。TensorFlow の tfdv.generate_statistics_from_csv API と同じ動作結果が得られます。
前文の ML.DESCRIBE_DATA 関数の例と同様に、「bqml_tutorial.penguins_model」モデルのトレーニングデータを使用してこの関数を試してみます。
SELECT * FROM ML.TFDV_DESCRIBE(
TABLE `bigquery-public-data.ml_datasets.penguins`,
STRUCT(5 AS num_rank_histogram_buckets)
);
上記のコードに使った引数は以下の通りです。
引数名 | 説明 |
---|---|
project_id | プロジェクト ID |
dataset | テーブルを含む BigQuery データセット |
table | 統計を計算するトレーニングデータまたはサービングデータを含む入力テーブルの名前 |
query_statement | 統計を計算するトレーニングデータまたはサービングデータを生成するクエリ |
num_rank_histogram_buckets | ランクヒストグラムに使用するバケットの数を指定する値。カテゴリ列と配列形式のカテゴリデータ列にのみ適用されます。(デフォルト値は 50) |
※ その他の引数を含む引数一覧は公式ドキュメントをご参照ください。
ML.TFDV_DESCRIBE は JSON 形式の TensorFlow DatasetFeatureStatisticsList protocol buffer を含む dataset_feature_statistics_list 列を返します。
以下は返された結果の一部を示します。
[
{
"dataset_feature_statistics_list": "{
"datasets" : [
{
"features" : [
{
"name" : "body_mass_g",
"num_stats" : {
"common_stats" : {
"avg_num_values" : 1,
"max_num_values" : 1,
"min_num_values" : 1,
"num_missing" : 2,
"num_non_missing" : 342,
"num_values_histogram" : {
"buckets" : [
{
"high_value" : 1,
"low_value" : 1,
"sample_count" : 34.2
},
{
"high_value" : 1,
"low_value" : 1,
"sample_count" : 34.2
},
{
"high_value" : 1,
"low_value" : 1,
"sample_count" : 34.2
},
{
"high_value" : 1,
"low_value" : 1,
"sample_count" : 34.2
},
{
"high_value" : 1,
"low_value" : 1,
"sample_count" : 34.2
},
{
"high_value" : 1,
"low_value" : 1,
"sample_count" : 34.2
},
{
"high_value" : 1,
"low_value" : 1,
"sample_count" : 34.2
},
{
"high_value" : 1,
"low_value" : 1,
"sample_count" : 34.2
},
{
"high_value" : 1,
"low_value" : 1,
"sample_count" : 34.2
},
{
"high_value" : 1,
"low_value" : 1,
"sample_count" : 34.2
}
],
}
}
}
}
]
……
(以下省略)"
}
]
}"
}
]
ML.TFDV_VALIDATE
ML.TFDV_VALIDATE 関数はトレーニングデータとサービングデータ、または 2 つのサービングデータセットの統計を計算し比較して、2 つのデータセット間の異常な差異を特定します。この関数は、TensorFlow の validate_statistics API と同じ動作結果が得られます。
ML.VALIDATE_DATA_DRIFT 関数の例と同様に、ビスコー諸島とトージャーセン島のデータを 2 つのサービングデータセットとして使用し、この関数を試してみます。
SELECT ML.TFDV_VALIDATE(
(SELECT * FROM ML.TFDV_DESCRIBE((
SELECT
*
FROM
`bigquery-public-data.ml_datasets.penguins`
WHERE island = 'Biscoe'))),
(SELECT * FROM ML.TFDV_DESCRIBE((
SELECT
*
FROM
`bigquery-public-data.ml_datasets.penguins`
WHERE island = 'Torgersen'))),
'DRIFT'
);
上記のコードに使った引数は以下の通りです。
※ ここでの引数は、 ML.TFDV_DESCRIBE 関数を使用して、先にデータの統計値を生成する必要があることに注意してください。
引数名 | 説明 |
---|---|
base_statistics | 比較のベースラインとして使用するトレーニングデータまたはサービングデータの統計 |
study_statistics | ベースラインと比較するトレーニングデータまたはサービングデータの統計 |
detection_type |
SKEW の場合トレーニングデータとサービングデータ間の統計的変動を表すデータスキューを返します。DRIFT の場合 2 つの異なるサービングデータセット間の統計的変動を表すデータドリフトを返します。 |
※ その他の引数を含む引数一覧は公式ドキュメントをご参照ください。
ML.TFDV_VALIDATE は、TensorFlow Anomalies protocol buffer を JSON 形式で返します。
以下は返された結果の一部を示します。
[
{
"f0_": "{
"anomaly_info" : {
"body_mass_g" : {
"description" : "The approximate Jensen-Shannon divergence between current and previous is 0.442615 (up to six significant digits),
above the threshold 0.3.",
"path" : {
"step" : [
"body_mass_g"
]
},
"reason" : [
{
"description" : "The approximate Jensen-Shannon divergence between current and previous is 0.442615 (up to six significant digits),
above the threshold 0.3.",
"short_description" : "High approximate Jensen-Shannon divergence between current and previous",
"type" : "COMPARATOR_JENSEN_SHANNON_DIVERGENCE_HIGH"
}
],
"severity" : "ERROR",
"short_description" : "High approximate Jensen-Shannon divergence between current and previous"
},
……
(以下省略)"
}"
}
}
]
まとめ
どのようなデータを使用するかはモデルのパフォーマンスに影響するため、データの理解は機械学習の重要な作業となります。したがって、データの差異を理解することは、モデルの精度を確保するために特に重要です。
上記のモデルモニタリング関数を組み合わせて使用すると、モデルで使用されるデータをより深く理解し、モデルの精度を向上させることができるようになります。
Discussion