チラシの裏の設計書

プログラム開発、データ分析からロボット作りまでものづくり全般を思うがままに書き連ねたブログ。

異常検知手法のお勉強記事ができるまで その2

その1の続きです。

 

前回までのお話

ブログのアクセス数推移をネタに異常検知をやってみよう。

ARIMA+回帰で予測して、予測値と実測値の差を評価したら良いんじゃなかろうか。

 

早速実装してみる

データ作成

細かいコードは完結後にQiitaにでも書くとして、やろうとしていることはこういう感じです。まず、アクセス数データと今回考慮すべき休祝日データを引っ付けて準備します。

f:id:stkdev:20180120172314p:plain

こんなイメージ。

もし予測精度を求められるような場合(予測自体が重要な場合とかKaggleやオプトのコンペとか)はここで休祝日以外にもひたすら変数を作り込んだりします。

 

利用データ定義

どのぐらいのデータを使って何日先を予測するか、というのを決めていきます。

1年分とかを学習データにしてしまうとそれだけデータ貯まらないと使えないという応用しづらいロジックになりそうですし、7日分ぐらいで学習したところで一週間前の数値がそのまま出るだけのモデルになりそうです。

ということで1ヶ月分にして見ます。7日周期性が気になるので正確には28日分にしておきます。

予測範囲は次の日でいいですね。

 

余談ですが、予想なんて当然次の日(次の1コマ)が対象だろうと思われるかもしれませんが、ビジネスの現場では「いや翌日の予測値出されてもすぐには使えないので三日後の予測値をピンポイントでくれ」みたいなこともよくあります。

あと「数ヶ月後の予測値出してくれ」と言われてぐぬぬ、、、とか。

 

予測実行してみる

細かいコードは完成後に(略

model <- arima(data.ts[,1], ←時系列のデータ列
 order = c(7,1,7), ←モデルのパラメータ
 method = "ML",
 xreg = data.ts[,2], ←休祝日のデータ列
 seasonal = list(order=c(0,0,0), period=NA))

 R言語の例ですが、関数一発でできちゃうので非常に楽です。

 

f:id:stkdev:20180120175244p:plain

図は実測(黒)&予測(青)のグラフですが、実際には28日分のデータから翌日の点予測して、ズラしてまた予測して、ズラして、というのを繰り返します。

正直、思った以上に予測できてるなぁ、ARIMAすげぇ、という印象。

祝日部分もちゃんと考慮されてるっぽい予測値になっています。

 

異常部分を定義する

さて、予測値が出せたところでどのくらい差があれば異常とみなすかを考えます。

・単純に差をとる

 → アクセスが少ない期間と多い期間があるので閾値が決めにくい

・誤差割合でみる

 → これもその日のアクセス数によってだいぶ意味合いが変わりそう。

標準偏差を利用しよう

 → 予測モデルでは予測値に加えその点での標準偏差σを返してくれます。予測区間とか考えるときに必要なやつ。

 

ということで、時系列モデル難しくて理解が怪しいところも多々ありますが、3σを閾値にすれば1%ぐらいで起こりうる事象に線引きできそうです。

図はさらに閾値絞って、実測値が予測区間7σ以上離れていれば異常としてピックアップしたもの。

f:id:stkdev:20180120183715p:plain

ちょっと拡大率はあれですが、なかなか?良い?ではありませんか?(混乱)

(本音:一発目でここまでできるとは思わなんだ)

 

目に見えてアクセス数が跳ねているところは捉えられていそうです。

面白いのは急激に跳ねている部分の後は多少数値が荒れても異常として検知しない期間があります。学習期間の変動幅がでかくなりすぎて予測区間が広くなったせいでしょう。しかしそれは都合が良い気がします。実際、一度大きく跳ねた後に多少荒れるのは人間の感覚的にも新たな異常ではなく異常が収束する過程と捉えそうな気がします。(全部異常としたいということなら別手法がいるかな)

また、変化度合いが少なくても学習期間部分が一定なら検知されています。いい感じ。

 

あ、あれ?もうこれでよくない?という思いにかられながらも、次回以降もうちょっと頑張ります。

 

おまけというかTODO

時系列モデルは結構難しいので理解が追いついてないところが多いです。

このあたりを参考にどうぞ。

(結構できてないとこある気がするなぁ)

 

https://www.amazon.co.jp/%E7%95%B0%E5%B8%B8%E6%A4%9C%E7%9F%A5%E3%81%A8%E5%A4%89%E5%8C%96%E6%A4%9C%E7%9F%A5-%E6%A9%9F%E6%A2%B0%E5%AD%A6%E7%BF%92%E3%83%97%E3%83%AD%E3%83%95%E3%82%A7%E3%83%83%E3%82%B7%E3%83%A7%E3%83%8A%E3%83%AB%E3%82%B7%E3%83%AA%E3%83%BC%E3%82%BA-%E4%BA%95%E6%89%8B-%E5%89%9B/dp/4061529080

 

異常検知手法のお勉強記事ができるまで その1

前回の続きです。今回から本編。

 

前回までのお話

課題:このアクセスデータから異常っぽいところをいい感じに見つけたいよ。

f:id:stkdev:20180120162121p:plain

なお、黒線は記事投稿タイミング。

 

手法調べる

まずは基礎知識をつけるため、グーグル先生に相談してきます。最近では情報もいっぱいありますし、コード付きで○○検知やってみた系の記事なんかもいっぱいあるのでありがたいです。

ただ、どうしても情報の質はバラバラなので注意が必要ですがその辺の話は置いておいて、参考になった情報を列挙。

www.slideshare.net

 

qiita.com

異常検知の基礎 | データ分析基礎知識

 

この辺りの記事は異常検知に対するアプローチ全般が綺麗にまとまっていて非常にありがたかったです。

 

今回の課題を念頭にスーパーざっくりまとめると

・色々アプローチあるけど、基本となるのは外れ値検出。いかにデータの集合を作るか。

・今回の課題は周期性や変動の顕著な時系列データなのでそのままいろんな手法にぶち込んでもダメそう

 

方針考える、1回目

調べた手法と今回の対象でデータから、どうアプローチするか考えます。1回目としているのは、どうせ一発で良い結果は出ないので試行錯誤する前提だからです。

また、わかりやすい手法で一回分析回してみて結果みて次決めるというのもよくやります。 

考察する

上記Albertさんのページでまさに時系列データに対する異常検知のページがあるので、見ていきます。

・外れ値検出

まず、為替チャートの例で挙げられているk近傍法による外れ値検出ですが、これは近い点との距離をみるもので、今回の課題のような平日と休日で顕著な差があるようなデータに適用してしまうと、平日休日ごとに検知してしまいそうです。

少なくとも曜日変動を除いてからやらないとダメそうです。

・異常部位検出

次に異常部位検出は、なかなか今回の課題に合ってそうです。しかし例では心電図のデータが使われているように周期性のきちっとしたデータに向いているものです。

今回の課題は周期性がきちっとしているように見えて祝日や三が日などを考えると微妙に周期性が異なっています。祝日が毎回検出されてしまいそうです。

・変化点検出

最後に変化点検出の例としてARモデルなどの時系列予測手法を使って、予測と実測の差をみるものが紹介されています。このやり方ですと、休祝日を考慮した時系列モデル+残差というやり方で今回の課題にも適用できそうです。

方針決めた 

まずは時系列予測+その残差を評価する方法にしてみます。

データ全体をみると増加していたり休祝日の影響が半端ないということから記事で挙げられているARモデルだけでは表現しきれないだろうということで、ARIMA+回帰でモデリングしてみることにします。 

さらに参考:

英語苦手であんまり読めてませんがこんな感じ。

ARIMA models with regressors

 

難しそうですが、R言語のライブラリに頼れば大丈夫!

 

・・・。

という感じで一発目の方針決めてるんですが、みんなこんな感じなのかなぁ。

教えて偉い人!

 

〜〜

 

異常検知手法のお勉強記事ができるまで その0

導入(本編が始まらない)

異常検知って結構ニーズあるんですね。

あんまり前書きをだらだら書いてもあれなので端折りますが、異常検知がしたいという要望をここ最近何度か見聞きしているので、来たるべき日に備えて手法周りを勉強しておく日記です。

で、いつもならだいたい形になったところでこのブログやらQiitaやらに書くんですが、今回はあえてまだ完成してない状態で試行錯誤日記を書いて見ることにします。

というのも昔、仕事で予測モデルやらアルゴリズムやらの話をお客さんに説明しているときに「予測モデルがどんなものかというのはなんとなくわかった、でもあなた方がデータの何をどう見て手法選択や組み合わせを作り上げていくのか、そっちの方が興味ある」的なことを言われたことがありまして。

確かにもしかすると手法そのものよりも試行錯誤中の状態の方がブログ記事としてのニーズもあるんじゃないかと思いまして。

なんかここまでの説明だけ見ると、いかにもデータサイエンティストやデータアナリストの人かな?という感じですが、そういう肩書きは1度もついたことのない普通のITエンジニアですので専門家でもなんでもないです、ご了承ください。

でも逆にいうとそんな普通のエンジニアにもこの手のデータサイエンス絡みの仕事が舞い込むぐらいには世の中のAIブームが続いてますなぁ。

 

あー、結局前書き長くなってしまった。

今回のテーマ

どこぞの綺麗なサンプルデータではなくて、ぐっちゃぐちゃの実データが使いたいので自分のQiitaのアクセス数でも使って見ましょう。いい感じに荒れてたと思うので。

本邦初公開。

f:id:stkdev:20180117232630p:plain

2016年から計測始めていて、見ての通り増加傾向があるというのとたまにアクセス数が跳ねることがあります。目に見えて増加している日以外にもなんとなく増えた気がするor減った気がするという日はあります。その辺りが検出できるモデルが作れればいいなぁ、という課題です。

 

異常検知はなかなか正解データというのが定義できないので評価は苦労しそうです。

今回のデータの場合、記事を投稿した日を異常な状態と評価していいかというとそうでもないですし、結局自分の感覚に添うかどうかという判断基準になってしまいそうです。

うーん、この辺りの評価もどうするんだろうなぁ。

まぁ異常と定義する状況が決められるならそれって異常検知できてるしなぁ。

 

と、手法云々に入る前に今日の日記力尽きました。次回に続きます。(たぶん)

 

あ、ちなみにこのブログのアクセス数は↑のグラフの20分の1ぐらいです。

平和でよろしい。

 

〜〜

 

Mac設定メモ再び

年始一発目は何もまとまっていないメモ記事です。

 

中古のMacbook Proをスペックと値段だけに注視して購入した結果、キーボードがUS配列でした。おお、確認してなかった。

 

US配列は別にいやではないんですが、仕事で使ってるPCや他に使っているPCがJIS配列なのでちょっと混乱することもありますが、まぁ慣れようかなと。

 

とはいえちょっと使いづらいところがあるので、キーバインドメモ。

まず装飾キーの変更。

Caps Lock -> Control

Control -> Command

Command -> Esc

買ったのがTouch BarありのタイプでEscの物理キーがなく、仕方なくCommandに割り当て。

 

日本語英語切り替えが「Shift+Ctrl+;」や「Shift+Ctrl+j」となっているのが押しにくいのでCtrl+Spaceで切り替えに変更。

 

追記訂正:デフォルトでもCtrl+Spaceで入力ソースの切り替えできます。自分のMacはいつの間にかCommand+Spaceに変更していたのでこっちがデフォルトかと勘違いしてました。

入力ソース色々入れている場合(Google日本語とか)は目的のに切り替えるのちょっと手間ですが。

 

 

続いて”:”がShift押しながらじゃないと押せないのがvim使うときに不便なので

msrx9.bitbucket.io

こちらの記事を参考に変更。

ついでにVimの設定も使いやすく設定

qiita.com

vimmerじゃないので詳しいことは知らないけど多少Vim使う、というレベルの自分にはこういうまとめはありがたい。

 

US配列の方々はキーバインドとかどう設定してるんですかねぇ。

 

 

最後にご利益がありそうな鳩みくじを引いて見たのでペタっと。

f:id:stkdev:20180107172959p:plain

今年はこの鳩にすがっていきたい。

 

もはやなんの記事かわからない。

コンペ記録メモ まとめ

参加していたコンペ2つが終了しました。

何度かチラシの裏的にメモをとっていたので、そのまとめをしておきます。

レコメンドコンペ

deepanalytics.jp

結果:10位/90人

順位的にはまぁまぁ。

1位のスコアが0.281に対して自分が0.253なので、そこそこスコアはよかった気がします。

が、しかし、問題は自分がほぼレコメンドなアルゴリズムを使わずに終わったというところ。。。

ほぼ、過去見たものを並べただけというアルゴリズム。レコメンドと言えばレコメンドな気もするが、いいのかそれで。

 

引っ越しコンペ

deepanalytics.jp

結果:6位/237人

順位的には満足。賞金には届かなかったけど。

1位とMAEでちょうど1ぐらいの差が付いているのはなかなか興味深い。

こちらはレコメンドコンペの5倍ぐらいは時間かけたが、割と辛いコンペだった。

自分のアルゴリズムとしては、機械学習系ではなく割と古典的な手法を選択。

季節変動や長期間のトレンド変化をモデル化して行き、細かい変動を回帰やRandomForestなんかでちまちまとモデル化。

いわば「現象の説明ができること」に重きを置いたやり方をしていました。

が、それ故に早々に「え、これ学習期間とテスト期間、傾向違いすぎね?」という状態に陥り、結果謎の補正パラメータαやβが登場する始末。一体何をモデル化してるんだろう状態でフィニッシュ。

 

余談:

コンペのスコア上昇にもっとも役に立ったのが、統計知識でも機械学習知識でもなく「実際に最近何度か引越しをした」経験だったため、もしこんな状態でランクインしていたら堂々と「KKD(勘・経験・度胸)で勝つコンペ」とでも題してLTするとこだったんですが、それをするには微妙なスコアかなと。

コンペ記録メモ その3

またチラシの裏なんだ。すまない。

 

このコンペの途中経過メモです。

deepanalytics.jp

徐々に順位を落としていましたが、なんとか盛り返して2位に浮上。

もうこれ以上盛り返せる気がしない。

f:id:stkdev:20171010010559p:plain

 

と、本当にメモだけになってしまうので、コンペにてスコアが上がるきっかけになったものをメモ。そのうちきれいにまとめたい。

 

・結果はちゃんと可視化しよう

 → 分析用プログラムが完成してくると「今回はちょっとパラメータ変えただけだから結果のグラフ化とか省略していいやー」となってしまうことが多いけど、ちゃんと可視化しよう。一部分で過学習起こしてて、直したら結構スコア伸びた。

 

・変数追加すりゃいいってわけでもない

 → 機械学習全盛時代なので「とにかくデータ集めてぶっこめ」となりがちですが、その変数がモデルにどう寄与してて、どこが表現しきれてないかをちゃんと見ていったほうがいい場合も。あと変数増やすことによるデメリットも。

 いやもっと自分に超絶機械学習スキルがあれば、なんでもモデルングができるのかもしれませんが。

 

・勘と経験は強い

 → ここ数年で引越ししまくってるので、いろいろ思い出した。

 

・・・次はちゃんとした日記書こう。

 

コンペ記録メモ その2

今日もチラシの裏メモ。

 

参加中コンペが、もう当分ないであろう好調具合なので記念メモ。パート2。

 

deepanalytics.jp

こちら順調に順位を下げると思いきや踏みとどまって5位キープ中。

f:id:stkdev:20170921000934p:plain

 

飛び入り参加したこちらは順調に順位を上げて9位まで到達。

deepanalytics.jp

f:id:stkdev:20170921001108p:plain

 

いや、皆さんが本気を出してくる終盤戦についていけないのは目に見えてるんですけどね。

 

ただ、両方とも試したい分析手法は実装し切れてないのでがんばる。