LogServiceではじめる時系列分析(教師なしML編)

はじめに

こんにちは。エンジニアの石井です。

前回から1年半ほど経ち、2回目の投稿ととなります。

 

今回はLogServiceで実現できる教師なしMLについて主に扱います。
ほんの一部の説明のみですが、多少なりとも使い方のイメージを掴んでもらえると嬉しいです!

www.alibabacloud.com

 

事前の用意

今回はAR(2)過程、つまりy_t = c + \phi_1 y_{t-1} + \phi_2 y_{t-2} + \epsilonに従う人工データを作成して利用します。*1
何回か生成するので、ここでは生成用の関数を定義しておきます。

gistedaab09029043c429a32c11083c0d6ae

 

また、データのアップロードは大容量データの場合OSSやDataIntegrationを利用すると良いですが、今回は大変軽いデータなので、Pythonから直接アップロードします。
スクリプトサンプルはこんな感じです。(SDK等必要なものは別途インストール済みであるとします)

giste6f8ed6851d7bd49d6afa97e167d6427

 

ちなみに一度にあまり大きいログをこの方法でアップロードするとエラーになるので、分割したり前述した方法を使ってください。

また、LogServiceにLogStoreを作成し、適切なIndexの設定が必要です。
今回の例であれば、以下のように設定しておけば問題ありません。

f:id:sbc_ishii:20200128132134p:plain

 

時系列モデリング

未来の動きを予測したい時

去のデータから先のことを予測したいと思うことはよくあると思います。
LogServiceではAR, ARMA, ARIMAに従うモデリングが可能で、これを用いてこの先に取りうる可能性を見ることができます。

まず、データは以下で生成して、LogService上にアップロードしておきます。

gistba50a3cbde61c1746e682318feb8524d

 

今回はデータの生成過程がわかっているのでAR(2)で10時点先までのデータを予測してみます。
予測するための関数はモデルに寄って色々あるのですが、今回はts_predicate_ar(timestamp(秒), データ, p, nPreds)を用います。
また、LogServiceは暗黙のlimit 100が設定されていますが、今回はデータ数100 + 予測数10なので、limit 110を追加します。

gist5189de9c26cde512ed8fcdb5d2b56b34

f:id:sbc_ishii:20200128132418p:plain

赤い枠がもともとデータが得られていたタイムフレームで、青い線が与えられたデータ、赤い線が予測値です。また、青い枠が純粋な予測の箇所です。

いきなりグラフを見せてしまいましたが、出力のテーブルもみてみましょう。

f:id:sbc_ishii:20200128132449p:plain

なんとなく見た目でわかると思いますが、unixtimeが時刻、srcがもとの値、predictが予測値、upperが上界、lowerが下界です。
anomaly_probは後述します。

異常を検知したい時

一言に異常といっても、外れ値、変化点等色々な異常があります。
ここではLogServiceで実現できる異常検知について見ていきます。

LogServiceの異常検知は教師なし学習により実現されます。
つまり、データが多少なりともあれば、お手軽に異常検知を始めることが出来ます。
データはセンサをつけたり、いろいろな方法を駆使すれば収集できると思いますが、故障などの検知したいイベントは、発生がかなり稀で中々データを集めにくい事が多いと思います。

そのため、一旦は教師データ無しでまずやってみることで、取り掛かりを早くできます。

反面、あくまでその系列データの分布をベースにして判定が行われ、故障と実際のデータの相関を見るわけではないため、検出力や誤検知などでは教師あり学習と比較して精度が落ちる可能性もある点は留意してください。

外れ値の検出

教師なし学習で外れ値の検出はいろいろな方法がありますが、基本的な考え方は「正しいと言える状態を定め」、「そこからデータが逸脱していないか」で判断します。
LogServiceでは、AR, ARMA, ARIMAといった時系列モデルを利用し、そのモデルによる予測値を正しい状態とし、そこからある閾値異常に逸脱する場合に異常であると判断することができます。

例えば、ARを使った外れ値の検出は以下のようになります。

 

gist5189de9c26cde512ed8fcdb5d2b56b34

 

おや?先程の予測のときの呼び出し方と全く同じですね。

そのため、結果も先程と同じとなります(画像も再掲します)

f:id:sbc_ishii:20200128132418p:plain

改めて見返すと、先程は解説しなかった黄色い丸がついている箇所があります。
これが異常ではないか?と検知したポイントになります。

モデルと実際の値を比較して、この値は分布的に異常であろう、という点をアノマリとして通知します。

つまり、あくまで過去データに対して予測を行っており、未来のいつ頃問題が発生するという予測ではないことに注意してください。

改めてテーブル出力を記載します。

f:id:sbc_ishii:20200128135247p:plain

先程解説しなかったanomaly_probが異常の有無を示す列です。
異常であれば1.0, そうでなければ0.0となります。0.5とかのような確率は出てこず、あくまで異常かそうでないかモデルをベースに判断した結果が書かれていると認識してください。

変化点を検出したい

いままでのデータでは変化点らしいところがないので、新たにデータを生成します。

gist5059ec6d2889996f2153bfeabe9c363c

 

変化点の検出は、大まかに言えば、あるwindow内のデータの傾向と次のwindow内のデータの傾向とを比較し、それが大幅に変化していた場合、その点を変化点として捉えるような仕組みです。
LogServiceでは、以下クエリを投げるだけで変化点の検出ができます。

 

gistf349c2685f84779dfd998825a82941c5

f:id:sbc_ishii:20200128132857p:plain

なぜここが?という点も検出されていますが、ちゃんと大きく変化したところは検出されています。

Tips的な話

ここからはやや余談的に、実際に使うときに役に立つ(と主観的に思っている)ことをいくつか書こうと思います。

機械学習関数の結果をサブクエリ内で利用する

機械学習の結果をそのまま使うのではなく、サブクエリ内で操作してから出したいということもあると思います。
そんなときに例えば、以下のようにやるとうまくいきません。

gist3f2e5a9a63731229ad821acd55aa8e2b

上のクエリはあまり意味はないですが、ts_predicate_arの結果にある表からunixtime列とpredict列だけをselectしようとしています。

以下のようにするとうまくいきます。

gistc9d3a24b3b5ab72379695ffb5ef51ff7

ポイントは、結果の部分にasで名前をつけるところと、unnest(p) as t(preds)です。
最終的にt(名前)で指定した名前でもとのデータにアクセスできるようになりますが、列名ではアクセスできないので、インデックスでアクセスします。
普通のプログラミング言語だと配列の添字は0からですが、logserviceでは1から始まるので注意してください。

クエリを発行した時刻から直近n時間分のデータを分析対象にしたい

LogServiceの場合、データの時刻の扱いが主に2つあって、1つはlogserviceに到着した時間で__time__フィールドに格納されます。
LogServiceは基本的に全データを対象にクエリを書くことはなく、この到着時間で絞った上でクエリを書きます。
ストリームのデータだと、エラーなどの問題でデータ生成と(ほぼ)同時にデータが到着していない可能性もあるため、まずこの点の絞り込みをどういったポリシーでやるかは十分に検討する必要があります。

その上で、クエリ上で直近n時間分だけのデータを取り出す場合は以下の様に書きます。
timestampにはデータ生成のタイムスタンプが入っていると仮定します。

gist469702cd61f45abbf35efd915f8616e1

localtimestampには現在時刻が入っていますので、to_unixtimeでユニックス時刻に変換してから比較します。

 

おわりに

今回はLogServiceのML関数とよく使いそうなTipsを少しだけ紹介しました。

時系列データの分析で異常検知のシナリオは比較的よくあると思うのですが、一方でデータが溜まっていても異常の状態をラベル付け出来ていないということもよくあると思います。

そんなときに、まずはLogServiceにデータを貯めて教師なし機械学習を適用しながら、異常のラベルを貯めていくことで、より高度なデータ活用が可能となります。

本記事では触れていませんが、LogServiceのデータをAlibabaCloudの各プロダクトと連携することはもちろん可能で、例えば機械学習プラットフォームであるPAIにデータをもっていき、データが溜まったところで個別のモデルを作り込むといったことも可能です。

いきなり高度なことをやろうとしても躓いてしまうことも多いですので、そういった課題のある方は、まずはLogServiceで簡単に時系列データの処理に取り組んでみてはいかがでしょうか。