Keras AutoEncoder で異常検知をやってみる

今回は温故知新、AutoEncoder をサクッと改造して 初歩的な異常検知をやってみたいと思います。

こんにちは cedro です。

最近、異常検知に興味があって色々やってみているわけですが、画像の異常検知の最も基本的なものと言えばオートエンコーダ ではないでしょうか。

オートエンコーダ(AutoEncoder)とは、入力画像を次元圧縮してから復元させることによって特徴量を学習し、学習後は入力画像とそっくりな画像を出力させるネットワークです。

入力と同じ画像を出力するネットワークなんて意味がないように思えますが、これが異常検知に使えるんです。それから、ノイズ除去メガネ女子のメガネを外すのにも、使えます(笑)。

ということで、今回は温故知新、AutoEncoder をサクッと改造して 初歩的な異常検知をやってみたいと思います。

 

まず、AutoEncoderを動かしてみます

シンプルなオートエンコーダのコードです。MNIST(数字の1〜9)のデータセットを学習し、学習後は入力に1〜9の数字を入れると、それとそっくりな1〜9の数字を出力します。

ネットワークは、入力28×28=784次元を30次元に次元圧縮してから元の28×28=784次元に戻すものです。入力画像と同じ画像を出力させるように学習をさせると、30次元のところで、1〜9の数字の特徴量を重みとして学習するわけです。

 

学習後にテスト画像を入力した結果です。上段がテスト画像、下段が出力画像です。結構忠実に再現出来るものですね。

さて、学習したことがあるものは再現出来るということは、逆に言うと学習したことがないものは再現出来ないわけです。この性質を利用すると異常検知が出来ることは何となく分かると思います。

それでは、正常画像を「1」、異常画像を「9」として、試してみましょう。

 

学習データは「1」のみ、テストデータは「1」と「9」にするために、♯ MNIST データ読み込み  の直後に、このコードを追加します。

なお、データ数が少なくなるので、epoch = 50 → epoch = 300 にしています。これで、コードを実行すると、

 

正常画像「1」はそっくりに再現出来ますが、異常画像「9」は全く再現出来ていません。この違いを定量化するために、テスト画像と出力画像の差を計算してみましょう。

 

入出力の差分画像と差分数値を表示するコードです。♯ サンプル画像表示  のコードの一部を修正・追加しています。

入出力の差分画像は、21行目の diff_img = x_test [ i ] – decoded_imgs [ i ] で、単純に 入力画像ー出力画像で計算しています。

入出力の差分数値は、24行目の diff = np.sum ( np.abs ( x_test [ i ] – decoded_imgs [ i ] )) で、各要素(784個)について入力から出力の引き算をし、その絶対値の総和をとって計算しています。

そして 27-36行目で、差分画像を表示し、その画像の下に差分数値( scoreを表示します。

それでは、これで実行してみます。

 

テスト画像が正常の「1」の場合は、差分画像が全体的に黒っぽくscore は低い値です。逆に、テスト画像が異常の「9」の場合は、差分画像に白っぽい部分が出て来てscore は高い値になります。

では、どれくらいの精度で異常検知が出来そうかをヒストグラムでみてみましょう。

 

テスト画像が「1」の場合と「9」の場合のスコア・ヒストグラムを重ね描きするコードです。このコードを最後に追加して、実行してみます。

 

テスト画像(n=100)が、「1」の場合のスコア・ヒストグラムを赤色、「9」の場合のスコア・ヒストグラムを青色で表示しています。これを見ると、適切な閾値を設定すれば、かなりの精度(98%くらい)で異常検知が出来そうです。

これだけみると、オートエンコーダだけで何でも出来そうですが、これはMNISTという黒字に白で数字を描いた単純なデータセットだから可能なだけで、ちょっと複雑なデータセットになるとこうは行きません。

最後に最終的なコード全体を載せておきます。

では、また。

 

 

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)

ABOUTこの記事をかいた人

2017年8月に、SONY Neural Network Console に一目惚れして、ディープラーニングを始めました。初心者の試行錯誤をブログにしています。