異常検出 (Snowflake Cortex ML ベースの関数)

注釈

異常検出は、Snowflakeのインテリジェントなフルマネージド AI および ML サービスであるSnowflake Cortexの一部です。この機能は、Snowflake Cortex ML ベースの関数スイートの一部です。

異常検出により、機械学習アルゴリズムを使用して、時系列データの外れ値を検出できます。外れ値(予想範囲から外れたデータポイント)は、データから得られる統計や、そのデータでトレーニングする機械学習モデルに非常に大きな影響を与える可能性があります。そのため、外れ値を見つけ、取り除くことは、結果の質を高めるのに役立ちます。

外れ値の検出は、明らかな原因がない場合に、プロセスの問題や逸脱の原因を突き止めるのにも役立ちます。例:

  • ログパイプラインに問題が発生し始めた時を判断する。

  • Snowflakeのコンピューティングコストが予想より高い日を識別する。

異常検出は単一系列データでも複数系列データでも機能します。複数系列データは、イベントの複数の独立したスレッドを表します。たとえば、複数の店舗の販売データがある場合は、各店舗の売上を店舗識別子に基づいて1つのモデルで別々にチェックすることができます。

データには次が含まれている必要があります。

  • タイムスタンプ列。一定の頻度(例えば、1時間毎、5分毎など)を指定する必要があります。

  • 各タイムスタンプで興味のある数量を表すターゲット値の列。

時系列データの外れ値を検出するには、Snowflake組み込みクラス ANOMALY_DETECTION を使用し、次のステップに従います。

  1. 異常検出オブジェクトを作成 し、トレーニングデータへの参照を渡します。

    このオブジェクトは、プロバイダーから提供された学習データにモデルを当てはめます。モデルはスキーマレベルのオブジェクトです。

  2. この異常検出モデルオブジェクトを使用して、 <name>!DETECT_ANOMALIES メソッドを呼び出し、分析するデータへの参照を渡して異常を検出します。

    このメソッドは、モデルを使用してデータ内の外れ値を識別します。

異常検出は 予測 と密接に関連しています。異常検出モデルは、異常をチェックするデータと同じ期間の予測を作成し、実際のデータと予測を比較して外れ値を特定します。

重要

法律上の注意点。 このSnowflake Cortex ML ベースの機能は、機械学習技術によって実現されています。機械学習技術と提供される結果は、不正確、不適切であったり、偏っていたりする可能性があります。自動パイプラインに組み込まれたものも含め、機械学習の出力に基づく決定には、モデルが生成したコンテンツが正確であることを保証するために、人間によるモニタリングとレビュープロセスが必要です。Snowflake Cortexの ML ベースの関数クエリは、他の SQL クエリと同様に扱われ、 メタデータ と見なされる可能性があります。

メタデータ。 Snowflake Cortex ML ベース関数を使用する場合、Snowflakeのログは メタデータフィールド に述べられている内容に加えて、 ML 関数によって返される一般的なエラーメッセージを記録します。これらのエラーログは、発生した問題のトラブルシューティングや、お客様により良いサービスを提供するための機能改善に役立ちます。

異常検出のアルゴリズムについて

異常検出アルゴリズムは、 勾配ブースティングマシン (GBM)を使用しています。 ARIMA モデルのように、非定常トレンドを持つデータをモデリングするために差分変換を使用し、モデル変数として過去のターゲットデータの自己回帰ラグを使用します。

さらに、このアルゴリズムは、過去のターゲットデータの移動平均を使用してトレンドの予測を支援し、タイムスタンプデータから周期的なカレンダー変数(曜日や週番号など)を自動的に生成します。

過去のターゲット値とタイムスタンプのデータだけでモデルを適合させることも、ターゲット値に影響を与えた可能性のある外生データ(変数)を含めることもできます。外生変数は、数値またはカテゴリ別の値であり、 NULL (外生変数の NULLs を含む行はドロップされません)の場合もあります。

このアルゴリズムは、カテゴリ別変数でトレーニングする際にone-hotエンコーディングに依存しないため、ディメンション数の多い(カーディナリティの高い)カテゴリデータを使用することができます。

モデルに外生変数が組み込まれている場合は、異常を検出する際に将来のタイムスタンプでそれらの変数の値を提供する必要があります。適切な外生変数には、気象情報(気温、降雨量)、企業固有の情報(これまでの、および計画されている企業の休日、広告キャンペーン、イベントスケジュール)、またはターゲット変数の予測に役立つと思われるその他の外部要因などがあります。

オプションで、別個のブール列を使用して、個別の履歴行に異常または異常なしのラベルを付けることができます。

予測区間 とは、データのある割合が該当する可能性のある上限値と下限値内の推定値の範囲を表します。たとえば、0.99という値は、データの99%が区間内に出現する可能性が高いことを意味します。異常検出モデルは、予測区間から外れたデータを異常として識別します。予測間隔を指定するか、デフォルトの0.99を使用します。この値は、1.0、0.9999に非常に近いか、あるいはさらに近い値に設定することをお勧めします。

重要

Snowflakeは異常検出アルゴリズムを改良することがあり、そのような改良は定期的なSnowflakeのリリースプロセスを通じてロールアウトされます。以前のバージョンの特徴量に戻すことはできませんが、以前のバージョンで作成したモデルは、引き続きそのバージョンを異常検出に使用します。

制限事項

  • 異常検出アルゴリズムを選択または調整することはできません。特に、アルゴリズムはトレンド、季節性、または季節振幅を上書きするパラメーターを提供しません。パラメーターはデータから推測されます。

  • 主な異常検出アルゴリズムの最小行数は、時系列ごとに12です。観測データが2と11の間の時系列では、異常検出はすべての予測値が最後に観測されたターゲット値に等しい「ナイーブ」な結果を生成します。ラベル付き異常検出のケースでは、使用される観測データの数は、ラベル列がfalseである行の数です。

  • データの最小許容粒度は1秒です。(タイムスタンプの間隔は1秒以内でなければなりません。)

  • 季節要因の最小粒度は1分です。(この関数は、より小さな時間差で周期的なパターンを検出することはできません。)

  • データのタイムスタンプは、一定の時間間隔を表す必要があります。入力データが不規則な場合は、モデルのトレーニング時にタイムスタンプ列の DATE_TRUNC または TIME_SLICE を試行します。

  • 自己回帰的な特徴量の「シーズンの長さ」は、入力頻度に関連付けられています(1時間ごとのデータでは24、1日ごとのデータでは7など)。

  • 異常検出モデルは、一度トレーニングすると不変です。新しいデータで既存のモデルを更新することはできず、まったく新しいモデルをトレーニングする必要があります。モデルはバージョニングをサポートしていません。一般的に、モデルが変化する傾向を常に把握できるように、新しいデータを受け取る頻度に応じて、週に1回、月に1回など、定期的にモデルを再トレーニングすることをお勧めします。

  • この特徴量は、トレーニングデータに対するテストデータの異常のみを検出します。トレーニングデータの異常を検出することはできません。トレーニングデータはモデルの元となるものであるため、定義上、それ自体に対する外れ値はありません。学習データが実際の外れ値のない典型的な期間をカバーしていることを確認するか、または既知の外れ値がブール列でラベル付けされていることを確認します。

  • モデルをクローンしたり、ロールやアカウント間でモデルを共有したりすることはできません。スキーマやデータベースをクローンする場合、モデルオブジェクトはスキップされます。

  • ANOMALY_DETECTION クラスのインスタンスを 複製 することはできません。

異常検出の準備

異常検出を使用する前に、以下が必要です。

また、 SNOWFLAKE.ML を含めるように 検索パスを変更 する場合もあります。

仮想ウェアハウスの選択

Snowflake 仮想ウェアハウス は、この特徴量のための機械学習モデルをトレーニングし、使用するためのコンピューティングリソースを提供します。このセクションでは、トレーニングステップ(プロセスの中で最も時間とメモリを消費する部分)に焦点を当て、この目的に最適なウェアハウスのサイズと型を選択するための一般的なガイダンスを提供します。

単一系列データのトレーニング

単一系列データで学習したモデルの場合、トレーニングデータのサイズに基づいてウェアハウスタイプを選択する必要があります。標準ウェアハウスは、 Snowparkのメモリ制限 が低く、行数が少ないトレーニングジョブや外生的な特徴に適しています。トレーニングデータに外生的な特徴が含まれていない場合、データセットが5万行以下であれば、標準ウェアハウスでトレーニングできます。トレーニングデータに5個以上の外生的な特徴量を使用している場合、最大行数は少なくなります。それ以外の場合は、大規模なトレーニングジョブに対して Snowparkに最適化されたウェアハウス を使用することをSnowflakeは提案します。

一般的に、単一系列データの場合、ウェアハウスサイズが大きくなっても、トレーニング時間が短縮されたり、メモリ制限が高くなったりすることはありません。大まかな経験則として、トレーニング時間は時系列の行数に比例します。たとえば、 XS 標準ウェアハウスでは、100,000行のデータセットのトレーニングに約30秒かかります。1,000,000行のデータセットでのトレーニングには、約140秒かかります。

最高のパフォーマンスを得るために、モデルのトレーニングには他のワークロードが同時に発生しない専用ウェアハウスを使用することをSnowflakeは推奨します。

複数系列データのトレーニング

単一系列のデータと同様に、最大の時系列の行数に基づいてウェアハウスタイプを選択します。最大の時系列が500万行を超える場合、トレーニングジョブは標準ウェアハウスのメモリ制限を超える可能性があります。

単一系列のデータとは異なり、複数系列のデータは、ウェアハウスサイズが大きくなるとかなり高速にトレーニングされます。選択する際は、以下のデータポイントを手引きとしてください。

ウェアハウスのタイプとサイズ

時系列の数

時系列ごとの行数

トレーニング時間(秒)

標準 XS

1

100,000

38秒間

標準 XS

10

100,000

112秒間

標準 XS

100

100,000

594秒間

標準 XL

10

100,000

34秒間

標準 XL

100

100,000

114秒間

標準 XL

1000

100,000

572秒間

Snowpark用に最適化された XL

10

100,000

74秒間

Snowpark用に最適化された XL

100

100,000

215秒間

Snowpark用に最適化された XL

1000

100,000

1429秒間

異常の検出

推論ステップでは、ウェアハウスのサイズに関係なく、入力データセットの500行の処理に約1秒かかります。

異常検出オブジェクトの作成権限の付与

異常検出モデルをトレーニングすると、スキーマレベルのオブジェクトが生成されます。したがって、モデルの作成に使用するロールには、モデルが作成されるスキーマ上で CREATE SNOWFLAKE.ML.ANOMALY_DETECTION 権限があり、そこにモデルを格納できるようにする必要があります。この権限は CREATE TABLE や CREATE VIEW のような他のスキーマ権限と類似しています。

Snowflakeは、 analyst という名前のロールを作成し、異常検出を実行する必要のある人が使用できるようにすることをお勧めします。

以下の例では、 admin ロールがスキーマ admin_db.admin_schema の所有者です。 analyst ロールにより、このスキーマでモデルを作成する必要があります。

USE ROLE admin;
GRANT USAGE ON admin_db TO ROLE analyst;
GRANT USAGE ON admin_schema TO ROLE analyst;
GRANT CREATE SNOWFLAKE.ML.ANOMALY_DETECTION ON SCHEMA admin_db.admin_schema TO ROLE analyst;
Copy

このスキーマを使用するには、ユーザーは analyst ロールを引き受けます。

USE ROLE analyst;
USE SCHEMA admin_db.admin_schema;
Copy

analyst ロールがデータベース analyst_db の CREATE SCHEMA 権限を持っている場合、そのロールは新しいスキーマ analyst_db.analyst_schema を作成し、そのスキーマに異常検出モデルを作成することができます。

USE ROLE analyst;
CREATE SCHEMA analyst_db.analyst_schema;
USE SCHEMA analyst_db.analyst_schema;
Copy

スキーマに対するロールのモデル作成権限を取り消すには、 REVOKE <権限> を使用します。

REVOKE CREATE SNOWFLAKE.ML.ANOMALY_DETECTION ON SCHEMA admin_db.admin_schema FROM ROLE analyst;
Copy

例に対するデータの設定

次のセクションの例では、異なる店舗にある商品の日次売上と、毎日の天候データ(湿度と気温)を含むサンプルデータセットを使用します。データセットには、その日が休日かどうかを示す列も含まれています。

  1. 以下のステートメントを実行して、モデルの学習データを格納する historical_sales_data という名前のテーブルを作成します。

CREATE OR REPLACE TABLE historical_sales_data (
  store_id NUMBER, item VARCHAR, date TIMESTAMP_NTZ, sales FLOAT, label BOOLEAN,
  temperature NUMBER, humidity NUMBER, holiday VARCHAR);

INSERT INTO historical_sales_data VALUES
  (1, 'jacket', to_timestamp_ntz('2020-01-01'), 2.0, false, 50, 0.3, 'new year'),
  (1, 'jacket', to_timestamp_ntz('2020-01-02'), 3.0, false, 52, 0.3, null),
  (1, 'jacket', to_timestamp_ntz('2020-01-03'), 5.0, false, 54, 0.2, null),
  (1, 'jacket', to_timestamp_ntz('2020-01-04'), 30.0, true, 54, 0.3, null),
  (1, 'jacket', to_timestamp_ntz('2020-01-05'), 8.0, false, 55, 0.2, null),
  (1, 'jacket', to_timestamp_ntz('2020-01-06'), 6.0, false, 55, 0.2, null),
  (1, 'jacket', to_timestamp_ntz('2020-01-07'), 4.6, false, 55, 0.2, null),
  (1, 'jacket', to_timestamp_ntz('2020-01-08'), 2.7, false, 55, 0.2, null),
  (1, 'jacket', to_timestamp_ntz('2020-01-09'), 8.6, false, 55, 0.2, null),
  (1, 'jacket', to_timestamp_ntz('2020-01-10'), 9.2, false, 55, 0.2, null),
  (1, 'jacket', to_timestamp_ntz('2020-01-11'), 4.6, false, 55, 0.2, null),
  (1, 'jacket', to_timestamp_ntz('2020-01-12'), 7.0, false, 55, 0.2, null),
  (1, 'jacket', to_timestamp_ntz('2020-01-13'), 3.6, false, 55, 0.2, null),
  (1, 'jacket', to_timestamp_ntz('2020-01-14'), 8.0, false, 55, 0.2, null),
  (2, 'umbrella', to_timestamp_ntz('2020-01-01'), 3.4, false, 50, 0.3, 'new year'),
  (2, 'umbrella', to_timestamp_ntz('2020-01-02'), 5.0, false, 52, 0.3, null),
  (2, 'umbrella', to_timestamp_ntz('2020-01-03'), 4.0, false, 54, 0.2, null),
  (2, 'umbrella', to_timestamp_ntz('2020-01-04'), 5.4, false, 54, 0.3, null),
  (2, 'umbrella', to_timestamp_ntz('2020-01-05'), 3.7, false, 55, 0.2, null),
  (2, 'umbrella', to_timestamp_ntz('2020-01-06'), 3.2, false, 55, 0.2, null),
  (2, 'umbrella', to_timestamp_ntz('2020-01-07'), 3.2, false, 55, 0.2, null),
  (2, 'umbrella', to_timestamp_ntz('2020-01-08'), 5.6, false, 55, 0.2, null),
  (2, 'umbrella', to_timestamp_ntz('2020-01-09'), 7.3, false, 55, 0.2, null),
  (2, 'umbrella', to_timestamp_ntz('2020-01-10'), 8.2, false, 55, 0.2, null),
  (2, 'umbrella', to_timestamp_ntz('2020-01-11'), 3.7, false, 55, 0.2, null),
  (2, 'umbrella', to_timestamp_ntz('2020-01-12'), 5.7, false, 55, 0.2, null),
  (2, 'umbrella', to_timestamp_ntz('2020-01-13'), 6.3, false, 55, 0.2, null),
  (2, 'umbrella', to_timestamp_ntz('2020-01-14'), 2.9, false, 55, 0.2, null);
Copy
  1. 以下のステートメントを実行して、分析するデータを含む new_sales_data という名前のテーブルを作成します。

CREATE OR REPLACE TABLE new_sales_data (
  store_id NUMBER, item VARCHAR, date TIMESTAMP_NTZ, sales FLOAT,
  temperature NUMBER, humidity NUMBER, holiday VARCHAR);

INSERT INTO new_sales_data VALUES
  (1, 'jacket', to_timestamp_ntz('2020-01-16'), 6.0, 52, 0.3, null),
  (1, 'jacket', to_timestamp_ntz('2020-01-17'), 20.0, 53, 0.3, null),
  (2, 'umbrella', to_timestamp_ntz('2020-01-16'), 3.0, 52, 0.3, null),
  (2, 'umbrella', to_timestamp_ntz('2020-01-17'), 70.0, 53, 0.3, null);
Copy

モデルのトレーニング、使用、表示、削除、更新

CREATE SNOWFLAKE.ML.ANOMALY_DETECTION を使用してモデルを作成し、トレーニングします。モデルは提供されたデータセットでトレーニングされます。

CREATE SNOWFLAKE.ML.ANOMALY_DETECTION mydetector(...);
Copy

SNOWFLAKE.ML.ANOMALY_DETECTION コンストラクターの包括的な詳細については、 ANOMALY_DETECTION をご参照ください。モデルの作成例については、 異常の検出 をご参照ください。

注釈

SNOWFLAKE.ML.ANOMALY_DETECTION は制限された権限で実行されるため、デフォルトではご使用のデータにアクセスできません。そのため、テーブルとビューを 参照 として渡す必要があります。参照は、呼び出し元の権限も一緒に渡します。テーブルやビューへの参照ではなく、 クエリ参照 を提供することもできます。

異常を検出するには、モデルの <name>!DETECT_ANOMALIES メソッドを呼び出します。

CALL mydetectorl!DETECT_ANOMALIES(...)
Copy

モデルのリストを表示するには、 SHOW SNOWFLAKE.ML.ANOMALY_DETECTION コマンドを使用します。

SHOW SNOWFLAKE.ML.ANOMALY_DETECTION;
Copy

モデルを削除するには、 DROP SNOWFLAKE.ML.ANOMALY_DETECTION コマンドを使用します。

DROP SNOWFLAKE.ML.ANOMALY_DETECTION <name>;
Copy

モデルを更新するには、モデルを削除して新しいモデルをトレーニングします。モデルは不変であり、導入状態で更新することはできません。

異常の検出

次のセクションでは、異常検出を使用して外れ値を検出する方法を示します。これらのセクションでは、単一時系列、複数時系列、外生変数の有無、ユーザー定義の予測区間、および教師あり(ラベル付き)アプローチによる異常の検出例を示します。

単一時系列の異常検出(教師なし)

データの異常を検出するには、

  1. 過去のデータを使用して異常検出モデルをトレーニングします。

  2. トレーニング済みの異常検出モデルを使用して、過去のデータまたは予測データの異常を検出します。テストデータのタイムスタンプは、トレーニングデータのタイムスタンプに時系列で追随している必要があります。モデルをトレーニングするには少なくとも2個のデータポイントが必要で、非ネイティブな結果には少なくとも12個のデータポイント、非線形結果を得るには少なくとも60個のデータポイントが必要です。

モデルの作成時および使用時に使用するパラメーターについては、 ANOMALY_DETECTION をご参照ください。

異常検出モデルのトレーニング

異常検知モデルオブジェクトを作成するには、 CREATE SNOWFLAKE.ML.ANOMALY_DETECTION コマンドを実行します。

たとえば、 store_id が1の店舗でジャケットの売上を分析するとします。

  1. 異常検出モデルをトレーニングするためのデータを返すビューを作成するか、クエリを設計します。

    この例では、 CREATE VIEW コマンドを実行して、日付と売上情報を含む view_with_training_data という名前のビューを作成します。

    CREATE OR REPLACE VIEW view_with_training_data
      AS SELECT date, sales FROM historical_sales_data
        WHERE store_id=1 AND item='jacket';
    
    Copy
  2. 異常検出オブジェクトを作成し、そのモデルをそのビュー内のデータでトレーニングします。

    この例では、 CREATE SNOWFLAKE.ML.ANOMALY_DETECTION コマンドを実行して、 basic_model という名前の異常検出オブジェクトを作成します。以下の引数を渡します。

    CREATE OR REPLACE SNOWFLAKE.ML.ANOMALY_DETECTION basic_model(
      INPUT_DATA => SYSTEM$REFERENCE('VIEW', 'view_with_training_data'),
      TIMESTAMP_COLNAME => 'date',
      TARGET_COLNAME => 'sales',
      LABEL_COLNAME => '');
    
    Copy

    ラベル列の目的は、どの行が既知の異常であるかをモデルに伝えることです。この例では教師なしのトレーニングを使用しているため、ラベル列を使用する必要はありません。ラベル列の名前として空の文字列を渡します。

    ちなみに

    input_data引数に対するビューを作成しない場合は、インラインビューとして機能する SELECT ステートメントを使用できます。 SYSTEM$REFERENCE を呼び出してテーブルビューへの参照を作成する代わりに、 SYSTEM$QUERY_REFERENCE を呼び出して SELECT ステートメントへのクエリ参照を作成します。一重引用符やその他の特殊文字はバックスラッシュでエスケープします。

    例:

    CREATE OR REPLACE SNOWFLAKE.ML.ANOMALY_DETECTION basic_model(
      INPUT_DATA =>
        SYSTEM$QUERY_REFERENCE(
          'SELECT date, sales FROM historical_sales_data WHERE store_id=1 AND item=\'jacket\''
        ),
      TIMESTAMP_COLNAME => 'date',
      TARGET_COLNAME => 'sales',
      LABEL_COLNAME => '');
    
    Copy

コマンドの実行に成功すると、異常検出インスタンスが正常に作成されたことを示すメッセージが表示されます。

+--------------------------------------------+
|                 status                     |
+--------------------------------------------+
| Instance basic_model successfully created. |
+--------------------------------------------+

異常を検出するための異常検出モデルの使用

異常検知オブジェクトを作成すると、モデルがトレーニングされ、スキーマに格納されます。異常検出オブジェクトを使用して異常を検知するには、オブジェクトの <name>!DETECT_ANOMALIES メソッドを呼び出します。例:

  1. 分析用のデータを返すビューを作成するか、クエリを設計します。

    この例では、 CREATE VIEW コマンドを実行して、日付と売上情報を含む view_with_data_to_analyze という名前のビューを作成します。

    CREATE OR REPLACE VIEW view_with_data_to_analyze
      AS SELECT date, sales FROM new_sales_data
        WHERE store_id=1 and item='jacket';
    
    Copy
  2. 異常検出モデルのオブジェクト(この例では、 先に作成した basic_model)を使用して、 <name>!DETECT_ANOMALIES メソッドを呼び出します。

    CALL basic_model!DETECT_ANOMALIES(
      INPUT_DATA => SYSTEM$REFERENCE('VIEW', 'view_with_data_to_analyze'),
      TIMESTAMP_COLNAME =>'date',
      TARGET_COLNAME => 'sales'
    );
    
    Copy

    このメソッドは、現在ビュー view_with_data_to_analyze にあるデータの行を含むテーブルを検出器の予測値と合わせて返します。このテーブルの列の説明については、 CREATE SNOWFLAKE.ML.ANOMALY_DETECTION をご参照ください。

出力

結果は読みやすくするために丸めてあります。

+-------------------------+----+----------+--------------+--------------+------------+--------------+--------------+
| TS                      |  Y | FORECAST |  LOWER_BOUND |  UPPER_BOUND | IS_ANOMALY |   PERCENTILE |     DISTANCE |
|-------------------------+----+----------+--------------+--------------+------------+--------------+--------------|
| 2020-01-16 00:00:00.000 |  6 |      4.6 | -7.185885251 | 16.385885251 | False      | 0.6201873452 | 0.3059728606 |
| 2020-01-17 00:00:00.000 | 20 |      9   | -2.785885251 | 20.785885251 | False      | 0.9918932208 | 2.404072476  |
+-------------------------+----+----------+--------------+--------------+------------+--------------+--------------|

結果を直接テーブルに保存するには、以下のコードを使用します。

BEGIN
  CALL basic_model!DETECT_ANOMALIES(
     INPUT_DATA => SYSTEM$REFERENCE('VIEW', 'view_with_data_to_analyze'),
     TIMESTAMP_COLNAME =>'date',
     TARGET_COLNAME => 'sales'
  );
  LET x := SQLID;
  CREATE TABLE my_anomalies AS SELECT * FROM TABLE(RESULT_SCAN(:x));
END;

SELECT * FROM my_anomalies;
Copy

上記のコードでは RESULT_SCAN を使用していますが、複数のプロセスが同時に 実行されている場合でも、競合状態に陥ることはありません。上記のモデルコールの結果は、 my_anomalies テーブルに決定論的に格納されます。

ラベル付きデータによる異常検出モデルのトレーニング

先ほどの例では、モデルの結果が不正確に見えます。それは次の理由によると考えられます。

  • 異常検出モデルは、わずかな入力データでトレーニングされた。

  • 2020年1月3日に、多数のジャケット(30着)が販売された。このため予測値が上方に歪み、予測区間が拡大しました。

異常検出モデルの精度を向上させるには、より多くのトレーニングデータを含めるか、トレーニングデータにラベルを付ける(教師ありトレーニング)ことができます。ラベル付きトレーニングデータには、各行に既知の異常があるかどうかを示すブール列が追加されています。ラベル付けは、異常検出モデルがトレーニングデータ内の既知の異常に過剰適合することを回避するのに役立ちます。

ラベル付きデータをトレーニングデータに含めるには、 CREATE SNOWFLAKE.ML.ANOMALY_DETECTION コマンドの LABEL_COLNAME コンストラクター引数にラベルを含む列を指定します。例:

  1. ラベルとトレーニングデータを返すビューを作成するか、クエリを設計します。

    この例では、 CREATE VIEW コマンドを実行して、 label という名前の列にあるラベルを含む view_with_labeled_data という名前のビューを作成します。

    CREATE OR REPLACE VIEW view_with_labeled_data_for_training
      AS SELECT date, sales, label FROM historical_sales_data
        WHERE store_id=1 and item='jacket';
    
    Copy
  2. 異常検出モデル用のオブジェクトを作成し、そのビューのデータでモデルをトレーニングします。

    この例では、 CREATE SNOWFLAKE.ML.ANOMALY_DETECTION コマンドを実行して、 model_trained_with_labeled_data という名前の異常検出オブジェクトを作成します。次のステートメントは、異常検出オブジェクトを作成します。

    CREATE OR REPLACE SNOWFLAKE.ML.ANOMALY_DETECTION model_trained_with_labeled_data(
      INPUT_DATA => SYSTEM$REFERENCE('VIEW', 'view_with_labeled_data_for_training'),
      TIMESTAMP_COLNAME => 'date',
      TARGET_COLNAME => 'sales',
      LABEL_COLNAME => 'label'
    );
    
    Copy
  3. この新しい異常検出モデルを使用し、 単一時系列の異常検出(教師なし) で使用したのと同じ引数を渡して、 <name>!DETECT_ANOMALIES メソッドを呼び出します。

    CALL model_trained_with_labeled_data!DETECT_ANOMALIES(
      INPUT_DATA => SYSTEM$REFERENCE('VIEW', 'view_with_data_to_analyze'),
      TIMESTAMP_COLNAME =>'date',
      TARGET_COLNAME => 'sales'
    );
    
    Copy

    このメソッドは、現在ビュー view_with_data_to_analyze にあるデータの行を含むテーブルを検出器の予測値と合わせて返します。このテーブルの列の説明については、 <name>!DETECT_ANOMALIES をご参照ください。

出力

結果は読みやすくするために丸めてあります。

+-------------------------+----+----------+---------------+--------------+------------+--------------+------------+
| TS                      |  Y | FORECAST |   LOWER_BOUND |  UPPER_BOUND | IS_ANOMALY |   PERCENTILE |   DISTANCE |
|-------------------------+----+----------+---------------+--------------+------------+--------------+------------|
| 2020-01-16 00:00:00.000 |  6 |        6 |  0.82         | 11.18        | False      | 0.5          | 0          |
| 2020-01-17 00:00:00.000 | 20 |        6 | -0.39         | 12.33        | True       | 0.99         | 5.70       |
+-------------------------+----+----------+---------------+--------------+------------+--------------+------------+

異常検出向け予測間隔の指定

さまざまな感度で異常を検出できます。異常として分類するオブザベーションの割合を指定するには、 <name>!DETECT_ANOMALIES の構成設定を含む OBJECT を作成し、 prediction_interval キーに、異常としてマークするオブザベーションの割合を設定します。

このオブジェクトを構築するには、 オブジェクト定数 または OBJECT_CONSTRUCT 関数を使用します。

そして、 <name>!DETECT_ANOMALIES メソッドを呼び出す際に、 CONFIG_OBJECT 引数としてこのオブジェクトを渡します。

デフォルトでは、prediction_intervalキーに関連する値は0.99に設定されており、これはデータのおよそ1%が異常としてマークされることを意味します。0~1の間で指定できます。

  • より少ないオブザベーションを異常としてマークするには、 prediction_interval に高い値を指定します。

  • より多くのオブザベーションを異常としてマークするには、 prediction_interval の値を小さくします。

次の例では、 prediction_interval を0.995に設定することで、異常検出をより厳密に設定します。この例では、ラベル付きデータ(ラベル付きデータによる異常検出モデルのトレーニング で設定)でトレーニングしたモデルを、分析対象のデータ(単一時系列の異常検出(教師なし) で設定)を含むビューで使用しています。

CALL model_trained_with_labeled_data!DETECT_ANOMALIES(
  INPUT_DATA => SYSTEM$REFERENCE('VIEW', 'view_with_data_to_analyze'),
  TIMESTAMP_COLNAME => 'date',
  TARGET_COLNAME => 'sales',
  CONFIG_OBJECT => {'prediction_interval':0.995}
);
Copy

このステートメントは、現在ビュー view_with_data_to_analyze にあるデータの行を含むテーブルを生成します。各行には、検出器の予測値を示す列があります。このモデルの結果は、ラベルのない例よりも正確であることがわかります。

出力

結果は読みやすくするために丸めてあります。

+-------------------------+----+----------+---------------+--------------+------------+--------------+------------+
| TS                      |  Y | FORECAST |   LOWER_BOUND |  UPPER_BOUND | IS_ANOMALY |   PERCENTILE |   DISTANCE |
|-------------------------+----+----------+---------------+--------------+------------+--------------+------------|
| 2020-01-16 00:00:00.000 |  6 |        6 |  0.36         | 11.64        | False      | 0.5          | 0          |
| 2020-01-17 00:00:00.000 | 20 |        6 | -0.90         | 12.90        | True       | 0.99         | 5.70       |
+-------------------------+----+----------+---------------+--------------+------------+--------------+------------+

分析向け追加列の含め

これらの列が真の異常の識別を向上させるのに役立つ場合は、トレーニングおよび分析用のデータに追加の列(例: temperatureweatheris_black_friday)を含めることができます。

分析に新しい列を含めるには、

  1. トレーニングデータに対して、新しい列を含むビューまたはクエリを作成し、そのビューまたはクエリへの参照を渡して新しい異常検出オブジェクトを作成します。

  2. 分析するデータについては、新しい列を含むビューを作成するかクエリを作成し、そのビューまたはクエリへの参照を <name>!DETECT_ANOMALIES メソッドに渡します。

異常検出モデルは、追加列を自動的に検出して使用します。

注釈

CREATE SNOWFLAKE.ML.ANOMALY_DETECTION コマンドを実行するときと、 <name>!DETECT_ANOMALIES メソッドを呼び出すときに、同じ追加列のセットをビューまたはクエリに提供する必要があります。コマンドに渡されたトレーニングデータの列と、関数に渡された分析用データの列が不一致の場合は、エラーが発生します。

たとえば、 temperaturehumidityholiday の列を追加するとします。

  1. これらの列を追加したトレーニングデータを返すビューを作成するかクエリを設計します。

    この例では、 CREATE VIEW コマンドを実行して、 view_with_training_data_extra_columns という名前のビューを作成します。

    CREATE OR REPLACE VIEW view_with_training_data_extra_columns
      AS SELECT date, sales, label, temperature, humidity, holiday
        FROM historical_sales_data
        WHERE store_id=1 AND item='jacket';
    
    Copy
  2. 異常検出モデル用のオブジェクトを作成し、そのビューのデータでモデルをトレーニングします。

    この例では、 CREATE SNOWFLAKE.ML.ANOMALY_DETECTION コマンドを実行して、 model_with_additional_columns という名前の異常検出オブジェクトを作成し、新しいビューへの参照を渡します。

    CREATE OR REPLACE SNOWFLAKE.ML.ANOMALY_DETECTION model_with_additional_columns(
      INPUT_DATA => SYSTEM$REFERENCE('VIEW', 'view_with_training_data_extra_columns'),
      TIMESTAMP_COLNAME => 'date',
      TARGET_COLNAME => 'sales',
      LABEL_COLNAME => 'label'
    );
    
    Copy
  3. これらの追加列を使用して分析するデータを返すビューを作成するかクエリを設計します。

    この例では、 CREATE VIEW コマンドを実行して、 view_with_data_for_analysis_extra_columns という名前のビューを作成します。

    CREATE OR REPLACE VIEW view_with_data_for_analysis_extra_columns
      AS SELECT date, sales, temperature, humidity, holiday
        FROM new_sales_data
        WHERE store_id=1 AND item='jacket';
    
    Copy
  4. この新しい異常検出オブジェクトを使用して、 <name>!DETECT_ANOMALIES メソッドを呼び出し、新しいビューを渡します。

    CALL model_with_additional_columns!DETECT_ANOMALIES(
      INPUT_DATA => SYSTEM$REFERENCE('VIEW', 'view_with_data_for_analysis_extra_columns'),
      TIMESTAMP_COLNAME => 'date',
      TARGET_COLNAME => 'sales',
      CONFIG_OBJECT => {'prediction_interval':0.93}
    );
    
    Copy

    このステートメントは、現在ビュー view_with_data_for_analysis_extra_columns にあるデータの行を含むテーブルを検出器の予測値と合わせて作成します。出力の形式は、先に実行したコマンドで表示された出力の形式と同じです。

出力

結果は読みやすくするために丸めてあります。

+-------------------------+----+----------+-------------+--------------+------------+--------------+------------+
| TS                      |  Y | FORECAST | LOWER_BOUND |  UPPER_BOUND | IS_ANOMALY |   PERCENTILE |   DISTANCE |
|-------------------------+----+----------+-------------+--------------+------------+--------------+------------|
| 2020-01-16 00:00:00.000 |  6 |        6 | 2.34        |  9.64        | False      | 0.5          | 0          |
| 2020-01-17 00:00:00.000 | 20 |        6 | 1.56        | 10.451       | True       | 0.99         | 5.70       |
+-------------------------+----+----------+-------------+--------------+------------+--------------+------------+

複数系列における異常の検出

前のセクションでは、単一系列の異常を検出する例を提供しました。これらの例では、1つの店舗(店舗 ID 1)で1つの種類のアイテム(ジャケット)の販売が異常であるとしてフラグが立てられました。同時に複数系列(例: 複数の商品と店舗の組み合わせ)の異常を検出するには、

  1. トレーニングデータについて、系列を識別する列を含むビューを作成するかクエリを設計し、新しい異常検出オブジェクトを作成して、そのビューまたはクエリへの参照を渡して、 SERIES_COLNAME 引数のために系列の列名を指定します。

  2. 分析するデータのために、系列を識別する列を含むビューを作成するかクエリを設計します。 <name>!DETECT_ANOMALIES メソッドを呼び出し、そのビューまたはクエリへの参照を渡して、 SERIES_COLNAME 引数のために系列の列名を指定します。

たとえば、 store_iditem の列の組み合わせを使用して系列を識別するとします。

  1. 系列のために列のあるトレーニングデータを返すビューを作成するかクエリを設計します。

    この例では、 CREATE VIEW コマンドを実行して、 view_with_training_data_multiple_series という名前のビューを作成します。このビューには、 store_item という名前の列があり、この列は、 ID と商品の組み合わせとして系列を識別します。

    CREATE OR REPLACE VIEW view_with_training_data_multiple_series
      AS SELECT
        [store_id, item] AS store_item,
        date,
        sales,
        label,
        temperature,
        humidity,
        holiday
      FROM historical_sales_data;
    
    Copy
  2. 異常検出用のオブジェクトを作成し、そのビューのデータでモデルをトレーニングします。

    この例では、 CREATE SNOWFLAKE.ML.ANOMALY_DETECTION コマンドを実行して、 model_for_multiple_series という名前の異常検出オブジェクトを作成し、新しいビューへの参照を渡して、 store_item 引数の SERIES_COLNAME を指定します。

    CREATE OR REPLACE SNOWFLAKE.ML.ANOMALY_DETECTION model_for_multiple_series(
      INPUT_DATA => SYSTEM$REFERENCE('VIEW', 'view_with_training_data_multiple_series'),
      SERIES_COLNAME => 'store_item',
      TIMESTAMP_COLNAME => 'date',
      TARGET_COLNAME => 'sales',
      LABEL_COLNAME => 'label'
    );
    
    Copy
  3. 系列の列で分析するデータを返すビューを作成するかクエリを設計します。

    この例では、 CREATE VIEW コマンドを実行して、系列の store_item という名前の列を含む view_with_data_for_analysis_multiple_series という名前のビューを作成します。

    CREATE OR REPLACE VIEW view_with_data_for_analysis_multiple_series
      AS SELECT
        [store_id, item] AS store_item,
        date,
        sales,
        temperature,
        humidity,
        holiday
      FROM new_sales_data;
    
    Copy
  4. この新しい異常検出オブジェクトを使用して、 <name>!DETECT_ANOMALIES メソッドを呼び出し、新しいビューを渡して、 SERIES_COLNAME 引数に store_item を指定します。

    CALL model_for_multiple_series!DETECT_ANOMALIES(
      INPUT_DATA => SYSTEM$REFERENCE('VIEW', 'view_with_data_for_analysis_multiple_series'),
      SERIES_COLNAME => 'store_item',
      TIMESTAMP_COLNAME => 'date',
      TARGET_COLNAME => 'sales',
      CONFIG_OBJECT => {'prediction_interval':0.995}
    );
    
    Copy

    このステートメントは、現在ビュー view_with_data_for_analysis_multiple_series にあるデータの行を含むテーブルを検出器の予測値と合わせて作成します。出力には系列を識別する列が含まれます。

出力

結果は読みやすくするために丸めてあります。

+--------------+-------------------------+----+----------+---------------+--------------+------------+---------------+--------------+
| SERIES       | TS                      |  Y | FORECAST |   LOWER_BOUND |  UPPER_BOUND | IS_ANOMALY |    PERCENTILE |     DISTANCE |
|--------------+-------------------------+----+----------+---------------+--------------+------------+---------------+--------------|
| [            | 2020-01-16 00:00:00.000 |  3 |      6.3 |  2.07         | 10.53        | False      | 0.01          | -2.19         |
|   2,         |                         |    |          |               |              |            |               |              |
|   "umbrella" |                         |    |          |               |              |            |               |              |
| ]            |                         |    |          |               |              |            |               |              |
| [            | 2020-01-17 00:00:00.000 | 70 |      2.9 | -1.33         |  7.13        | True       | 1             | 44.54         |
|   2,         |                         |    |          |               |              |            |               |              |
|   "umbrella" |                         |    |          |               |              |            |               |              |
| ]            |                         |    |          |               |              |            |               |              |
| [            | 2020-01-16 00:00:00.000 |  6 |      6   |  0.36         | 11.64        | False      | 0.5           |  0           |
|   1,         |                         |    |          |               |              |            |               |              |
|   "jacket"   |                         |    |          |               |              |            |               |              |
| ]            |                         |    |          |               |              |            |               |              |
| [            | 2020-01-17 00:00:00.000 | 20 |      6   | -0.90         | 12.90        | True       | 0.99          |  5.70         |
|   1,         |                         |    |          |               |              |            |               |              |
|   "jacket"   |                         |    |          |               |              |            |               |              |
| ]            |                         |    |          |               |              |            |               |              |
+--------------+-------------------------+----+----------+---------------+--------------+------------+---------------+--------------+

異常の視覚化と結果の解釈

Snowsight を使用して、異常検出の結果を確認し、視覚化します。 Snowsight では、 <name>!DETECT_ANOMALIES メソッドを呼び出すと、結果がワークシートの下のテーブルに表示されます。

Results from DETECT_ANOMALIES method displayed in a table

結果を視覚化するには、 Snowsight のチャート機能を使用することができます。

  1. <name>!DETECT_ANOMALIES メソッドを呼び出した後、クエリの結果テーブルで Charts を選択します。

  2. チャート右側の Data で、
    1. Y 列を選択し、 AggregationNone を選択します。

    2. TS 列を選択し、 BucketingNone を選択します。

  3. LOWER_BOUNDUPPER_BOUND 列を追加し、 AggregationNone を選択します。

  4. 初期の視覚化を表示するには、 Chart を選択します。

    Results from DETECT_ANOMALIES method displayed in a chart
  5. ページの右側で Add Column を選択し、視覚化する列を選択します。

    • LOWER_BOUND

    • UPPER_BOUND

    • IS_ANOMALY

    結果:

    Anomaly displayed in a chart
  6. 高いスパイクにカーソルを合わせると、Yが上限の外側にあり、 IS_ANOMALY のフィールドに1がタグ付けされていることがわかります。

ちなみに

結果をよりよく理解するには、 Contribution Explorer をお試しください。

Snowflakeタスクおよびアラートによる異常検出の自動化

モデルの再トレーニングとデータ異常のモニタリング両方のために、Snowflakeタスクまたはアラート内で異常検出関数を使用して、自動化された異常検出パイプラインを作成できます。

Snowflakeタスクを使用した反復トレーニング

Snowflakeタスク を使用して、最新のデータを反映するようにモデルを更新できます。

異常検出オブジェクトを1時間ごとにリフレッシュするタスクを作成するには、 your_warehouse_name をウェアハウス名に置き換えて、以下のステートメントを実行します。

   CREATE OR REPLACE TASK ad_model_retrain_task
   WAREHOUSE = <your_warehouse_name>
   SCHEDULE = '60 MINUTE'
   AS
   EXECUTE IMMEDIATE
   $$
   BEGIN
     CREATE OR REPLACE SNOWFLAKE.ML.ANOMALY_DETECTION model_trained_with_labeled_data(
       INPUT_DATA => SYSTEM$REFERENCE('VIEW', 'view_with_labeled_data_for_training'),
       TIMESTAMP_COLNAME => 'date',
       TARGET_COLNAME => 'sales',
       LABEL_COLNAME => 'label'
     );
   END;
   $$;

By default, newly created tasks are suspended.
Copy

タスクを再開するには、以下のコマンドを実行します。

ALTER TASK ad_model_retrain_task RESUME;
Copy

タスクを一時停止するには、以下のコマンドを実行します。

ALTER TASK ad_model_retrain_task SUSPEND;
Copy

Snowflakeタスクを使用したモニタリング

Snowflakeタスクを使用して、指定された頻度でデータをモニターすることもできます。

まず、異常検出の結果を保持するテーブルを作成します。

CREATE OR REPLACE TABLE anomaly_res_table (
  ts TIMESTAMP_NTZ, y FLOAT, forecast FLOAT, lower_bound FLOAT, upper_bound FLOAT,
  is_anomaly BOOLEAN, percentile FLOAT, distance FLOAT);
Copy

定期的な異常検出操作の結果をテーブルに格納するタスクを作成します。

CREATE OR REPLACE TASK ad_model_monitoring_task
WAREHOUSE = snowhouse
SCHEDULE = '1 minute'
AS
EXECUTE IMMEDIATE
$$
BEGIN
  CALL model_trained_with_labeled_data!DETECT_ANOMALIES(
    INPUT_DATA => SYSTEM$REFERENCE('VIEW', 'view_with_data_to_analyze'),
    TIMESTAMP_COLNAME => 'date',
    TARGET_COLNAME => 'sales',
    CONFIG_OBJECT => {'prediction_interval':0.99}
  );

INSERT INTO anomaly_res_table (ts, y, forecast, lower_bound, upper_bound, is_anomaly, percentile, distance)
  SELECT * FROM TABLE(RESULT_SCAN(LAST_QUERY_ID()));
END;
$$;
Copy

タスクを再開するには、以下のコマンドを実行します。

ALTER TASK ad_model_monitoring_task RESUME;
Copy

anomaly_res_table には各タスクの実行結果がすべて含まれます。

タスクを一時停止するには、以下のコマンドを実行します。

ALTER TASK ad_model_monitoring_task SUSPEND;
Copy

Snowflakeアラートを使用したモニタリング

Snowflakeアラート を使用して、指定された頻度でデータをモニターし、検出された異常をメールで送信することもできます。次のステートメントは、1分ごとに異常を検出するアラートを作成します。まず、 ストアドプロシージャ を定義して異常を検出し、次にそのストアドプロシージャを使用するアラートを作成します。

CREATE OR REPLACE PROCEDURE extract_anomalies()
  RETURNS TABLE()
  LANGUAGE SQL
  AS
  $$
    BEGIN
      CALL model_trained_with_labeled_data!DETECT_ANOMALIES(
        INPUT_DATA => SYSTEM$REFERENCE('VIEW', 'view_with_data_to_analyze'),
        TIMESTAMP_COLNAME => 'date',
        TARGET_COLNAME => 'sales',
        CONFIG_OBJECT => {'prediction_interval':0.99}
      );

      DECLARE res RESULTSET DEFAULT (SELECT * FROM TABLE(RESULT_SCAN(-1)) WHERE is_anomaly = TRUE);
      BEGIN
        RETURN TABLE(res);
      END;
    END;
  $$
  ;

CREATE OR REPLACE ALERT sample_sales_alert
WAREHOUSE = <your_warehouse_name>
SCHEDULE = '1 MINUTE'
IF (EXISTS (CALL extract_anomalies()))
THEN
CALL SYSTEM$SEND_EMAIL(
  'sales_email_alert',
  'your_email@snowflake.com',
  'Anomalous Sales Data Detected in data stream',
  CONCAT(
    'Anomalous Sales Data Detected in data stream \n',
    'Value outside of prediction interval detected in the most recent run at ',
    current_timestamp(1)
  ));
Copy

アラートを開始または再開するには、以下のコマンドを実行します。

ALTER ALERT sample_sales_alert RESUME;
Copy

アラートを一時停止するには、次を実行します。

ALTER ALERT sample_sales_alert SUSPEND;
Copy

ストアドプロシージャからメールを送信するには、メール統合を設定する必要があります。 メール通知の送信 をご参照ください。

特徴量の重要性について

異常検出モデルは、選択した外生変数や自動生成時間特徴量(曜日や週番号など)、ターゲット変数の変換(移動平均や自己回帰ラグなど)など、モデルで使用されるすべての特徴量の相対的な重要性を説明することができます。この情報は、データに実際に影響を与えている要因を理解するのに役立ちます。

<name>!EXPLAIN_FEATURE_IMPORTANCE メソッドは、モデルのツリーが各特徴量を使用して決定した回数をカウントします。それから、これらの特徴量の重要度スコアは、合計が1になるように0から1の間の値に正規化されます。結果として得られるスコアは、トレーニング済みモデルの特徴量の近似ランキングを表します。

スコアが近い特徴量は同じような重要性を持ちます。極端に単純な系列(たとえば、対象列の値が一定の場合)では、すべての特徴量の重要度スコアが0になる可能性があります。

互いによく似た複数の特徴量を使用すると、それらの特徴量の重要度スコアが低下する可能性があります。たとえば、ある特徴量が 販売個数 であり、別の特徴量が 在庫個数 である場合、その値は相関している可能性があります。なぜなら、在庫個数よりも多く販売することはできず、在庫個数は販売個数よりも多くならないように在庫を管理しようとするからです。2つの特徴量が同じである場合、モデルは決定を下す際にそれらを交換可能なものとして扱い、その結果、同じ特徴量のうちの1つだけが含まれていた場合には、特徴量の重要度スコアは本来のスコアの半分になる可能性があります。

特徴量の重要度は、 ラグ特徴量 も報告します。トレーニング中、モデルはトレーニングデータの頻度(毎時、毎日、毎週)を推測します。特徴量 lagx (例: lag24)は、ターゲット変数 x 単位時間前の値です。たとえば、データが1時間ごとと推測される場合、 lag24 は24時間前のターゲット変数を表します。

ターゲット変数の他のすべての変換(移動平均など)は、結果テーブルの aggregated_endogenous_features として要約されます。

制限事項

  • 特徴量の重要度を計算する手法は選択できません。

  • 特徴量の重要度スコアは、どの特徴量がモデルの精度にとって重要かを直感的に理解するのに役立ちますが、実際の値は推測として考慮される必要があります。

モデルに対する特徴量の相対的な重要性を理解するには、モデルをトレーニングしてから、 <name>!EXPLAIN_FEATURE_IMPORTANCE を呼び出します。この例では、まず2つの外生変数を持つランダムデータを作成します。1つはランダムであるためモデルにとって重要性が低くなると考えられ、もう1つはターゲットのコピーであるためモデルにとって重要性が高くなると考えられます。

以下のステートメントを実行すると、データが生成され、モデルがトレーニングされ、特徴量の重要度が取得されます。

CREATE OR REPLACE VIEW v_random_data AS SELECT
  DATEADD('minute', ROW_NUMBER() over (ORDER BY 1), '2023-12-01')::TIMESTAMP_NTZ ts,
  MOD(SEQ1(),10) y,
  UNIFORM(1, 100, RANDOM(0)) exog_a
FROM TABLE(GENERATOR(ROWCOUNT => 500));

  CREATE OR REPLACE VIEW v_feature_importance_demo AS SELECT
    ts,
    y,
    exog_a
  FROM v_random_data;

  SELECT * FROM v_feature_importance_demo;

  CREATE OR REPLACE SNOWFLAKE.ML.ANOMALY_DETECTION anomaly_model_feature_importance_demo(
    INPUT_DATA => SYSTEM$REFERENCE('VIEW', 'v_feature_importance_demo'),
    TIMESTAMP_COLNAME => 'ts',
    TARGET_COLNAME => 'y',
    LABEL_COLNAME => ''
  );

  CALL anomaly_model_feature_importance_demo!EXPLAIN_FEATURE_IMPORTANCE();
Copy

出力

この例ではランダムなデータを使用しているため、出力がこれと正確に一致するとは限りません。

+------+--------------------------------------+-------+-------------------------+
| RANK | FEATURE_NAME                         | SCORE | FEATURE_TYPE            |
+------+--------------------------------------+-------+-------------------------+
|    1 | aggregated_endogenous_trend_features |  0.36 | derived_from_endogenous |
|    2 | exog_a                               |  0.22 | user_provided           |
|    3 | epoch_time                           |  0.15 | derived_from_timestamp  |
|    4 | minute                               |  0.13 | derived_from_timestamp  |
|    5 | lag60                                |  0.07 | derived_from_endogenous |
|    6 | lag120                               |  0.06 | derived_from_endogenous |
|    7 | hour                                 |  0.01 | derived_from_timestamp  |
+------+--------------------------------------+-------+-------------------------+

トレーニングログの検査

複数の系列を CONFIG_OBJECT => 'ON_ERROR': 'SKIP' でトレーニングする場合、トレーニングプロセス全体が失敗しなくても、個々の時系列モデルがトレーニングに失敗することがあります。どの時系列がなぜ失敗したかを把握するには、 <model_instance>!SHOW_TRAINING_LOGS を呼び出します。

CREATE TABLE t_error(date TIMESTAMP_NTZ, sales FLOAT, series VARCHAR);
INSERT INTO t_error VALUES
  (TO_TIMESTAMP_NTZ('2019-12-20'), 1.0, 'A'),
  (TO_TIMESTAMP_NTZ('2019-12-21'), 2.0, 'A'),
  (TO_TIMESTAMP_NTZ('2019-12-22'), 3.0, 'A'),
  (TO_TIMESTAMP_NTZ('2019-12-23'), 2.0, 'A'),
  (TO_TIMESTAMP_NTZ('2019-12-24'), 1.0, 'A'),
  (TO_TIMESTAMP_NTZ('2019-12-25'), 2.0, 'A'),
  (TO_TIMESTAMP_NTZ('2019-12-26'), 3.0, 'A'),
  (TO_TIMESTAMP_NTZ('2019-12-27'), 2.0, 'A'),
  (TO_TIMESTAMP_NTZ('2019-12-28'), 1.0, 'A'),
  (TO_TIMESTAMP_NTZ('2019-12-29'), 2.0, 'A'),
  (TO_TIMESTAMP_NTZ('2019-12-30'), 3.0, 'A'),
  (TO_TIMESTAMP_NTZ('2019-12-31'), 2.0, 'A'),
  (TO_TIMESTAMP_NTZ('2020-01-01'), 2.0, 'A'),
  (TO_TIMESTAMP_NTZ('2020-01-02'), 3.0, 'A'),
  (TO_TIMESTAMP_NTZ('2020-01-03'), 3.0, 'A'),
  (TO_TIMESTAMP_NTZ('2020-01-04'), 7.0, 'A'),
  (TO_TIMESTAMP_NTZ('2020-01-05'), 10.0, 'B'),
  (TO_TIMESTAMP_NTZ('2020-01-06'), 13.0, 'B'),
  (TO_TIMESTAMP_NTZ('2020-01-06'), 12.0, 'B'), -- duplicate timestamp
  (TO_TIMESTAMP_NTZ('2020-01-07'), 15.0, 'B'),
  (TO_TIMESTAMP_NTZ('2020-01-08'), 14.0, 'B'),
  (TO_TIMESTAMP_NTZ('2020-01-09'), 18.0, 'B'),
  (TO_TIMESTAMP_NTZ('2020-01-10'), 12.0, 'B');

CREATE SNOWFLAKE.ML.ANOMALY_DETECTION model(
  INPUT_DATA => SYSTEM$QUERY_REFERENCE('SELECT date, sales, series FROM t_error'),
  SERIES_COLNAME => 'series',
  TIMESTAMP_COLNAME => 'date',
  TARGET_COLNAME => 'sales',
  LABEL_COLNAME => '',
  CONFIG_OBJECT => {'ON_ERROR': 'SKIP'}
);

CALL model!SHOW_TRAINING_LOGS();
Copy

出力

+--------+-------------------------------------------------------------------------------------------------+
| SERIES | LOGS                                                                                            |
+--------+-------------------------------------------------------------------------------------------------+
| "B"    | {   "Errors": [     "Frequency cannot be inferred when duplicate timestamps are present."   ] } |
| "A"    | NULL                                                                                            |
+--------+-------------------------------------------------------------------------------------------------+

コストの考慮事項

異常検出モデルのトレーニングと使用にはストレージとコンピューティングコストがかかります。

仮想ウェアハウスの選択 で説明したように、トレーニングには、トレーニング済みモデルからの予測よりも多くのコンピューティングコストがかかります。しかし、予測は繰り返し使用するとコストがかさみます。Snowflakeのコンピューティングコストに関する一般的な情報については、 コンピューティングコストについて をご参照ください。

発生するストレージコストは、トレーニングステップで作成された ML モデルインスタンスのストレージに反映されます。モデルインスタンスに関連付けられたオブジェクトを表示するには、Account Usageビュー(例: ACCOUNT_USAGE.TABLES および ACCOUNT_USAGE.STAGES)に移動します。これらのオブジェクトは、NULL のデータベース列とスキーマ列で表示されます。しかし、 instance_id 列には、これらのオブジェクトがモデルインスタンスに含まれていることを示す値が入力されます。これらのオブジェクトはモデルインスタンスによって包括的に管理され、個別にアクセスしたり削除したりすることはできません。モデルに関連するストレージコストを削減するために、未使用のモデルや古いモデルは削除します。

Snowparkにおける異常検出の利用

session.call はまだ異常検出モデルに対応していません。Snowparkで異常検出モデルを呼び出すには、代わりに session.sql を使用します。

session.sql('call my_model!detect_anomalies(...)').collect()
Copy