VAE(Variational Auto Encoder)で猫が復元できなかった話

はじめに

couseraでBayesian Methods for Machine Learningを受けているんですが、 その中で出てきたVAE(Variational Auto Encoder)で少し試してみたいことがあったのでその実験記録になります。

参考文献

VAEの理論や位置付けについては下記資料が参考になります。

VAEについて

f:id:rmizutaa:20190923122955p:plain

VAEは上図のような構造をもつモデルで、 入力画像の特徴量をEncoderによって低次元の潜在変数に押し込め、その潜在変数を用いて元の画像を復元するというモデルになります。低次元化された潜在変数では入力画像の復元をするのに重要な特徴量のみを抽出できるため、次元削減やノイズ除去に利用されます。また入力と出力の誤差を用いて異常検知にも利用できます。

この構造はAuto encoderと同じなのですが、VAEはこの潜在変数の部分を確率分布としている点が特徴になります。 潜在変数を確率分布とするメリットとしては、ノイズ項があるため同じ入力でも異なる出力となり全く新しい出力を生成できること、潜在変数が連続的な分布であるために、例えばある特徴をもつ出力を生成するために潜在変数を調整できることや、未知の入力に対する挙動も担保できる点が挙げられます。

実験

kaggleのDogs vs. Catsのデータを使って猫画像だけを学習させ、猫以外の画像を異常と検知するようなモデルの作成を目指します。

VAE+CNNの実装がkerasの公式にあるのでこれをベースにします。

上記のリンクのものから入出力やCNNの層の数などを今回のデータに合わせるために少し変更しました。 ネットワークは四段のCNNで構成し、潜在変数の数は256としました。 サンプルサイズはtrainデータは8000、validデータは2000です。 実験環境はgoogle colaboratoryです。

作成したEncoderのネットワークは以下になります。 f:id:rmizutaa:20190923122850p:plain

Decoderのネットワークは以下になります。 f:id:rmizutaa:20190923122913p:plain

ここではコードは割愛しますが、使用したものはこちらになります。

github.com

ある程度学習できたようなので、このモデルの精度を確認するためにいくつか入力画像と出力画像を見比べてみます。 左が入力、右が出力になります。

f:id:rmizutaa:20190923122935p:plain

あまり復元がうまくできていません。輪郭がうっすらわかる程度です。 精度の問題かと思ってネットワークの層の数やパラメータ、潜在変数の数の変更、画像のグレースケール化などを試してみましたが結果に大きな変化はみられませんでした。reconstruction errorで犬画像との差を見ようと思っていたのですが、それ以前の問題でした。

この原因としては、学習画像によるばらつきが大きすぎるのが原因かと考えています。 よくサンプルとして使われるmnistや顔画像のデータセットは画像のどの部分になにがあるかが比較的明確で、画像毎のばらつきが小さいデータセットだと思います。それらと比較すると今回入力として用いた画像は猫のサイズ、位置や向き、背景、猫種など同じ猫でも入力画像毎の違いが大きく、潜在変数の少ないパラメータでは画像の特徴を表し切ることができなかったのかなと思いました。 (とはいえNNはあまり得意でないのでプロがやったらできるのかもしれませんが…)

まとめ

  • VAEで猫画像だけを学習させた異常検知のモデルは作れなかった

  • VAEを正しく使用する際にはネットワークのチューニングや入力画像の選定が必要だと感じた