AutoEncoder


使用 MNIST and notMNIST 做了一個 AutoEncoder with Fully Connected DNN 的實驗。

依序將實驗結果根據如下步驟顯示出來,程式碼可以參考 [github]

  1. Data Loading and Plotting
  2. AutoEncoder Graph Construction
    a. Define the input output tensors
    b. Define the graph and construct it
    c. Define loss and optimizer
  3. Run Session
  4. Show some reconstructed images
  5. Plot Embeddings
  6. Do Image Generation by Decoder

Data Loading and Plotting

MNIST training data 有 55000 筆資料,是一個 28x28 的 image,值的範圍是 [0~1],因此會對 input 都減去 0.5 正規化。

而 notMNIST 整理過後有 200000 筆,同樣也是 28x28 的 image,但值的範圍已經是 [-0.5~0.5]。值得一提的是,此資料還參雜著一些錯誤,如下圖就可發現,第二列的第二個應為 J,但是標記是 A。因此 notMNIST 相對來說很挑戰,但我們一樣可以看到 AutoEncoder 也會做出一些合理的壓縮。


AutoEncoder Graph Construction

Define the input output tensors

Input x 與 Output y 都是一樣 (沒有要做 Denoise AutoEncoder),其中 code 是建立 Decoder 時的 input tensor。

1
2
3
4
x = tf.placeholder(tf.float32, (None, img_dim))
y = tf.placeholder(tf.float32, (None, img_dim))
embedding_dim = 2
code = tf.placeholder(tf.float32, (None, embedding_dim))

Define the graph and construct it

針對 Encoder 和 Decoder 都使用同一組參數,這樣的好處是參數量直接少約一半,同時減少 overfitting 的機會。當然我們沒有理由一定要將參數綁再一起,可以各自用自己的方法 (參數、模型結構) 去 Encode 和 Decocde。
結構如下:

Define loss and optimizer

注意到 loss 的定義除了原來的影像重建誤差之外,還多了一個 embeddings 的 l2-norm。這是為了希望在 embedding space 上 encode 之後都接近 0,減少那種很大的 outliers 出現。參考李宏毅 Deep AutoEncoder

1
2
3
loss_op = tf.reduce_sum(tf.pow(tf.subtract(reconstruct_auto, y), 2.0)) + l2_weight* tf.reduce_sum(tf.pow(embedded_auto, 2.0))
optimizer = tf.train.AdamOptimizer(learning_rate = rate)
training_op = optimizer.minimize(loss_op)

Run Session

Adam optimizer 跑了 100 個 epochs


Show some reconstructed images

隨機選幾個 MNSIT 的重建圖:

隨機選幾個 notMNSIT 的重建圖:

可以看到 notMNIST 果然難多了。


Plot Embeddings

MNIST 針對所有 training data 求得的 2-d embeddings 如下:

notMNIST 針對所有 training data 求得的 2-d embeddings 如下:

如果只要做到 unsupervised dimension reduction 的話,使用 t-SNE 求得的 embedding 會比上圖都好看很多。但 t-SNE 沒有 Decoder,無法給定一個 embedding 去求回原先的 image。而這種 Encoder - Decoder 結構就相對彈性很多。

t-SNE 的 MNIST 圖如下:


Do Image Generation by Decoder

我們針對 Embedding Space 的一個區域去等距取出很多點,然後使用 Decoder 去 decode 出 image 來。

MNIST 的範圍選擇為, x 軸和 y 軸 [-1~1] 間隔 0.2,共 100 個點。(可參考上面 embedding space 了解選擇的範圍)

notMNIST 的範圍選擇為, x 軸和 y 軸 [-2~2] 間隔 0.2,共 400 個點。(可參考上面 embedding space 了解選擇的範圍)

可以發現 embedding space 的兩個維度具有某些意義在!


Reference

  1. 李宏毅 Deep AutoEncoder
  2. Distill t-SNE
  3. Reducing the Dimensionality of Data with Neural Networks (Hinton 2006)
  4. 本文之 [github]