【一問一答】マヅコの知らない「異常検知」の世界

これから**異常検知を勉強される**初心者、中級者の方のために一問一答集を作ってみました。

実際にあった質問も含まれますが、ほとんどの質問は、私が勉強しながら疑問に思ったことです。

なお、各質問には**私の失敗談**を添えております。皆さんは私のような失敗をしないよう
祈っております(^^)。異常検知に特化した内容となっておりますので、ご了承ください。

#初心者の方向け
##勉強の仕方編
Q：異常検知を勉強したいのですが、何から手をつけて良いのか分かりません。
A：書籍を買って読むのがおススメです。

最初、私はネット情報で勉強していました。しかし、それにも限界があります。
ところが、書籍（[入門　機械学習による異常検知](https://www.amazon.co.jp/%E5%85%A5%E9%96%80-%E6%A9%9F%E6%A2%B0%E5%AD%A6%E7%BF%92%E3%81%AB%E3%82%88%E3%82%8B%E7%95%B0%E5%B8%B8%E6%A4%9C%E7%9F%A5%E2%80%95R%E3%81%AB%E3%82%88%E3%82%8B%E5%AE%9F%E8%B7%B5%E3%82%AC%E3%82%A4%E3%83%89-%E4%BA%95%E6%89%8B-%E5%89%9B/dp/4339024910/ref=sr_1_1?adgrpid=61747762268&dchild=1&gclid=CjwKCAjw_-D3BRBIEiwAjVMy7HE-_3So3C_I64r4iSnaHOw9p5I_ExSjRvJM6sy-p9g7i7MoOaO2nxoCYEwQAvD_BwE&hvadid=338568407423&hvdev=c&hvlocphy=1009404&hvnetw=g&hvqmt=b&hvrand=2852220216720968301&hvtargid=kwd-313180874540&hydadcr=27266_11561146&jp-ad-ap=0&keywords=%E5%85%A5%E9%96%80%E6%A9%9F%E6%A2%B0%E5%AD%A6%E7%BF%92%E3%81%AB%E3%82%88%E3%82%8B%E7%95%B0%E5%B8%B8%E6%A4%9C%E7%9F%A5&qid=1593413287&sr=8-1&tag=googhydr-22)）を買って読んだところ、かなり知識を
得ることができました。最初から、書籍を買っていれば、**一年くらい得することができたのに**...
と思うこともあります（^^；

ただ、こちらの本はディープラーニング系は載っていません。しかし、ディープラーニングに通じる
技術がたくさん載っていますので、ディープラーニング系の異常検知をやる方であっても一読する
ことをおススメします。

「ディープラーニング系の異常検知」の書籍は、今のところ見かけたことはありませんが、[こちら](https://github.com/shinmura0/Python-study-group)で
コードを動かしながら学ぶことができるかもしれません。

##前処理編
Q：スコアが全然出ません。
A：まずは、可視化してみてください。

異常検知に限らず、データ分析全般にいえることですが、データが与えられたとして分析を
いきなり始めるのではなく、可視化するプロセスは必ずやった方が良いです。

これにより、データ分析の難しさをある程度推測することもできますし、思わぬ気付きも
あるかもしれません。あるいは、データ収集の問題点が浮き彫りになることもあります。

多次元で可視化するのが難しければ、t-sneを使えば可視化できます。最近ではUMAPという
速い手法も出てきています。

![ダウンロード (1).png](https://qiita-image-store.s3.amazonaws.com/0/264781/6a0eab25-7291-f6b6-9124-b322bfa1eeb3.png)
[上の例](https://qiita.com/shinmura0/items/cfb51f66b2d172f2403b#%E5%88%86%E5%B8%83%E3%82%92%E7%9C%BA%E3%82%81%E3%82%8B)は、Fashin-MNISTのデータを使ってt-sneで可視化した一例です。

上の例のように、いくらか分布が異なれば「異常検知ができそう！」とか見積ることが
できます。あるいは、完全に分布が分かれれば、あえて機械学習を使う必要がなく、
ルールベースの判定法でも良いかもしれません。「[機械学習をしなくて良い方法を考える](https://www.amazon.co.jp/%E4%BB%95%E4%BA%8B%E3%81%A7%E3%81%AF%E3%81%98%E3%82%81%E3%82%8B%E6%A9%9F%E6%A2%B0%E5%AD%A6%E7%BF%92-%E6%9C%89%E8%B3%80-%E5%BA%B7%E9%A1%95/dp/4873118255/ref=sr_1_fkmr1_1?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&dchild=1&keywords=amazon+%E4%BB%95%E4%BA%8B+%E6%A9%9F%E6%A2%B0%E5%AD%A6%E7%BF%92&qid=1593413554&sr=8-1-fkmr1)」
という考え方も大切です。

「可視化の次は分析！」といきたいところですが、前処理も十二分に検討しましょう。
0-1変換が良いのか、標準化が良いのか、あるいは対数変換を使うのか...

音の分析では、0-1変換→標準化に変更するだけで、AUC（通常0.5～1.0となる、高ければ
高いほど良い）が0.05上がったこともあります（^^；

あるいは、K近傍法など距離ベースの異常検知手法は、スケール（0～1変換）を揃える
必要があります。これを忘れるだけで、精度が数十％降下することもあります。

##手法編
Q：ディープラーニングが**カッコイイから**、とりあえずディープラーニングにデータを突っ込めばいいんでしょう？
A：初手、ディープラーニングはやめた方が良いです。時間が溶けます。

**初手オートエンコーダは非常に有効だと思います。**[オートエンコーダ](https://qiita.com/shinmura0/items/06d81c72601c7578c6d3#2017%E5%B9%B4%E3%82%AA%E3%83%BC%E3%83%88%E3%82%A8%E3%83%B3%E3%82%B3%E3%83%BC%E3%83%80%E3%81%AB%E3%82%88%E3%82%8B%E7%95%B0%E5%B8%B8%E6%A4%9C%E7%9F%A5)は学習も安定していて
ある程度のスコアも保証してくれます。

それ以外のディープラーニング系は調整に時間がかかるため、最後の手段として試した方が良いです。
結論として初手は、[Isolation Forest](https://scikit-learn.org/stable/auto_examples/ensemble/plot_isolation_forest.html#sphx-glr-auto-examples-ensemble-plot-isolation-forest-py)（IF）や[LOF](https://scikit-learn.org/stable/auto_examples/neighbors/plot_lof_novelty_detection.html#sphx-glr-auto-examples-neighbors-plot-lof-novelty-detection-py)（もしくはオートエンコーダ）がおススメです。

実は、ディープラーニングが得意とする画像系のデータであっても、従来からある手法（IFやLOF）を
使うことで、ある程度のスコアを出すこともできます。もちろん、こららの手法はテーブルデータ
（表形式のデータ）でもかなりのスコアを出してくれます。これらの手法の良いところは、パラメータ
調整が少ないところです。また、計算時間の短さもメリットが大きいです。

失敗談として、ディープラーニング系の手法をテーブルデータに適用したお話しです。

今やディープラーニングは、画像系をはじめ**テーブルデータでも**SOTA（スコアが最も高い）を
達成するようになってきました。下の表はテーブルデータにディープラーニング系の異常検知
手法（GOAD）を適用したものです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264781/a30049da-ab6c-ead6-f485-65993d046c67.png)
（表は[Classification-Based Anomaly Detection for General Data](https://arxiv.org/abs/2005.02359)より引用）

しかし、この手法は使ってみると分かるのですが、パラメータ依存性が非常に高く、再現性を
担保することも難しいです。（アフィン変換をランダムに行うのですが、このランダム性が
非常にやっかい）

従って、論文に書いてあるようなスコアを出すためには安定する乱数や、パラメータを見つける
必要があります。さらに、論文では出てこないような調整ノウハウも存在することがあり、
多くの時間が溶ける可能性があります。

使えるコスト・時間・人員を考えて手法を選んだ方が良いです。これらが潤沢にあれば
ディープラーニング系でも良いですし、厳しければIFやLOFを検討しましょう。

##ハードウェア編
Q：エッジ処理で異常検知をしたいです。おススメのハードウェアはありますか？
A：価格ならラズパイ4、使いやすさならJetsonNano、安定性ならPCです。

価格でいうとラズパイ4が圧倒的です。5千円強のお値段でディープラーニングが
ある程度の速度で動きます。[下の例](https://qiita.com/shinmura0/items/a8668cec387e08308209#%E7%95%B0%E5%B8%B8%E9%83%A8%E5%88%86%E3%81%AE%E5%8F%AF%E8%A6%96%E5%8C%96)は異常検知しながら、異常部分を可視化した
例です。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">本当にやりたかったのはコレ！Faster-Grad-CAMで異常部分の可視化。<br><br>〇を正常として学習させました。（余分な線、欠けた線、異物は「異常」です。）リアルタイムで「可視化」と「異常検知」が同時にできるなんて夢のよう...(^^)。 <a href="https://t.co/66BFAc8Efz">pic.twitter.com/66BFAc8Efz</a></p>&mdash; shinmura0 @ 4/11参加者募集中 (@shinmura0) <a href="https://twitter.com/shinmura0/status/1236852805068939266?ref_src=twsrc%5Etfw">March 9, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

なお、このデモはラズパイ3を使ってMobileNetV2を動かしています。
ラズパイ4で動かすと9FPSくらい出ます。

ただ、ラズパイのセットアップは非常に面倒くさいです。最近は@karaage0703 さんが
[こちら](https://karaage.hatenadiary.jp/entry/rpi4-dl-setup)でshellコードを公開してくれているため、非常に楽になっています。

JetsonNanoは使いやすいです。価格は1万円強とすこし高いですが、[JetCard](https://qiita.com/shinmura0/items/08db54d98a7bef93f30d#jetcard%E3%81%A7%E6%A5%BD%E3%80%85%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB)という
非常に使いやすいパッケージを用意してくれているため、すぐに使えるようになります。
速度はラズパイ4より少し速いです。

これらのハードウェアは価格面、サイズの面で非常に優秀です。しかし、電源の安定性や
熱の問題に細心の注意を払わないと、シャットダウンしてしまうことがあります。
従って、どうしてもダウンしてマズイところはPCを使うのが妥当です。

と書いてきましたが、**一番のおススメはやはりラズパイ4です。**価格も優れていますが、
実績もあるハードウェアなので、信頼性もある程度高いです。私の経験では、2か月
工場で作動させっぱなし（中では機械学習が動いていた）にしても、問題なく動き
ました。

#中級者の方向け
##勉強の仕方編
Q：書籍を読んだり、コードを動かしたりしたのですが、飽きました。面白い勉強方法はありませんか？
A：Kaggleなどのコンペに出てみましょう。あるいは、論文を読んでも面白いかもしれません。

コンペに出るのは学びが多いです。メリットは以下のとおりです。

+ 前処理から始まり、コードの管理、手法の検証など一連の作業を学ぶことができる
+ 論文を読む習慣が付く、そして読む速度が速くなる
+ 仮説を考える習慣が身に付く
+ **素晴らしい方とお知り合いになれる**

実は最後が非常に重要で、コンペに出るとライバルと呼べる方と知り合えるかもしれません。
ときには、その方とチームを組みディスカッションや論文の紹介など、非常に貴重な情報交換が
できることもあります。また海外の強い人の動向も知ることができ、英語でディスカッション
することもできます。

一人で勉強していては、ゆっくりとした速度でしか成長できません。やはり、仲間やライバルが
いると**成長する速度は速く**（体感10倍くらい(^^)）、お互いに良い刺激を与えることが
できます。

論文読み単独でも面白いときはありますが、やはり論文を読むのは非常に体力が必要です。
従って、これだけやっていても長続きせず、断続的に読むことになる可能性もあります。
しかし、コンペに出れば締め切りが決まっている分、読む速度も速くなりますし、
モチベーションが上がります。コンペ×論文読みセットがおススメです。

##前処理編
Q：精度が100％になりました。これ以上やることはないですか？
A：念のため、コードに間違いがないか検証しましょう。

仕事やコンペでデータをいじっていて、精度100％が出たら、その結果は**疑ってかかるべきです。**
前処理や後処理でミスしている可能性が高いです。

一番手っ取り早い検証方法は、異常スコアをグラフにするべきです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264781/b73699c2-36a7-031c-700e-ac2a0920cb31.png)

上記は異常スコアの一例です。

スコアがこのように入り乱れていると、ある程度信頼できます。
ところが、スコアが完全に二分されていると、前処理や後処理でミスしている可能性が高いです。

ディープラーニングを使っている場合は、[下記のように](https://qiita.com/shinmura0/items/54585fccbb20cb2879fd)可視化してみて、ちゃんと異常部分を
見ているのか検証してみても良いでしょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264781/361d7bdb-a03a-b38f-e3a7-a876a7e25f8c.png)

私がミスったのは、画像を回転させる前処理を入れたときに、画面の明るさが変わってしまい、
画像の異常部分ではなく、**画像の明るさ**で異常を判定していたときがありました。
一瞬「AUC1.0、ヨッシャー！」となりましたが、幻の結果となりました（^^；

「精度100％は都市伝説」くらいに考えた方が良いです。

##手法編
Q：どうしても精度が伸びません。貪欲に最新手法を試すべきでしょうか？
A：今使っている手法でもう少し粘ってみましょう。

異常検知の分野でも、日々最新手法が登場しています。しかし、それらの手法は精度が少し
改善した報告がほとんどです。これらの論文は再現性が担保されていないものも多く、皆さんが
お持ちのデータに適合するかも不明瞭です。データ数が少ないと性能を発揮しないかもしれません。
つまり、最新手法に変えたからといって、うまくいく可能性は非常に低いです。

2～3年に一度、ブレイクスルーとなるような論文も登場しますが、それはいずれ噂となり、皆さん
の耳にも届いてくると思いますので、最新論文に手を出すのは**しばらく待ちましょう。**
よって、今の手法でもう少し粘るのが時間的に一番有効です。

具体的には、

+ 今の手法でアンサンブル学習してみる
+ 違う手法を混ぜてアンサンブル学習してみる（私の経験では、AUC0.05上がったこともあります。）
+ 学習の仕方を変えてみる。（例えば、[自己教師あり学習の異常データ生成方法を変えてみる](https://qiita.com/shinmura0/items/54585fccbb20cb2879fd)など）

あとは以下のような前処理が効くときがあります。

+ ぼけた画像を破棄する
+ 正常画像を刻んで細かく検査させる
+ 正常データをいくつかのグループに分けて異常検知する

私の経験談として、一年前に[深層距離学習（ArcFace）を使った異常検知](https://qiita.com/shinmura0/items/06d81c72601c7578c6d3)を試しました。
その後、深層距離学習の最新手法をいくつか試しましたが、精度は上がりませんでした。
さらに、深層距離学習以外の手法にも手を出しましたが、精度が上がっても少し、中には
再現しなくて精度が下がったものもありました。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">深層距離学習の最新手法「CircleLoss」を異常検知で使ってみた。<br><br>特長にあった、パラメータのロバスト性・高精度は出なかった(T T)。ただ、前述したように学習速度は異常に速く、エッジ学習で活躍しそう(^^)。<br><br>※データは <a href="https://twitter.com/hashtag/DCASE?src=hash&amp;ref_src=twsrc%5Etfw">#DCASE</a> 2020 Task2 Fan id=0<a href="https://t.co/e8AB5WDTfx">https://t.co/e8AB5WDTfx</a> <a href="https://t.co/4fG0O2hvNf">pic.twitter.com/4fG0O2hvNf</a></p>&mdash; shinmura0 @ 7/11参加者募集中 (@shinmura0) <a href="https://twitter.com/shinmura0/status/1257506785000189954?ref_src=twsrc%5Etfw">May 5, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

つまり、最新手法を試したからといって、精度が劇的に上がることは稀です。
最新手法が出るたびに、それらに手を出していたら、時間が溶けます。

##ハードウェア編
Q：ラズパイで異常検知をして、かつ**極限まで速度を上げたいです。**おススメの手法はありますか？
A：ハードウェアの進化を待つか、職人技（TensorFlow lite）を使いましょう。

ラズパイ4を使えば、モデルのサイズによりますが、10FPSくらいの速度は出ます。
これだけでも非常に使えるシーンはあるかと思います。ただ、それ以上の速度となると
結構険しい道が待っているかもしれません。

[TensorFlow lite](https://qiita.com/terryky/items/243000fcfcb89af11510)はモデルを量子化することで、速度が大体2倍になるらしいです。
「らしい」というのは私が使ったことないためです(^^；。この手のモデル変換は結構
ハマることが多く、時間が溶けることが多いです。私は、OpenVINOというIntel製のモデル変換
技術を使ったことがありますが、かなり難儀しました。結局、@PINTO　さんのお力を借りて
モデルを若干変更することで何とか変換できました。私一人では無理でした。

つまり、量子化などのモデル変換は、使える人が限られています。かなりの職人技です。
高度な知識・経験が要求されます。これらを使いたい人は、上記の記事や@PINTO さんの
[レポジトリ](https://github.com/PINTO0309/PINTO_model_zoo)などを参考にしながらチャレンジしてみてください。

最近、[JETSON XAVIER NX](https://www.nvidia.com/ja-jp/autonomous-machines/embedded-systems/jetson-xavier-nx/)が発売されました。ラズパイ4が登場して1年も経たないうちに
新たなハードウェアが登場したことになります。速度はJetson Nanoの2倍速いという噂も
聞こえてきます。このようにハードウェアの進化は早く、少し待てば高速なハードウェアが
出てくるかもしれません。高速化したいけど、急がない人はハードウェアの進化を待っても
良いかもしれません。

#おわりに
ディープラーニングに対し、かなり懐疑的な内容になってしまいましたが、ディープラーニングは
調整を頑張れば、かなりのスコアを出すことが期待できます。そして、使いこなせるようになると
もはや調整が必要なくなる（**勘所が分かる**）瞬間が来ます。ここまでくると、こっちのものです。

私の場合、[ArcFace+自己教師あり学習](https://qiita.com/shinmura0/items/54585fccbb20cb2879fd)が使い慣れていますが、ArcFace側のパラメータをいじる
ことはありません。いじるところはエポック数くらいです。また、ISやLOFのパラメータ調整
もほとんど行いません。従って、一度お馴染みの手法を確立してしまえば、どんな手法を使うのか
頭を悩ませる時間は無くなります。

一番言いたかったのは、新たな案件が来たとして、未知の手法を使うのではなく、まずは
**使い慣れた手法でとことん粘ってみましょう**ということです。結局、新たな手法を使っても、
使い慣れた手法で粘った方が良いスコアが出ます。手法をころころ変えていると、「データでは
なく、手法を見てる」に過ぎないです。

分析で一番時間をかけているのは、学習のさせ方・前処理の工夫・データのクレンジング・
ドメイン知識の勉強など、データの裏側を探索する作業がほとんどです。そこを頑張れば、
時にはAUCで0.2～0.3くらい底上げすることもできますので、辛抱強くデータを見てください。