TensorFlow Data Validation によるトレーニング / サービング スキューの分析

このドキュメントは、データ スキュー検知のために、AI Platform Prediction にデプロイされている機械学習(ML)モデルをモニタリングする方法について説明するシリーズの 3 番目のパートです。このガイドでは、TensorFlow Data Validation(TFDV)を使用してトレーニング / サービング データ スキューを検知するためのコンセプトと実装方法に焦点を当てています。

このガイドは、時間の経過とともにデータがどのように変化するかをモニタリングし、データ スキューと異常を特定するデータ サイエンティストと ML エンジニアを対象としています。このドキュメントは、Google Cloud、BigQuery、Jupyter ノートブックの使用経験があることを前提としています。

このシリーズは、次のガイドで構成されています。

このドキュメントで説明するプロセスのコードは、Jupyter ノートブックに組み込まれています。ノートブックは GitHub リポジトリにあります。

データ ドリフトとコンセプト ドリフトについて

本番環境における ML モデルの予測パフォーマンスのモニタリングが、MLOps の重要な分野になっています。時間経過に伴うモデルの予測パフォーマンスの低下の一般的な原因として、次の 2 つが考えられます。

  • トレーニング データとサービング データとの間のスキューが大きくなります。この問題は、データドリフトと呼ばれています。
  • 入力予測とターゲット特徴量との間の関係の解釈が変化します。この問題はコンセプト ドリフトと呼ばれています。

データ ドリフトでは、モデルがスコアリングのために受け取る本番環境のデータは、モデルのトレーニング、調整、評価に使用されたデータセットとは異なります。トレーニング データとサービング データの相違は、一般にスキーマ スキューまたは分布スキューとして分類されます。

  • スキーマ スキューは、トレーニング データとサービング データが同じスキーマに従っていない場合に発生します。スキーマ スキューは、サービング データを生成するアップストリーム プロセス内の障害や変更が原因でよく発生します。トレーニング データとサービング データのスキーマの相違は、以下を含みます。

    • 一貫性のない特徴量 - たとえば、サービング データに新しい特徴量が追加されている。
    • 一貫性のない特徴量の型 - たとえば、トレーニング データでは整数だった数値特徴量が、サービング データでは実数になっている。
    • 一貫性のない特徴量のドメイン - たとえば、カテゴリ特徴量の値が消えている、または数値特徴量の範囲に変更がある。
  • 分布スキューは、トレーニング データの特徴量の分布がサービング データと大きく異なる場合に発生します。このスキューは、実際のデータを表すために誤ったトレーニング データセットを選択することでも発生します。このスキューは、環境の変遷における変化により、データに新しい傾向とパターンが出現すると、自然に発生する場合もあります。たとえば、不動産価格の変化や、ファッション アイテムの人気度の変化などです。

コンセプト ドリフトは、データの解釈が変化したことを意味します。コンセプト ドリフトは、多くの場合、トレーニング中に使用されたラベルに対する入力特徴量のマッピングが有効ではなくなるか、新しいクラスまたはラベル値の範囲が登場したことを意味します。コンセプト ドリフトは、モデル化しようとするプロセスにおける変化により、よく発生します。それはまた、このプロセスの理解の進化にもなります。

このドキュメントでは、特に、トレーニング データとサービング データとの間のスキーマ スキューと特徴量分布のスキューの検知のような、データ ドリフトのシナリオに焦点を当てます。

アーキテクチャの概要

次の図は、このドキュメントで説明する環境を示したものです。

このチュートリアル シリーズで作成されるフローのアーキテクチャ。

このアーキテクチャでは、AI Platform Prediction のリクエスト / レスポンス ロギングにより、オンライン リクエストのサンプルのログが BigQuery テーブルに記録されます。その後、Notebooks と TFDV を使用して、このデータを解析し、記述統計を計算して、データスキューとデータ ドリフトを可視化できます。

サービング データのキャプチャ

このシリーズの以前のドキュメント(AI Platform Prediction を使用したサービング リクエストのロギング)では、オンライン予測用の Keras モデルをデプロイするために、AI Platform Prediction を使用する方法を説明しています。また、リクエスト / レスポンス ロギングを有効にする方法も説明しています。これにより、オンライン予測のリクエストとレスポンスのサンプルのログが BigQuery テーブルに記録されます。

ログが記録されたリクエスト インスタンスとレスポンス予測は、未加工の形式で保存されます。このシリーズの前のドキュメントでは、これらの未加工ログを解析し、構造化ビューを作成して、入力特徴と出力予測を分析する方法が示されます。このドキュメントでは、Google データポータルを使用して特徴値が時間とともに変化する様子を可視化する方法についても説明します。この可視化は、予測スキューを引き起こす可能性のあるデータ内の外れ値を見つける場合にも役立ちます。

サービング データ スキューの検知

可視化されたものを調べるだけで、データ内の潜在的なスキューや異常を手動で特定することは困難です。入力特徴量が多い場合は、特に困難です。したがって、サービング データにおける潜在的な問題を積極的にハイライト表示するには、本番環境でのスケーラブルで自動的な方法が必要です。

このドキュメントでは、TFDV を使用してデータスキューを検出、分析、可視化する方法について説明します。TFDV は、予想されるスキーマと、トレーニング データから生成された統計値に対してサービング データログを分析することで、異常値を特定し、トレーニング / サービング スキューを検出するのに役立ちます。前のアーキテクチャ図に示すように、TFDV ツールをインタラクティブに使用するには、ノートブックを使用します。

TFDV を使用してトレーニング / サービング スキューを検知する

次の図は、TFDV を使用して BigQuery のリクエスト / レスポンスのサービング ログにおけるスキューを検知して分析する方法のワークフローを示しています。

トレーニング / サービング スキューを検知するためのワークフロー。

このワークフローは次のフェーズから構成されます。

  1. トレーニング データからのベースライン統計と参照スキーマの生成。その後、ベースラインの統計と参照スキーマを使用して、サービング データを検証できます。
  2. サービング データ スキューの検知。このプロセスでは、サービング データの統計が生成され、参照スキーマに対するサービング データの検証時に、検知された異常を特定します。
  3. 検証出力の分析と可視化。生成された異常は可視化されて、分析され、スキューの分布を示すために統計が可視化されます。

目標

  • ベースライン統計と参照スキーマを生成する。
  • サービング スキューを検知する。
  • 検証出力を分析して可視化する。

料金

このチュートリアルでは、課金対象である次の Google Cloud コンポーネントを使用します。

料金計算ツールを使うと、予想使用量に基づいて費用の見積もりを生成できます。新しい Google Cloud ユーザーは無料トライアルをご利用いただけます。

始める前に

始める前に、このシリーズのパート 1パート 2 を完了する必要があります。

これらのパートを完了すると、以下の準備ができます。

  • TensorFlow 2.3 を使用する Notebooks インスタンス
  • このガイドで必要な Jupyter ノートブックを含む GitHub リポジトリのクローン。
  • リクエスト / レスポンスのログと、未加工のリクエスト / レスポンスのデータポイントを解析するビューを含む BigQuery テーブル。

このシナリオ用の Jupyter ノートブック

このワークフローのプロセスは、始めから終わりまで、このドキュメントに関連付けられている GitHub リポジトリの Jupyter ノートブックに組み込まれています。このノートブックの手順は、UCI Machine Learning Repository の Covertype データセットに基づいています。このデータセットは、このシリーズの前のドキュメントでサンプルデータに使用したものと同じです。

ノートブック設定の構成

このセクションでは、Python 環境を準備し、シナリオのコードを実行するために必要となる変数を設定します。

  1. Cloud Console でパート 1 の AI Platform Notebooks インスタンスをまだ開いていない場合は、次の操作を行います。

    1. [Notebooks] ページに移動します。

      [Notebooks] ページに移動

    2. Notebooks インスタンス リストでノートブックを選択し、[Jupyterlab を開く] をクリックします。ブラウザで JupyterLab 環境が開きます。

    3. ファイル ブラウザで mlops-on-gcp ファイルを開き、skew-detection ディレクトリに移動します。

  2. 03-covertype-drift-detection_tfdv.ipynb ノートブックを開きます。

  3. ノートブックの [設定] で、[パッケージと依存関係のインストール] セルを実行して、必要な Python パッケージをインストールし、環境変数を構成します。

  4. [Google Cloud 環境設定の構成] で、次の変数を設定します。

    • PROJECT_ID: リクエスト / レスポンス データの BigQuery データセットがロギングされる Google Cloud プロジェクトの ID。
    • BUCKET: 生成されたアーティファクトを保存する Cloud Storage バケットの名前。
    • BQ_DATASET_NAME: リクエスト / レスポンスのログが保存される BigQuery データセットの名前。
    • BQ_VIEW_NAME: このシリーズのパート 2 で作成した BigQuery ビューの名前。
    • MODEL_NAME: AI Platform Prediction にデプロイされるモデルの名前。
    • VERSION_NAME: AI Platform Prediction にデプロイされるモデルのバージョン名。バージョンは vN という形式です(例: v1)。
  5. [設定] の残りのセルを実行して、環境の構成を完了します。

    1. GCP アカウントの認証
    2. ライブラリのインポート
    3. ローカル ワークスペースを作成する

ベースライン統計と参照スキーマを生成する

ノートブックの最初のセクションでタスクを実行すると、トレーニング データによりベースライン統計と参照スキーマが生成されます。データを CSV ファイルとしてダウンロードして、tfdv.generate_statistics_from_csv メソッドを使用してベースライン統計を計算し、それを baseline_stats 変数に格納します。コードは、tfdv.infer_schema メソッドを使用してトレーニング データの参照スキーマを推定し、それを reference_schema 変数に格納します。

次のコード スニペットに示すように、推定スキーマを変更できます。

baseline_stats = tfdv.generate_statistics_from_csv(
   data_location=TRAIN_DATA,
   stats_options=tfdv.StatsOptions(schema=reference_schema,
       sample_count=10000))

reference_schema = tfdv.infer_schema(baseline_stats)

# Set Soil_Type to be categorical
tfdv.set_domain(reference_schema, 'Soil_Type', schema_pb2.IntDomain(
   name='Soil_Type', is_categorical=True))

# Set Cover_Type to be categorical
tfdv.set_domain(reference_schema, 'Cover_Type', schema_pb2.IntDomain(
   name='Cover_Type', is_categorical=True))

# Set max and min values for Elevation
tfdv.set_domain(reference_schema,
   'Elevation',
   tfdv.utils.schema_util.schema_pb2.IntDomain(min=1000, max=5000))

# Allow no missing values
tfdv.get_feature(reference_schema,
   'Slope').presence.min_fraction = 1.0

# Set distribution skew detector for Wilderness_Area
tfdv.get_feature(reference_schema,
   'Wilderness_Area').skew_comparator.infinity_norm.threshold = 0.05

生成された参照スキーマは、tfdv.display_schema メソッドを使用して表示します。このメソッドを使用すると、次のようなリストが表示されます。

生成されたスキーマのリスト出力。

サービング データ スキューの検知

ノートブックの次のセクションでは、サービング データ スキューを検知するためのタスクを実行します。このプロセスは以下の手順で構成されます。

  1. リクエスト / レスポンスのデータ一式は、BigQuery の vw_covertype_classifier_logs_v1 ビューから読み込まれます。ビューには、解析された特徴量の値と、covertype_classifier_logs テーブルに記録される予測が表示されます。このテーブルには、先に AI Platform Prediction にデプロイされた covertype_classifier モデルの未加工のインスタンス リクエストと予測レスポンスが含まれています。
  2. ログに記録されたサービング データは、TFDV で使用するために CSV ファイルに保存されます。
  3. 次のコード スニペットに示すように、TFDV は tfdv.experimental_get_feature_value_slicer メソッドを使用して、サービング データのさまざまなスライスのために、CSV データファイルからサービングの統計を計算します。

    slice_fn = tfdv.experimental_get_feature_value_slicer(features={'time': None})
    
    serving_stats_list = tfdv.generate_statistics_from_csv(
    data_location=serving_data_file,
    stats_options=tfdv.StatsOptions(
        slice_functions=[slice_fn],
        schema=reference_schema))
    
  4. TFDV は、tfdv.validate_statistics メソッドを使用し、(reference_schema 変数内の)参照スキーマに対して各 serving_stats スライスを検証します。次のコード スニペットに示すように、このプロセスによって異常が生成されます。

    anomalies_list = []
    
    for slice_key in slice_keys[1:]:
      serving_stats = tfdv.get_slice_stats(serving_stats_list, slice_key)
      anomalies = tfdv.validate_statistics(
           serving_stats, schema=reference_schema,
           previous_statistics=baseline_stats)
      anomalies_list.append(anomalies)
    

TFDV は、スキーマと統計プロトコル バッファを比較して、異常をチェックします。TFDV が検知できる異常タイプの詳細については、TensorFlow データ検証異常リファレンスをご覧ください。スキーマと統計のフィールドを使用して、各異常のタイプと、各異常のタイプが検知された条件を検知できます。

検証出力の分析と可視化

ノートブックの 3 番目のセクションでは、異常を可視化します。このコードは、分布スキューをハイライト表示するために、tfdv.visualize_statistics メソッドを使用して、トレーニング データのベースライン統計に対する serving_stats スライスを可視化します。

次のスクリーンショットは、ElevationAspect の数値特徴量の分布の可視化の例を示したものです。

高度とアスペクトの異常を示すグラフ。

次のスクリーンショットは、Wildness_AreaCover_Type カテゴリ特徴量の可視化例を示したものです。カテゴリ特徴量の可視化では、Cover_Type はターゲットの特徴量であり、分布は予測スキューを示します。

荒野地域の可視化。

被覆タイプの可視化。

serving_stats スライスで生成された異常を検査するには、tfdv.display_anomalies メソッドを呼び出します。次の一覧は、検出された異常の例を示したものです。

「display_anomares」メソッドで検出された異常の一覧。

TFDV visualization API を使用して可視化することに加えて、Python のプロット ライブラリを使用して、ノートブックで統計を可視化することもできます。

次のプロットは、サービングの統計の数値特徴量の平均値がタイムスライス間でどのように変化するかと、ベースライン統計の平均値と比較してどのくらいずれているかを示したものです。

高度の平均値のグラフ。

アスペクトの平均値のグラフ。

Slope の平均値のグラフ。

次のプロットは、サービングの統計のカテゴリ特徴量の値の分布がタイムスライス間でどのように変化するかを示しています。

時間の経過に伴う特徴量の分布を示す棒グラフ。

クリーンアップ

このシリーズの残りも継続する予定の場合は、作成済みのリソースはそのままにしておいてください。継続する予定でない場合は、リソースを含むプロジェクトを削除するか、プロジェクトは残して個々のリソースを削除します。

プロジェクトの削除

  1. Cloud Console で [リソースの管理] ページに移動します。

    [リソースの管理] に移動

  2. プロジェクト リストで、削除するプロジェクトを選択し、[削除] をクリックします。
  3. ダイアログでプロジェクト ID を入力し、[シャットダウン] をクリックしてプロジェクトを削除します。

次のステップ