Open yoheikikuta opened 5 years ago
GAN を使った異常検知の手法が実際のところどれくらい実応用で使えそうなのかが知りたかったので、いくつか調べて比較的新しくて cite もされているこの論文を読んでみることにした。
GAN を使った異常検知は基本的には以下のような問題設定となっている
今回の論文以前に GAN を使った異常検知で有名なものとしては この論文 がある。
これは上で述べたような再構築をどのように実現するかに取り組んだものである。 典型的な GAN は何からしらの潜在変数 z から G(z) によって画像を生成するような G を学習するものだが、異常検知の問題設定では、入力が x であるときにそれに対応する z_x が欲しくて、x と G(z_x) の距離を計算することで異常スコアを計算したい。
ここで挙げている論文では、適当に z を取ってまず G(z) を作り、それと x の誤差から backprop をして G(z') が x に近くなるような z' を求める、ということを指定回数だけ繰り返すことで所望の z_x を求めるということをする。その際には discriminator の情報も使って f(x) と f(G(z)) の距離も計算しており、その線形和が loss になってこれがそのまま異常スコアになるという算段である。
正常なデータであれば十分よい z_x が見つかるはずだが、そもそも分布を知らない異常データではそのような z_x が(比較的)うまく見つけられないだろう、ということで網膜医療画像で実験をして一定度の成果を出している。
ただし当然この方法は一つの予測に対して指定回数 backprop せねばならず、再構築データを作るコストが高い。 この辺を改良しつつ性能を高めるというのが以降の論文の一つのモチベーションになった。
上述の基本的な方向性が分かっていれば今回の論文を理解するのはそこまで難しくはない。 少し複雑だが全体像が以下のようになっている。
実画像をインプットとするモデルとするために autoencoder の仕組みも取り入れた Encoder-Decoder-Encoder の構造をしている。これによって入力画像に対して一回のモデル適用で再構築した画像を作ることができて、上述の計算コストの問題も発生しない。
下段の Conf layer からなる出力を f() とする部分が discriminator になっている。
loss としては以下の三つになっている。
Encoder-Decoder-Encoder の最初の二つの部分が典型的な GAN でいうところの Generator に対応していて、それと Discriminator を adversarial に学習する。
公式実装では https://github.com/samet-akcay/ganomaly/blob/master/lib/model.py#L177-L186 の部分の update_hoge()
の部分ですね。
これで学習したモデルを使って、異常スコアは以下のように定義する。
ここで、G_E は最初の Encoder で、G は Encoder-Decoder-Encoder の最初の Encoder-Decoder 部分で、E は最後の Encoder である(意味を考えればそれはそう)。 あとはこれをテストセット全体で計算して、スコアを [0,1] に正規化して閾値以上を異常画像とする。ちなみに論文では閾値を持ち出していなくて、スコアを使って AUC を計算して評価している。テストセット全体を使って正規化というのはちょっとまあイケてないっすね。
実験はラベル付きの分類問題用のデータを使う。 一つのクラスを異常クラスとして、それ以外を正常クラスとする。正常クラスの一部のみで学習して、残りの正常クラスと異常クラスで予測をして AUC を計算することで評価している。
MNIST と CIFAR10 での結果は以下。 MNIST の 2 とか CIFAR10 の frog のような他のカテゴリと似てないようなものが異常クラスの場合は AUC が高い。一方で 1-7 とか plane に形が似ている bird とかの場合は AUC が低くなったりする。ただし plane はそこまで低くなくて対称性がなかったり 9 が低かったりで、直感的にはちと分からない振る舞い。 そして期待していたよりは良くない。CIFAR10 でこれくらいの性能だと実用的には厳しいかなという印象。
そのほかにも UBA や FFOB といったデータでも実験している。 これらは荷物のX線画像で中に武器が入っているか検出するというような感じのデータらしい。 こちらもこんな感じかぁという結果。
GAN を使った異常検知はなかなか夢がある話だけど、少なくとも複雑で多彩なデータに対しては頑張って annotation をして通常の分類問題に持ち込んだ方が良さそうに思う。工場の部品画像とか病理画像とか、正常なデータのパターンがほぼ固まっていてそこからズレるものを探す、とかなら結構いけるのかもしれない。
正常画像と異常画像のスコア分布や潜在空間での分布を可視化したものが以下。 スコア分布は閾値を決めるのにも使えるが、まあまあ重なってますね(どのデータでの結果なのか書いてないけど)。
最後に再構築した画像がどうなるかを見たものが下図。 赤枠が異常クラスとして設定されたもので、期待としては異常クラスの再構築画像はうまく再構築されないということである。 MNIST は簡単だから全然違いは分からない。モデル的には区別できているということなんだろう。CIFAR10 は ship カテゴリで、まあ確かに他のカテゴリよりはうまく再構築できてないかなという印象。 とはいえ異常スコアはあくまで潜在空間での距離で計算しているのでこの見た目とスコアが直接リンクしているわけではない。再構築画像の距離も入れるとどうなるかという類の実験は特にやられてはいない。
公式レポジトリを動かしてみたけど、スコアが再現しなかったり(自分は PyTorch1.0 でやったので論文と環境は異なるけど)してうーむという感じだった。 最初試した時は動かなかったので直して issue を建てたりもしたが反応は今のところなし。
まあそこまで真面目に使っていくこともなさそうだし、内容は理解したので、今回はここまで。
そういえばタイトルに Semi-Supervised
と入っているが、どの辺りが semi-supervised なのだろうか。
GAN で semi-supervised と言ったら典型的には discriminator の出力が classification のカテゴリとなるようにして学習にカテゴリ情報を使うとかだと思っていたが、GANomaly ではラベル情報は使ってないんだよな。
どういう意味で使うのか知っている人がいたら教えてください。
論文リンク
https://arxiv.org/abs/1805.06725
公開日(yyyy/mm/dd)
2018/05/17
概要
GAN を使った異常検知のモデルで、AutoEncoder 型で Encoder-Decoder-Encoder の構造を取る。 入力画像に対して、画像と潜在空間での特徴量を再構築してその誤差を元に学習もしくは異常スコアを計算するようになっている。 画像を再構築するということは典型的な GAN と異なるところで、従来手法では生成画像を入力画像に近づけるような iterative な処理をして再構築画像を作っていた。これは予測時にも計算負荷が大きいので、入力画像を直接モデルに入れられる AutoEncoder 型にすることで計算負荷を落とした(性能も向上)。 MNIST や CIFAR10 や武器を含む荷物のX線画像などで実験して、従来の GAN を使った手法よりも性能指標や計算負荷の意味で上回っている。 公式実装は こちら 。