はじめに
こんにちは。MLエンジニアの福成毅です。
私は、ある自社プロダクトの要素技術として時系列異常検知モデルの開発に携わってきました(2019/10 〜 2020/03)。 異常検知には今まで取り組んだことがなかったですが、時間をかけて様々なアプローチがあることを学びました。 異常検知は、機械の故障やシステム障害などにおいて発生する異常データを見つけ出す手法であり、様々な産業での応用が期待されています。 一方で教師データ(特に異常データ)の不足や時系列特有の制約など、どうしても難易度が高くなりがちなタスクでもあります。
今回の投稿では、異常検知の基本的な考え方を述べ、時系列異常検知における代表的なタスクの紹介を行います。 何回かに分けて投稿しますので、少し長くなりますが、おつきあい頂ければ幸いです。
基本的な考え方
ここでは異常検知の基本的な考え方について述べていきます。
教師なし学習
異常検知は教師あり学習・教師なし学習どちらでも解くことができますが、 どちらかというと教師なし学習の方がスタンダードなやり方になります。
イメージとしては、まず「正常モデル」のみを作り上げ、 この正常モデルでは「理解」できなかったデータは異常であると考えるということです。
ちなみに正常と異常が選り分けられなくていなくとも、異常データが正常データに比べてごくわずかであれば、異常データがノイズとなるだけで正常モデルを作ることができます(とはいえ正常データのみで正常モデルを作ることがベストではありますが・・・)。
教師あり学習の難しさ
なぜ教師なし学習が異常検知においてスタンダードなのか。 もちろんラベルさえあれば教師あり学習でも行うことは可能ですが、いくつかハードルを乗り越える必要があると思います。
具体的には、以下のようなケースがあると考えられます。
そもそもラベルがない
よくある話です。まだ異常に遭遇していなかったり、異常のパターンが網羅できてなかったりすることが理由として考えられます。 また後に述べますが、正常の定義が変わっていくことでラベルをつけることができないケースも考えられます。
異常データが少なすぎる
そもそも異常は滅多に起こらず(だからこそ「異常」なのですが)、 正常データは十分あるが異常データがほとんど得られないということが考えられます。 このような不均衡データでモデルを作るとどうしても予測が正常に偏りがちになります。
未知の異常に遭遇する可能性が高い
いままで運良く故障しなかった箇所の故障、新手の詐欺・ハッキングetc... 大方我々を待ち受けているのは未知の異常です。これまでの既知の異常でモデルを作ったとしても、未知の異常が得られるたびに、再学習や時には問題設定の変更を強いられることになります。
確率分布による正常モデル
ではその「正常モデル」をどうやって作っていくか。色々方法はあるかと思いますが、よくあるのは、確率分布を考えるアプローチかと思います。 ざっくり説明すると、正常データでヒストグラムを作り、それを滑らかにするイメージです。 ここでの正常データは、異常が含まれていないか、含まれていたとしてもごくわずかであることを前提とします。 ごくわずかであれば含まれていてもよいというのは、わずかであればモデル化の際に無視されるためです。
そして異常かどうか調べたいデータが上記の分布において確率が低いところで観測された場合、 正常とされる中でめったに起こらないことが起こった = 別の分布から発生したのではないか?と疑うことができます。つまり正常ではないということです。どれぐらいの低確率だったら異常とするか = 閾値をどれくらいにするかは調整次第ですが、様々な手法は概ねこの考え方から派生します。
また分布そのもので考えず、統計量で考えることも可能です。例えば、正常データの平均値からの距離が標準偏差×定数倍を超えたら異常とする、といったものです。データが少なすぎてどうしても分布を推定できそうにない時に使える手法です。
時系列データにおける考え方
以降では、時系列データにおける異常検知の考え方について述べていきます。
時系列データは常に一定の状態を取るとは限らず、着目する区間によって正常の意味が変わってきます。 そのため時系列データにおいての異常検知は、"どの時点に対しての"異常であるか?を意識する必要があります。 言い換えると、「ある区間Aのデータを正常な区間と考え、別の区間Bが区間Aに対して異常であるかどうかを調べること」ということになります。 あとは上で挙げた異常検知の考え方と同様に、 区間Aでモデルを作り、区間Bでのデータがそのモデルで「理解できない」とした時に「区間Aに対して区間Bが異常である」と言うことができます。 以降、便宜上この2つの区間を以下のように定義します。
- 正常と仮定した区間A → 参照区間
- 異常かどうかを調べたい区間B → 評価区間
大抵のタスクでは、直近の時系列に対して異常かどうかを判定したい場合が多いので、参照区間と評価区間を隣り合わせにすることがポイントです。 そして下図のようにスライドさせることで、すべての区間で異常かどうかを調べていく、という流れになります。
また私自身経験はしていませんが、もし正常な区間が絶対的に定まるようなタスクの場合は、参照区間を正常な区間に固定し、 評価区間のみをスライドさせることも考えられます。この方法は機械の故障検知などで有効だと思われます。
時系列異常検知のタスク
時系列における異常検知のタスクとしてよく出てくるのは、「外れ値検知」と「変化点検知」この2つかと思います。 字面を見るだけでもなんとなく違いをイメージできるかと思いますが、 先ほど紹介した参照区間と評価区間の枠組みを用いてこれらを説明します。
評価区間を1点にする → 外れ値検知
評価区間を1点とすることで、その1点が異常かどうかを調べることになります。 これが「外れ値検知」とよばれるタスクになります。
そして、外れ値検知はさらに2種類に分けられます。
1つは時系列依存しない外れ値です。つまり、時系列をシャッフルさせても外れ値としてわかるものです。 この場合、値そのものが異常と判断できるので、先ほどの確率分布による正常モデルで考えることができます。 また、閾値を持たせることでルールベースでも検出できます。
もう1つは時系列依存する外れ値です。つまり、時系列をシャッフルさせるとその値が異常であるとわからなくなるようなものです。 このような外れ値の場合はChangeFinderのような時系列予測系のモデルを用いた方がうまく解けます。
評価区間を2点以上とる → 変化点検知
これに対し、評価区間をある程度の長さに取ると、「変化点検知」とよばれるタスクになります。 この場合、評価区間という「カタマリ」単位で異常かどうかが判断されます。
参照区間と評価区間を隣り合わせにしていることが前提で、 評価区間が異常と判断された場合、参照区間と評価区間の間で何かしらの「変化」が生じたということが言え、 これらの区間の境目が「変化点」ということになります。
そしてこちらの変化点検知に対しても、外れ値検知と同様に、時系列依存する場合としない場合に分けることができます。
時系列依存しない場合のアプローチに関して、一番シンプルな方法としては、 参照区間と評価区間の統計量を計算しそれぞれ比較する、といった方法が考えられます。 また、これまでは正常区間のみでモデルを作ることをお話ししてきましたが、 評価区間にも十分データが揃うのであれば、評価区間でもモデルを作ることが可能です。 分布のイメージだと、参照区間と評価区間でそれぞれ分布ができるようなものです。 あとは分布そのもので比較したり、また「密度比推定」と呼ばれる分布の比をダイレクトに求める方法で異常かどうか調べていくことができます。
時系列依存する場合は、外れ値検知と同様に予測モデルを作るアプローチが考えられます。 例えばAutoEncoderの再構成誤差を用いる方法が考えられます。
今回のまとめと次回予定
長くなりましたので今回はここまでです。ポイントを以下にまとめます。
- 異常検知では、明示的な正解ラベルを学習に用いない教師なし学習が主流である。
- 時系列中に2つの区間を設け、その中でモデル化を行いつつ区間をスライドさせるのが基本的な考え方である。
- 区間の長さにより、大きくは外れ値検知・変化点検知に分けられる。
- 両者ともに、時系列依存の有無の観点で分けることも可能である。
次回は、外れ値検知・変化点検知のより具体的なアプローチについて述べていきたいと思います。
参考文献
おわりに
エクサウィザーズは優秀なエンジニア、社会課題を一緒に解決してくれる魔法使い”ウィザーズ”を募集していますので、ご興味を持たれた方はぜひご応募ください。
採用情報|株式会社エクサウィザーズ
ExaWizards Engineer Blogでは、AIなどの技術情報を発信していきます。ぜひフォローをよろしくお願いします!
Linkedinもどしどしフォローお待ちしています!