クエリ作成ガイド

概要

このセクションでは、異常検出クエリを適切に設定する方法について説明します。大まかに言うと、次の 4 種類のパラメータで調整する必要があります。

  • 分析に含めるデータを指定するデータ選択パラメータ。例: QueryDataSetRequest.dimensionNamesQueryDataSetRequest.pinnedDimensionsQueryDataSetRequest.testedInterval
  • 集計パラメータ。スライスを比較するために使用する値を生成するために複数のイベントをグループ化する方法を指定します。例: ForecastParams.aggregatedDimension
  • 予測パラメータ。使用する値を計算するために採用されている予測アルゴリズムを構成します。例: ForecastParams.holdoutForecastParams.forecastHistoryForecastParams.minDensity
  • 密調整パラメータ。これが変更されると、報告される異常数、レイテンシ、計算リソースの数が増減します。例: ForecastParams.maxPositiveRelativeChangeForecastParams.maxNegativeRelativeChangeForecastParams.forecastExtraWeight

前提条件

クイックスタート ガイドのセットアップ手順に沿って、このガイドのすべてのコマンドを実行します。

ここでは、GDELT プロジェクトからのデータがすでにプリロードされている公開デモ データセットに対してクエリを実行し、各パラメータごとに返される結果に影響を与える方法を説明します。

次のクエリを作業ディレクトリに query.json として保存します。

{
  dimensionNames: ["EntityLOCATION"],
  testedInterval: {
    startTime: "2019-04-15T00:00:00Z",
    length: "86400s"
  },
  forecastParams: {
    forecastHistory: "2592000s",
    holdout: 10.0,
    minDensity: 0.0,
    maxPositiveRelativeChange: 1.0,
    maxNegativeRelativeChange: 1.0,
    forecastExtraWeight: 200.0
  }
}

クイックスタート ガイドで説明されているように、次のコマンドを使用してクエリを発行できます。

$ gcurl -X POST -d @query.json https://timeseriesinsights.googleapis.com/v1/projects/timeseries-insights-api-demo/datasets/webnlp-201901-202104:query

このガイドでは、query.json 内の異なるパラメータを変更して、出力に及ぼす影響を示します。上の gcurl コマンドをコピーして、クエリを再実行することもできます。このコマンドは クイックスタート ガイドの araad です。

データの選択

異常検出クエリは、特定の期間内になんらかの異常が発生して特定のデータセットに異常が見つかったかどうかを評価し、必要に応じて一部のディメンションの値をフィルタします。このセクションでは、データ選択のすべてのステップを制御する方法について説明します。

時間間隔の指定

QueryDataSetRequest.tested_interval を設定することで、異常の検査対象となる時間間隔を指定できます。query.json では、2019 年 4 月 15 日の期間中に発生した異常を検出する必要があることを指定します。

...
  testedInterval: {
    startTime: "2019-04-15T00:00:00Z",
    length: "86400s"
  },
...

たとえば、2019 年 4 月 15 日午後 1 時~午後 2 時に発生した異常を検出するには、代わりに testedInterval を次のように設定します。

...
  testedInterval: {
    startTime: "2019-04-15T13:00:00Z",
    length: "3600s"
  },
...

ヒント: 異なる開始時間と長さを設定して testedInterval 値を再生し、返される異常の違いを確認します。

スライス

特定の期間内の異常を検出する際は、データスライスへのイベントのグループ化方法も指定する必要があります。そのためには、dimensionNames をデータセット全体で分割するディメンションのセットに設定します。

query.json では、"EntityLOCATION" のディメンション dimensionNames: ["EntityLOCATION"] のみでデータをスライスしています。結果リストでは、すべてのスライスが「EntityLocation」ディメンションに対する異なる値であることがわかります。

データを複数のディメンションに分割する場合は、次のように複数のディメンション名を指定できます。

{
  dimensionNames: ["EntityLOCATION", "EntityORGANIZATION"],
  testedInterval: {
    startTime: "2019-04-15T00:00:00Z",
    length: "86400s"
  },
  forecastParams: {
    forecastHistory: "2592000s",
    holdout: 10.0,
    minDensity: 0.0,
    maxPositiveRelativeChange: 1.0,
    maxNegativeRelativeChange: 1.0,
    forecastExtraWeight: 50.0
  }
}

このクエリを実行すると、2 つの指定されたディメンション「EntityLOCATION」と「EntityORGANIZATION」の値が取得されます(返される最初の異常スライスのみが表示されています)。

$ gcurl -X POST -d @query.json https://timeseriesinsights.googleapis.com/v1/projects/timeseries-insights-api-demo/datasets/webnlp-201901-202104:query

{
  "name": "projects/timeseries-insights-api-demo/datasets/webnlp-201901-202104",
  "anomalyDetectionResult": {
    "anomalies": [
      {
        "dimensions": [
          {
            "name": "EntityLOCATION",
            "stringVal": "Seine"
          },
          {
            "name": "EntityORGANIZATION",
            "stringVal": "AP"
          }
        ],
        "result": {
          "holdoutErrors": {},
          "trainingErrors": {},
          "forecastStats": {
            "numAnomalies": 1
          },
          "testedIntervalActual": 344
        },
        "status": {}
      },
...

フィルタリング

データセットのサブセットのみの分析が必要な場合は、pinnedDimensions を設定すると、ディメンションごとに特定の値を持つイベントのみをフィルタリングできます。

EntityORGANIZATION によるフィルタリングと EntityLOCATION によるスライスの例(最初の結果のみを表示します):

$ cat query.json

{
  dimensionNames: ["EntityLOCATION"],
  pinnedDimensions: [
  {
    name: "EntityORGANIZATION",
    stringVal: "AP"
  }
  ],
  testedInterval: {
    startTime: "2019-04-15T00:00:00Z",
    length: "86400s"
  },
  forecastParams: {
    forecastHistory: "2592000s",
    holdout: 10.0,
    minDensity: 0.0,
    maxPositiveRelativeChange: 1.0,
    maxNegativeRelativeChange: 1.0,
    forecastExtraWeight: 250.0
  }
}

$ gcurl -X POST -d @query.json https://timeseriesinsights.googleapis.com/v1/projects/timeseries-insights-api-demo/datasets/webnlp-201901-202104:query

{
  "name": "projects/timeseries-insights-api-demo/datasets/webnlp-201901-202104",
  "anomalyDetectionResult": {
    "anomalies": [
      {
        "dimensions": [
          {
            "name": "EntityLOCATION",
            "stringVal": "Seine"
          }
        ],
        "result": {
          "holdoutErrors": {},
          "trainingErrors": {},
          "forecastStats": {
            "numAnomalies": 1
          },
          "testedIntervalActual": 344
        },
        "status": {}
      },
      {
        "dimensions": [
          {
            "name": "EntityLOCATION",
            "stringVal": "Ile de la Cite"
          }
        ],
        "result": {
          "holdoutErrors": {},
          "trainingErrors": {},
          "forecastStats": {
            "numAnomalies": 1
          },
          "testedIntervalActual": 282
        },
        "status": {}
      },
...

集計

デフォルトの集計方法では、スライス内のイベント数がカウントされています。

また、数値ディメンションを合計すると、イベントを集計することもできます。これは、合計を集計する数値ディメンションに ForecastParams.aggregatedDimension を設定することで指定できます。

予測の設定

テストされた時間間隔で期待値を計算するには、スライス アルゴリズムが使用されます。予測アルゴリズムは、スライスの履歴値に基づいて、テストされた間隔で必要な値を予測します。

: スライスの値は、集計メソッドによって指定されます。

予測の履歴

時系列に含まれるデータの量は、ForecastParams.forecastHistory パラメータで指定します。

最初の例では、次のようになります。

  • 2019 年 3 月 16 日から 2019 年 4 月 15 日までの間にイベントを取得し、その 2 つの期間間で時系列を形成するように指示できるように、forecastHistory: "2592000s" を設定しました。
  • 時系列の各データポイントは、テストされた間隔と同じ長さ(たとえば 86400s - 1 日)に対応します。
  • 時系列には 30 個のポイントがあり、各ポイントはその日に発生したイベントについての集計値を保持します。集計方法としてカウントする場合、最初の時系列ポイントは 2019 年 3 月 16 日の合計イベント数として 2019 年 3 月 17 日以降のものになります。

ForecastResult.history フィールドで返された時系列の履歴値を確認できます(リクエストで QueryDataSetRequest.returnTimeseriestrue に設定されている場合のみ返されます)。

: これは、Timeseries proto として定義されます。TimeseriesPoint )のように、時間順で並べ替えられ、(TimeseriesPoint.value )、TimeseriesPoint.timeTimeseriesPoint.time + testedInterval.length ] を基準とする時間間隔が決まっています。

ForecastParams.forecastHistory の値を大きくし、長い履歴を含めることで、特定の季節パターンをキャプチャし、より多くのデータを含む予測の精度を高めることができます。たとえば、季節パターンが ある場合、forecastHistory 30 日間に設定すると、このようなパターンをキャプチャできないため、forecastHistory分析する時系列に複数の月パターンがあります(たとえば、月単位のパターンが 100 ~ 300 日で十分であれば、実際のパターンによっても十分です)。

最初の例では、testedInterval.length3600s(1 時間)に減らして ForecastParams.forecastHistory8640000s(100 日間)に増やしてみてください。これにより、history 時系列のポイント数が 2400 に増え、より詳細な設定ができるようになります。

ホールドアウト/テスト間隔

予測品質を評価するため、時系列の最初の X% でのみトレーニングを行います。時系列の最後の部分は評価目的で保持され、ForecastParams.holdout パラメータによって制御されます。

ForecastParams.holdout パラメータは、パーセンテージ(0 ~ 100 の範囲)を表し、テストのために保持するデータの量を示します。この例では holdout: 10.0 を指定しているため、最初の 90% に基づく予測のパフォーマンスを評価するため、時系列の最後の 10% を維持します。

最初の例では 30 の時系列があるため、最初の 27 ポイントについてはトレーニングに、最後の 3 つのモデルはモデルのテストと評価に保持されていることを意味します。

ホールドアウト期間中に測定されたエラーは ForecastResult.holdoutErrors に返され、それらのエラーは予測の下限と上限の計算(testedIntervalForecastLowerBoundtestedIntervalForecastUpperBound)の計算に使用されます。ホールドアウト エラーが大きいほど、予測範囲が厳しくなります。また、エラーが減少しれば、限界が広がります(ForecastResult.testedIntervalForecast に近づきます)。

ホールドアウト値は低い割合(3%〜10%)にする必要がありますが、予測境界の計算にはこうしたエラーが必要になるため、データポイントに十分な数のデータポイントが含まれている必要があります。

最小密度

ForecastParams.minDensity パラメータで指定された最小密度(時系列が 1 つ以上のイベントを含む)で、時系列に含まれる可能性のある異常数に対して、潜在的な異常とみなされるのに必要な値を指定します。

ホールドアウトと同様、0 ~ 100 の範囲のパーセンテージ値です。

ポイントの数は、testedInterval.startTime - forecastHistory から testedInterlal.startTime までの予想ポイントの数と比較されます。

たとえば、予想される時系列が 30 個ある場合(最初の例のように testedInterval.length を 1 日、forecastHistory を 30 日に設定した場合)、minDensity を設定します。 80 に設定すると、1 つ以上のイベントを含む 24 点を含む時系列のみ受け入れられます。

: この例では、minDensity を 0 に設定し、スパイクを検出するときに 0 に設定することをおすすめします。

ホライズン

ForecastParams.horizonTime で指定された timegrid は、テストされた期間から将来の期間を指定するだけです。過去の時系列に基づいて値を予測します。

QueryDataSetRequest.returnTimeseries が true に設定されている場合、予測時系列がスライスごとに ForecastResult.forecast に返され、testedInterval.startTime + testedInterval.lengthtestedInterval.startTime + testedInterval.length + horizonTime の間の予測値が含まれます。

感度調整

スライスのテスト済み間隔と予測された値に基づいて、スライスは機密パラメータに基づいて異常とみなすことができます。パラメータは次のとおりです。

  • ForecastParameters.maxPositiveRelativeChange は、testedIntervalForecastUpperBound と比較して、実際の値を増やすことができる値を指定します。
  • ForecastParameters.maxNegativeRelativeChange は、testedIntervalForecastLowerBound と比較した場合の実際の値の減少を指定します。
  • ForecastParameters.forecastExtraWeight は、予測境界と予測境界を比較するときに、余分な重みとして使用されます。より小さな絶対分散を無視する場合は、重みを大きくすることをおすすめします。

: Positive と Negative の変更にはそれぞれ異なるパラメータがあり、クライアントを thresholds めたり弱くしたりして、しきい値を変えることができます。高い上限。

: 正の時系列の場合、maxNegativeRelativeChange の最大実数は 1.0 です(たとえば、集計メソッドとしてイベント数をカウントする場合)。実際の価値の 100%

ベースラインとして、次の機密パラメータをすべて 0 に設定します。

{
  dimensionNames: ["EntityLOCATION"],
  testedInterval: {
    startTime: "2019-04-15T00:00:00Z",
    length: "86400s"
  },
  forecastParams: {
    forecastHistory: "2592000s",
    holdout: 10.0,
    minDensity: 0.0,
    maxPositiveRelativeChange: 0.0,
    maxNegativeRelativeChange: 0.0,
    forecastExtraWeight: 0.0
  }
}

これは、最も実行可能なクエリであり、testedIntervalActual が [testedIntervalForecastLowerBound, testedIntervalForecastUpperBound] の境界の外側にあるすべてのスライスとしてマーキングされます。これが望ましい内容のように思えますが(一部のアプリケーションでも役立つ可能性があります)、実際には、その異常のほとんどが無視されることが考えられるため、基本的には無視してかまいません。

このベースライン クエリを実行すると、約 2,500 件の異常が発生します。

$ gcurl -X POST -d @query.json https://timeseriesinsights.googleapis.com/v1/projects/timeseries-insights-api-demo/datasets/webnlp-201901-202104:query \
    | grep "testedIntervalActual" | wc -l

2520

maxPositiveRelativeChangemaxNegativeRelativeChange の両方を 1.0 に増やすと、異常数が約 1,800 に減少します。これにより、変動の小さなスライスは取り除かれますが、それでも大量のスライスとして分類されます。

そのニュースの中で、その日に急上昇した急上昇が特に多い場合にのみ、forecastExtraWeight を増やすと、ボリュームの小さいスライスを除外できます。200.0 に設定して、最終的な query.json を設定します。

{
  dimensionNames: ["EntityLOCATION"],
  testedInterval: {
    startTime: "2019-04-15T00:00:00Z",
    length: "86400s"
  },
  forecastParams: {
    forecastHistory: "2592000s",
    holdout: 10.0,
    minDensity: 0.0,
    maxPositiveRelativeChange: 1.0,
    maxNegativeRelativeChange: 1.0,
    forecastExtraWeight: 200.0
  }
}

前のクエリを実行すると、3 つの異常しか発生せず、それらが 2019 年 4 月 15 日のニュースで最も多く言及された「ノートルダム 火災」に関連するものとなります。

$ gcurl -X POST -d @query.json https://timeseriesinsights.googleapis.com/v1/projects/timeseries-insights-api-demo/datasets/webnlp-201901-202104:query \
    | grep stringVal

            "stringVal": "Ile de la Cite"
            "stringVal": "Notre Dame"
            "stringVal": "Seine"

クエリのパフォーマンスとリソース使用量

ノイズ低減を減らし、関心のないスライスを除外することで、異常検出の感度を下げることで、クエリのレイテンシとリソース使用量を大幅に削減することもできます。

通常、forecastExtraWeight を増やすと、異常な slices 著な slices 度が減少するため、クエリ パフォーマンスの向上を目的として改善する必要がある主な機密性パラメータになります。

さまざまな機密パラメータを使用して、クエリのパフォーマンスにどのように影響するかを確認できます。次に例を示します。

$ cat query.json

{
  dimensionNames: ["EntityLOCATION"],
  testedInterval: {
    startTime: "2019-04-15T00:00:00Z",
    length: "86400s"
  },
  forecastParams: {
    forecastHistory: "2592000s",
    holdout: 10.0,
    minDensity: 0.0,
    maxPositiveRelativeChange: 0.0,
    maxNegativeRelativeChange: 0.0,
    forecastExtraWeight: 0.0
  }
}

$ time gcurl -X POST -d @query.json https://timeseriesinsights.googleapis.com/v1/projects/timeseries-insights-api-demo/datasets/webnlp-201901-202104:query \
    | grep stringVal | wc -l

2580

real 0m26.765s
user 0m0.618s
sys  0m0.132s

機密性が高いパラメータでは、クエリに約 26.7 秒かかっていることがわかります。感度を下げることで、最大 3.4 秒の高速化が可能です。

$ cat query.json

{
  dimensionNames: ["EntityLOCATION"],
  testedInterval: {
    startTime: "2019-04-15T00:00:00Z",
    length: "86400s"
  },
  forecastParams: {
    forecastHistory: "2592000s",
    holdout: 10.0,
    minDensity: 0.0,
    maxPositiveRelativeChange: 1.0,
    maxNegativeRelativeChange: 1.0,
    forecastExtraWeight: 200.0
  }
}

$ time gcurl -X POST -d @query.json https://timeseriesinsights.googleapis.com/v1/projects/timeseries-insights-api-demo/datasets/webnlp-201901-202104:query \
    | grep stringVal | wc -l

3

real 0m3.412s
user 0m0.681s
sys  0m0.047s

次のステップ