Elasticsearchのマシン・ラーニング異常検知の動きを理解する(3) [変更設定編]

シリーズ記事
[Elasticsearchのマシン・ラーニング異常検知の動きを理解しよう(1)](https://qiita.com/nobuhikosekiya/items/e0fbb7792a9b70284c57)
[Elasticsearchのマシン・ラーニング異常検知の動きを理解する(2) [アラート編]](https://qiita.com/nobuhikosekiya/items/59cb1705dac98860c5dc)
[Elasticsearchのマシン・ラーニング異常検知の動きを理解する(3) [変更設定編]](https://qiita.com/nobuhikosekiya/items/ee8be363fe6e8faa75f1)

# はじめに
[前回](https://qiita.com/nobuhikosekiya/items/59cb1705dac98860c5dc)の記事では、MLの異常検知でアラートを出すための手順について書きました。
異様検知を運用で真剣に使い始めると、色々な変更作業が必要になってきます。

# どんな変更が想定されるか？
全てではないかもしれませんが、運用中の主な変更作業についてまとめます。

### 異常検知ジョブの分析対象の指標やBuket spanの変更(Detector設定)
Single Metricタイプのジョブは検知対象の指標が一つなので、変更したいとしたら指標の集約期間であるBucket spanくらいかと思います。
しかし、Multi Metricタイプのジョブは検知対象の指標及びInfluencer、Split Fieldも複数指定したりと、途中で変更したくなる可能性があります。
これらは学習モデルに影響のあるパラメータなので、基本的にはジョブ作成時にしか設定できません。変更したい場合はジョブをクローンして、その際に設定を変更する方法があります。
詳しいステップについては本記事の下の方に記載しています。

### アラートルールの変更
異常検知のジョブパラメータはそのままで、アラートを上げるSeverity値（スコア値）や、スコア対象（Bucket/Record/Influence)を変えたいケースもよくあると思います。

アラートルールの変更はもちろん可能です。アラート発報頻度が高すぎたり、低すぎたりする場合、Single Metric Chartで過去の異常検知スコアを確認し、どのスコアで検知させたいか確認しましょう。
一つの異常検知ジョブに対して複数のアラートを設定できます。よって異なるアラート条件を同時並行で動かすこともできますので、これで検知具合の差を運用で確認していくこともできるでしょう。


### 異常検知のカスタムルールの追加/変更
Detector設定の中に異常と判断させたくない条件を設定することができます。以下の２つの設定があります。
* 条件ロジック ... 例えばCPU使用率の異常検知では、50%以下の時の異常は検知させたくないといった追加の条件を設定
* フィルター値 ... 特定のデータ属性を除外。例えば特定のソースIPアドレスのログは想定通りに他とは異なる動きをするため、異常検知から除外させたい場合に設定

上記２点に対するアクションとして、以下の２つを設定できます。（片方、もしくは両方設定可能）
skip_result ... デフォルトのアクション。本設定後、異常検知対象ではなくなります。
skip_model_update ... 本設定後、さらに学習モデルに含まれないようにする場合はこちらも指定。

この設定は、稼働中のジョブに対しても変更できます。
詳しくは[こちら](https://www.elastic.co/guide/en/machine-learning/8.8/ml-configuring-detector-custom-rules.html)を参照ください。

### 計画的に特定期間を異常検知から除外
祝日、セール日、計画停止などがある場合など、異常検知対象から外したいケース。
事前にメンテナンスなどの計画が想定されていれば、[カレンダー](https://www.elastic.co/guide/en/machine-learning/8.8/ml-ad-run-jobs.html#ml-ad-calendars)の登録によりその期間を (1)異常検知されなくし、 (2)学習モデルに反映しないことができます。（1,2両方です。片方だけにしたいということはできません）

### 後から特定期間を学習モデルから除外
事前に上記カレンダーを登録できない場合、あるいはカレンダーを登録し忘れたような場合で、後から学習モデルから事象を除外したい場合もあると思います。

[モデルスナップショットのリストア機能](https://www.elastic.co/guide/en/machine-learning/current/ml-reverting-model-snapshot.html)により、一旦過去の状態の学習モデルをリストアしつつ、特定期間を対象外にしながらDataFeedにて現在時刻までロールフォワードさせることで、特定期間が学習モデルに反映されないようにすることができます。

ただし、例えば障害が発生したようなケースで、その障害のデータを学習させたくない場合にリストアすると、Anomaly Explorerなどで確認できる障害時の異常検知の結果情報も削除されてしまいます。それなりの頻度で起きるような小さい障害は、（リストアせずにそのままの運用で）学習モデルに反映するのが基本です。まれに起きるような大きな障害のケースの場合、リストアも検討する形です。

もしリストア前に異常検知の結果を保存しておきたい場合は、画面のスクリーンショットで記録を残すのが簡単ですが、やろうと思えば異常検知ジョブをクローンしてもう一つ作り、そっちの方で過去から障害発生までのデータをDatafeedで投入して異常検知の結果状態を再現することもできます。（クローンされたジョブにはモデルスナップショットはコピーできないので、Datafeedにて再現する必要があります。）　これを実施する際、一時的にElaticsearchのデータノードにも負荷がかかるので、本番での実施タイミングは注意ください。

モデルのスナップショットはデフォルトで3~4時間おきに取得されます。（ジョブパラメータbackground_persist_intervalで変更可能）
デフォルトでは自動的に10日前以上の古いスナップショットは削除されますが、ずっと残したいスナップショットは画面から指定できます(retain）。[参照](https://www.elastic.co/guide/en/machine-learning/8.8/ml-ad-run-jobs.html#ml-ad-model-snapshots)

# 異常検知ジョブのクローンを使った変更方法

実はそんなに難しくなく、[第１回](https://qiita.com/nobuhikosekiya/items/e0fbb7792a9b70284c57)でやったDatafeedの使い方をマスターしていると、以下のように対応できます。

1. 異常検知ジョブv1をクローンし、ジョブv2を作成します。クローンする際にジョブv2の分析パラメータを変更できます。
1. ジョブv2のDatafeedをStartする際に過去のデータを読み込めばすぐに過去データを学習してくれます。
1. この時点で異常検知の動きがv2にてどう変わったかを画面より確認します。
1. 設定に納得いけばそのまま、新しいデータについてのリアルタイムな異常検知を開始できます。
1. アラートルールはv1からコピーされていません。また、一つのアラートルールは一つの異常検知ジョブにしか使えないようになっています。よって、以前のアラートルールを再利用したい場合、アラートルールの管理画面でこちらもクローンし(アラートルールv2)、それをジョブv2に割り当てます。（ちなみに１つのジョブに複数のアラートを割り当てることは可能です）

一つ注意点です。ログデータが大量にある場合、2.のDatafeedによる過去データの学習にてElasticsearchに対するクエリー処理が多く実行され一時的な負荷となるので、本番で行う際は場合によっては夜のメンテナンス期間に実施したり、あるいはDatafeedの過去データ学習を小さく複数回に分けるなどをご検討ください。

ジョブv1はそのまましばらく使い続け、v2との結果の差を見てみるといいでしょう。
また、ジョブv1のDatafeedを停止すれば、設定は残したまま動作を停止し、必要に応じてまた再開させることもできます。

以下はアラートルールのクローンを作り、ジョブv2に割り当てる様子です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109197/e483fbfb-3c4d-5b97-e863-46a9f27486d6.png)

以下はv1、v2の両方のアラートルールがアラートをあげた結果です。このように結果の対比が可能です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109197/7b676d0a-521c-4778-6cf1-a4e22fd77b63.png)

# 終わり
このようにMLの異常検知は、変更したり、また複数のパラメータを同時並行で観察するといったこともできます。たくさん増やしすぎるとそれ自体の管理が大変になりますが、試用期間中はうまく使っていくことで複数のパラメータを効率良く試していくことができると思います。