elasticsearch-anomaly-detection-explainer について
elasticsearch-anomaly-detection-explainerは、Elasticsearch ML異常検知の利用者向け解釈スキルです。ジョブ設定と異常レコードを調べ、スコア、モデルの挙動、再正規化、関連する背景情報を説明します。
主な機能
- 01MLジョブ設定と統計情報の取得
- 02初期スコアと現在のスコア差の説明
- 03actualとtypicalによる異常方向の解釈
- 04スコア要因と影響エンティティの確認
- 05モデル境界とログカテゴリの取得
活用シーン
- 01特定の異常レコードのスコア説明
- 02予想外に低いまたは高いスコアの調査
- 03ジョブ全体のスコア再正規化の測定
- 04異常の影響要因やモデル境界の確認
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ elastic/ agent-skills --skill elasticsearch-anomaly-detection-explainerインストール後、Claude Code で/elasticsearch-anomaly-detection-explainerを入力して読み込まれたか確認します。
同梱ファイルreferences/explainer-reference.md
詳細
異常検知スコアの解説
異常スコアやモデルの動作を説明し、結果がそのように見える理由を解説します。ジョブ設定には ML REST API を使用し、
結果の取得には .ml-anomalies-* に対する標準の _search API を使用します。ES|QL は使わず、Elastic
Serverless と完全に互換性があります。ジョブのライフサイクル(作成、開始、停止)には、elasticsearch-anomaly-detection スキルを使用してください。
環境設定
このスキルでは、Elasticsearch の操作に elastic CLI を使用します。
elastic CLI がインストールされていない場合は、何に必要なのかをユーザーに伝えてください。認証情報を推測したり、HTTP API を直接呼び出したり、ほかの回避策を試したりしないでください。
このスキルでは、HTTP 省略形式(例:GET /、GET /_cat/indices、GET /{index}/_mapping、
GET /{index}/_settings/index.mode、POST /_query)で操作を参照します。このドキュメントの最後にある
操作の表で、各省略形式に対応する elastic CLI コマンドを確認できます。HTTP API を直接呼び出すのではなく、必ず CLI を使用してください。
前提条件: ML 異常検知をセルフマネージドクラスターで使用するには、Platinum 相当のライセンスが必要です。Serverless プロジェクトには ML が含まれています。呼び出し元には、ジョブ設定と異常結果を読み取るための
monitor_ml権限が必要です。Serverless に関する注意: Elastic Serverless では、
_ml/.../results/*REST エンドポイントは HTTP 410 を返します。結果のクエリには、常にPOST /.ml-anomalies-*/_searchを使用してください。この方法は、このスキルが実行されるすべての環境で完全にサポートされています。
プロセス
-
データを取得するか、ユーザーが提供した内容を解釈するかを判断します。 ユーザーのプロンプトに異常レコード(またはジョブ設定)が含まれている場合は、以下のドメイン知識を使ってそのまま解釈します。すでに提示されているフィールドを再取得するために API を呼び出さないでください。ジョブ ID、時間範囲、またはレコードが不足している場合は、クラスターから取得します。
判断基準:レコードに
record_score、initial_record_score、actual、typical、functionが含まれている場合は、判断のみに基づく説明に進みます。それ以外の場合は、説明の前に不足している情報を取得します。 -
クラスターに接続するときは、接続を確認します。
GET /を呼び出します。呼び出しに失敗した場合は、処理を中止して接続エラーを提示してください。エンドポイントや認証情報を推測しないでください。 -
ジョブ ID を特定し、設定を読み込みます。 ジョブ ID が不明な場合は、
GET /_ml/anomaly_detectorsを呼び出して候補を一覧表示します。GET /_ml/anomaly_detectors/{job_id}を呼び出して、完全なanalysis_config(bucket_span、detectors、 custom_rules、use_null、model_plot_config)を取得し、GET /_ml/anomaly_detectors/{job_id}/_statsを呼び出して、state、model_size_stats.memory_status、データ件数を取得します。判断基準:スコアを解釈する前に、検知器の関数と方向がユーザーの質問に合っていることを確認してください。
low_countジョブが減少を検知するのは正常ですが、high_countジョブは減少を検知しません。 -
時間範囲内の異常レコードを取得します。
result_type: record、ジョブ ID、タイムスタンプの範囲、必要に応じてrecord_scoreフィルターを指定して、POST /.ml-anomalies-*/_searchを呼び出します。initial_record_score、record_score、actual、typical、function、multi_bucket_impact、anomaly_score_explanationを読み取ります。initial_record_scoreとrecord_scoreの両方を必ず表示してください。 両者の差が再正規化の経緯を示します。 -
原因を推測する前に、スコアのパターンを分類します。
initial_record_score>>record_score— 再正規化です。 後から発生した、より極端な異常によって、このレコードのスコアが下方修正されています。これは想定どおりの健全なモデルの動作であり、モデルの故障や検知を疑う理由にはなりません。アラートの重大度にはinitial_record_scoreを使用し、両方のスコアを示して、その差を明確に説明します。initial_record_score==record_score— 検知以降、再正規化は行われていません。actual<<typicalで、low_count、count、またはlow_meanがある場合 — 欠落/減少の異常です。 高スコアは妥当なもので、ジョブが停止、パイプラインの停滞、またはサービス障害を検知しています。これは誤検知ではありません。 スコアの調整ではなく、インシデントの調査を推奨します。actual>>typicalで、high_countまたはhigh_meanがある場合 — スパイク異常です。single_bucket_impactで確認します。
レコードに存在する
anomaly_score_explanationの要因のみを挙げます。high_variance_penaltyがfalseの場合、分散を原因にしてはいけません。要因がない場合は、返されていないことを記載し、作り上げてはいけません。 -
ジョブ全体の再正規化を定量化します(任意)。
POST /.ml-anomalies-*/_searchを再実行し、対象の時間範囲のレコードをtimestampの昇順で並べます。レコードごとにscore_drift = initial_record_score − record_scoreを計算し、|score_drift| ≥ 20で絞り込みます。大きな負のドリフト(initial >> record)は、後からより極端な異常が出現したことで再正規化されたことを示します。 -
ユーザーが「何が原因ですか?」や「なぜこれほど低い/高いのですか?」と尋ねた場合は、コンテキストを追加します。
- モデルの境界 —
model_plot_config.enabledが true の場合、同じジョブと時間範囲を対象に、result_type: model_plotを指定してPOST /.ml-anomalies-*/_searchを呼び出します。actualをmodel_lower/model_upperと比較します。 - インフルエンサー — バケットの時間範囲を対象に、
result_type: influencerを指定してPOST /.ml-anomalies-*/_searchを呼び出し、influencer_scoreの降順で並べます。 - カテゴリ化ジョブ —
result_type: category_definitionを指定してPOST /.ml-anomalies-*/_searchを呼び出し、学習済みのログパターン(category_idごとのterms、regex、examples)を一覧表示します。
集計、ジョブ横断のクエリ、バケットレベルの結果、またはスコアと時間以外のカスタムフィルターについては、references/explainer-reference.md を参照してください。
- モデルの境界 —
よくある複数ステップのワークフロー
| タスク | 手順(順番どおり) |
|---|---|
| 特定の異常を説明する | ジョブ設定 → レコード(ジョブ+正確な時刻)→ initial_record_score と record_score、およびスコア要因を提示します。 |
| スコアが低いのはなぜですか? | ジョブ設定 → レコード → 再正規化の確認 → モデルプロット(有効な場合)→ スコア要因を説明します。 |
| スコアが高いのはなぜですか? | ジョブ設定 → レコード → 関数の方向、不十分な履歴、use_null、カーディナリティを確認します。 |
| 再正規化のドリフト | レコード(timestamp で並べ替え)→ score_drift を計算 → initial >> record のレコードを一覧表示します。 |
| どのエンティティが寄与しましたか? | インフルエンサー(ジョブ+時間範囲)→ influencer_score で並べ替えます。 |
| モデルの境界を可視化する | モデルプロット(ジョブ+時間範囲)→ model_lower/model_upper と actual を比較します。 |
| カテゴリ化ジョブのパターン | category_definition(job_id)→ カテゴリごとの terms、regex、examples。 |
重要な原則
- まずレコードを取得してください(または、ユーザーが提供したレコードを使用してください)。
initial_record_score、record_score、actual、typical、functionがない状態でスコアを説明してはいけません。 - 再正規化は正常な動作です。
initial_record_score >> record_scoreの場合、後からより極端な異常が発生して このスコアが下がったことを示します。これは想定された動作であり、モデルの不具合ではありません。 - 方向が重要です。
low_countは値が低下したときに反応し、high_countは急上昇したときに反応します。交通量の 停止でlow_countのスコアが高い場合は、誤検知ではなく正しい検知です。 - 推測する前に要因を説明してください。 レコードから
anomaly_score_explanationを確認してください。含まれていて 関連性のある要因のみ取り上げてください。 - ジョブ設定は不可欠です。
bucket_span、検出関数、custom_rules、use_null、メモリの状態はすべてスコアに 影響します。スコアに違和感がある場合は、ジョブ設定を調べてください。 - 最も視覚的に説明できるのはモデルプロットです。 有効になっている場合は、モデルの範囲を表示して、実際の値が 予測範囲のどこに位置するかを示してください。
- ジョブの健全性(「ドキュメントが不足している」「メモリ制限」「データフィードが実行されていない」)については、
elasticsearch-anomaly-detectionスキルを使用してください。
ドメイン知識
スコアの種類
| 用語 | 意味 |
|---|---|
| record_score | 単一の異常レコードに対する正規化済みの 0~100 のスコア。再正規化によって更新されます。75 超は重大です。 |
| initial_record_score | 再正規化前、検出時に割り当てられたスコアです。アラートにはこの値を使用してください。 |
| anomaly_score | ジョブ内のすべての検出器を集約した、バケットレベルの重大度です。 |
| influencer_score | バケット内の特定のエンティティ(ホスト、ユーザー、サービス)がどれほど異常かを示します。高いほど原因である可能性が高くなります。 |
| multi_bucket_impact | 0~5 の値で、複数のバケットにわたって持続する動作がスコアをどれほど引き上げたかを示します。≥3 は動作の変化を示します。 |
anomaly_score_explanation の要因
各レコードの anomaly_score_explanation フィールドでは、スコアが要素ごとに分解されています。
| 要因 | 方向 | 意味 |
|---|---|---|
| anomaly_length | 上昇 | 異常が継続した連続バケット数です。長いほどスコアが高くなります。 |
| single_bucket_impact | 上昇 | この単一バケットの極端さです。確率が低いほど影響度が高くなります。 |
| multi_bucket_impact | 上昇 | 複数のバケットにわたって持続するパターンの寄与です。 |
| anomaly_characteristics_impact | 上昇 | 異常が平均値のシフトか分散の変化かを示します。 |
| high_variance_penalty | 低下 | ノイズの多いデータやトレーニング初期には信頼区間が広がり、スコアが下がります。 |
| incomplete_bucket_penalty | 低下 | バケット内のデータが想定より少なかったことを示します(データの遅延、イベントの疎らさ)。 |
スコアが予想外に低くなる理由
- high_variance_penalty: 指標の過去の変動が大きく、信頼区間が広いため、急上昇が吸収されます。
- 再正規化: 後からより極端な異常が発生し、このスコアが下がりました(
initial_record_score>>record_score)。 - トレーニング履歴が不十分: 週ごとの季節性には 3 週間以上、検出対象の期間には完全な周期が 2 回以上必要です。
bucket_spanが大きすぎる: 短時間の急上昇が平滑化されます。高頻度のイベントには、より小さなbucket_spanを使用してください。- 検出関数の不一致:
meanとhigh_mean、countとhigh_countのような違いです。反応する方向は一方だけです。 - incomplete_bucket_penalty: バケットに取り込まれたデータが想定より少なかったことを示します(取り込みの遅延または欠落)。
custom_rules: 検出器のフィルターによって異常が抑制されている可能性があります。
スコアが予想外に高くなる理由
- 履歴が不十分: モデルがまだ通常のパターンを学習していないため、初期の異常は信頼性が低くなります。
- モデルの分割が細かすぎる: カーディナリティの高い
partition_fieldまたはby_fieldによって、エンティティごとのポイントが非常に少なくなり、確率の信頼性が低くなります。 - use_null:
use_null: trueの場合、欠落したエンティティによって「null」異常が発生しますが、意味があるとは限りません。 - 不在/減少の検出:
low_countまたはlow_meanでは、actual << typicalによって正当に高いスコアが生成されます。これは誤検知ではなく、実際のインシデントとして扱ってください。
モデルの動作に関する概念
| 概念 | 意味 |
|---|---|
| actual | 観測値です。typical はモデルが予測した値です。方向が重要です。 |
| 不在異常 | count、low_count、または low_mean での actual << typical は、停止、パイプラインの中断、サービス障害を示します。 |
| by_field | エンティティごとの独立したベースライン(例:ホストごと)です。各エンティティをそれぞれの履歴と比較します。 |
| over_field | 母集団の分析です。エンティティを自身の履歴ではなく、同じバケット内のピアグループと比較します。 |
| partition_field | パーティションごとにスコアの正規化を分けた、完全に独立したサブモデルです。 |
モデルプロットとカテゴリ
- モデルプロット: 各時点でモデルが学習した上限と下限を示します。
actualが範囲内なら異常ではありません。範囲外の場合、スコアは境界からの距離に応じて決まります。ジョブでmodel_plot_configが有効な場合にのみ利用できます。result_type: model_plotを指定してPOST /.ml-anomalies-*/_searchでクエリします。 - カテゴリ:
categorization_field_nameを持つジョブでは、result_type: category_definitionをクエリすると、ログメッセージのパターン(各category_idの用語、正規表現、例)を表示できます。異常レコードではby_field_value = <category_id>が使用されます。
スコアのトラブルシューティング手順
- ジョブを一覧表示する — ジョブ ID が不明な場合は、
GET /_ml/anomaly_detectorsを呼び出します。 - ジョブの設定と統計情報を取得する —
GET /_ml/anomaly_detectors/{job_id}とGET /_ml/anomaly_detectors/{job_id}/_statsを呼び出します。bucket_span、検出関数、custom_rules、use_null、 ジョブの状態(opened/closed/failed)、model_size_stats.memory_statusを確認します。 - レコードを取得する —
result_type: record、ジョブ ID、時間範囲、およびオプションの最小record_scoreを指定して、POST /.ml-anomalies-*/_searchを呼び出します。initial_record_score、record_score、actual、typical、function、multi_bucket_impact、anomaly_score_explanationを確認します。 - 再正規化を確認する —
initial_record_scoreとrecord_scoreを比較します。初期値がレコードスコアを大幅に上回る場合は、タイムスタンプ順にレコードを再クエリし、score_driftを計算してジョブ全体の再正規化を定量化します。 - モデル境界を可視化する —
model_plot_configが有効な場合は、result_type: model_plotをクエリし、実際の値がmodel_lowerとmodel_upperに対してどの位置にあったかを示します。 - インフルエンサー — 異常バケットの時間範囲について
result_type: influencerをクエリし、influencer_scoreの降順に並べます。 - 要因を説明する — レコードの
anomaly_score_explanationから、該当する存在する要因をそれぞれ説明します。high_variance_penalty、incomplete_bucket_penalty、anomaly_length、single_bucket_impact、multi_bucket_impactが対象です。レコードに存在しない要因には言及しないでください。
例
- 「急上昇が大きく見えるのに、異常スコアが 15 なのはなぜですか?」→ 再正規化を確認してください。
initial_record_score(約 92)>>record_score(約 15)です。急上昇は実際に発生していましたが、現在のスコアは再スケーリングされて低くなっています。アラートには初期スコアを使用してください。 - 「トラフィックが止まったのに、HIGH スコアが出ました。誤検知ですか?」→ いいえ。
actualがtypicalを大きく下回るlow_countは、正当な不在検知です。障害を調査してください。 - 「昨夜、ジョブ X の異常に最も寄与したエンティティはどれですか?」→ 該当する時間範囲のインフルエンサーをクエリしてください。
- 「このジョブのモデル境界を表示してください。」→
model_plot_configが有効な場合は、モデルプロットをクエリしてください。 - 「スコアが大幅に下方へ再正規化されたレコードを一覧表示してください。」→ タイムスタンプ順にレコードを並べ、
initial_record_score − record_scoreが大きいものを絞り込んでください。
ガイドライン
- API またはユーザー提供のレコードに含まれる情報のみを報告してください。スコア、タイムスタンプ、エンティティ値、説明要因を捏造しないでください。
- レコードについて説明する際は、必ず
initial_record_scoreとrecord_scoreの両方を示し、再正規化が発生したかどうかを明示してください。 - スコア要因がレコードにない場合は、それについて断定せず、そのフィールドが返されなかったことを記載してください。
- レコード内のフラグが
falseまたは存在しない場合は、低スコアの原因をhigh_variance_penaltyまたはincomplete_bucket_penaltyにしないでください。 - 調査(「原因は何ですか?」「どのサービスに責任がありますか?」)では、インフルエンサーをクエリするか、references/explainer-reference.md を参照してジョブ間検索を組み立ててください。
- ジョブの健全性を確認するには、
elasticsearch-anomaly-detectionスキルを使用してください。
操作
| HTTP API(省略形) | elastic CLI コマンド |
|---|---|
GET / | elastic es info |
GET /_ml/anomaly_detectors | elastic es ml get-jobs |
GET /_ml/anomaly_detectors/{job_id} | elastic es ml get-jobs --job-id '<job_id>' |
GET /_ml/anomaly_detectors/{job_id}/_stats | elastic es ml get-job-stats --job-id '<job_id>' |
POST /.ml-anomalies-*/_search | elastic es search --index '.ml-anomalies-*' --input-file '<search-body.json>' |
各 result_type(record、influencer、model_plot、category_definition)のクエリ本文の形式は、
references/explainer-reference.md に記載されています。