
Hello Autoencoder
最近,身内でDeep Learningを題材に含んだ勉強会を行なっている.
メインは専門である自然言語処理まわりだが, とりあえず実装(というよりnumpy)の導入になる上,結果を視覚化できることから, 画像データを利用したAutoencoderの実装について取り扱った.
軽い説明と共にコードと,色々な結果を
Autoencoder
Autoencoderとは,Neural Networkの特殊系で,基本的には
- 入力層と出力層のユニット数が同じである.
- 教師信号として入力そのものを与える.
という特徴を持つ.
Autoencoderは,入力の情報をを一度隠れ層の空間に写像(encode) したあと, 元の信号を復元(decode)するようなパラメータを学習する.
図のように,もしも隠れ層のユニットが入力層のものよりも少ない場合は, decodeの際,より少ない情報から元の信号を復元する必要がある. そのため,そのようなことが可能なパラメータが学習できれば, Autoencoderは非線形な次元圧縮器とみなすことができる.
具体的な計算式は以下で,パラメータとは \(W_1, W_2, b_1, b_2\).
圧縮された表現(この場合4次元の入力が2次元に圧縮されている)は,元の情報から, 大切な情報だけをうまく抜き出したなんか良い感じのもの
Denoising Autoencoder
Autoencoderの派生系の一つにDenoising Autoencoderがある. 入力にノイズを付与し,そのノイズを取り除くようなencoderを学習しようというもの. 出力層で再構築する対象は,ノイズ付与前の入力なので,Denoising Auroencoderは,
- 入力の情報を保持する良いencoderの学習
に加えて
- 入力に加えられたノイズを除去する
ことも学習しなければならない.
以下の画像のように,N%の画素が欠落ことがノイズに相当する.(教師は常に左のオリジナル)

Autoencoderを複数積み上げるStacked Autoencoderの構成要素にこれを採用することで, かなり性能が上がる .
実装
コードは こちらのGist に. 実行にはnumpy, PILが必要.
最初に,autoencoder.py冒頭のコメントにあるように,MNISTのデータセットをDLする.
これは,28*28の手書き数字画像(0~9)が大量に入ったデータベース. そのためautoencoderの入力,出力次元は784.
可視化
隠れ層の各ユニットにつながる重み(入力画像と同じ次元になる)を可視化 (参考は こちら ).
なので,隠れ層が100だったら,28*28の画像が100枚並んだものが出てくる. 白いと重みの値が大きく,黒いと小さい.
結果
いくつか条件を変えて学習されるパラメータ画像を見る.
感想は,画像を見て個人的に感じたことであって,ちゃんとした考察ではない. (可視化についてちゃんと調べていずれちゃんと書きたい)
Autoencoder

隠れ層が100ユニットで,ノイズ付与なしのAutoencoder
python autoencoder.py 100
Denoising
ノイズの付与率によるパラメータの違い.
結果は以下
- noise 20%
python autoencoder.py 100 -n 0.2
- noise 50%
python autoencoder.py 100 -n 0.5
- noise 80%
python autoencoder.py 100 -n 0.8
ノイズを載せたほうが,載せない( Autoencoder のとこの画像)よりもそれっぽい学習ができている隠れユニットが多い.
80%もノイズをのせると,情報がなさすぎるためか, 答えを丸暗記しているためそのまま数字が浮かび上がってしまっている?過学習? つまり,データに潜む本質的な情報を捉えることを放棄している? (要出展)
Tied vs. Untied weight
decoderとencoderが転置の関係にあるのがTied weight ( \(W_2 = W_1^T\) ).
逆にencoderとdecoderを別々に学習するのがUntied.
どっちが良いかはよくわからない.
とりあえず画像だけ.プログラムではuオプションをつけるとuntiedになる.
- Untied な場合のencoder
- Untied な場合のdecoder
- Tied weightな場合のencoder (転置するとdecoder)
はじめの方はなんとなくuntiedなのの方が良いのかな?と思ってたけど, よく考えたらAutoencoderをStacked autoencoderに組み込む際は,decoderは使用しない. なので,decoderとencoderを別に学習するUntied weightなモデルは無駄が出てしまうかもしれない? (decoderの方が特徴っぽいのが大きく出ているし)
validation.pyについて
最後に,gistについてるvalidation.pyについて. back propagationにおける勾配計算の**コードが正しいか否か**を判別するための方法.j
back propagationはデバッグがしにくいが,これを使うと割と楽.
を勾配の近似とし,計算した勾配の値と比べる. 二つの差分が十分小さくなれば,勾配の計算部分にバグはないという確認ができる.
参考は Gradient checking and advanced optimization など
この項目は最後の最後に書いてないの見つけて急いで書いたので,いずれ詳しくメモを書きたい.
