What are Autoencoders?

A gentle intro to Autoencoder and its various applications. Also, these tutorials use tf.keras, TensorFlow’s high-level Python API for building and training deep learning models.

Yu-Ru Tsai
Taiwan AI Academy
16 min readMar 9, 2019

--

Overview

常常見到 Autoencoder 的變形以及應用,打算花幾篇的時間好好的研究一下,順便練習 Tensorflow.keras 的 API 使用。

  1. What is Autoencoder
  2. Types of Autoencoder
  3. Application of Autoencoder
  4. Implementation
  5. Great examples
  6. Conclusion

Difficulty: ★ ★ ☆ ☆ ☆

後記: 由於 Tensorflow 2.0 alpha 已於 3/8號釋出,但此篇是在1月底完成的,故大家可以直接使用安裝使用看看,但需要更新至相對應的 CUDA10。

1. What is Autoencoder?

首先,什麼是 Autoencoder 呢? 不囉唆,先看圖吧!

source : Julien Despois

Autoencoder 最原始的概念很簡單,就是丟入一筆 input data 經過類神經網路後也要得到跟 input data一模模一樣樣的 data。首先,整個 Autoencoder 可以拆解成 Encoder 和 Decoder 兩個神經網路。Encoder 先吃進 input data,經過神經網路後壓縮成一個維度較小的向量 Z,接著,在將 Z 輸入 decoder中,將 Z 還原成原始大小。聽起來很容易,但是我們仔細來瞧瞧,這件事情是不是那麼的容易我們就一步一步的分開來看!

source: EvansTsai

Encoder:

Encoder 負責將原始的輸入 Input data,壓縮成成低維向量 C,這個 C,我們通常稱作 code、latent vector 或者特徵向量,但我習慣叫它 latent space,因為 C 表示隱藏的特徵。Encoder 可以將原始 data 可以壓縮成有意義的低維向量,也就表示 Autoencoder 有降維的功能,經過的 hidden layer 擁有非線性轉換的 activation fuction,那麼這個 Encoder 就像是強力版的 PCA,因為 Encoder 能夠做到 non-linear dimension reduction!

Decoder:

Decoder 要做的事情就是將 latent space 盡量地還原回去 input data,是一將低維空間的特徵向量轉換到高維空間中。

那麼怎麼衡量 Autoencoder 的工作狀況呢 !? 很簡單,就是去比較兩個原始的 input data 與 reconstructed data 的相似程度。因此我們的 Loss function 可以寫為….

Loss function:

因為要盡可能縮小兩筆 data 的差異,我們很自然的就使用 mean square error 做為 loss function (但實作上都使用cross_entropy,這個後面的章節再講XDD )。AutoEncoder 的訓練方法跟一般的神經網路一樣,都是用 Backpropagation 去更新權重。

做個小結,Autoencoder是….
1. 很常見到的模型架構,也是常見的 unsupervised learning。
2. 可以做為 non-linear 的 dimension reduction 的一種方法
3. 可以學到 data representation,有代表性的特徵轉換

講到這邊,應該可以很輕鬆的理解,Autoencoder是怎麼樣的的一個東西了,架構很簡單,那再來就來看看他的變形吧!

2. Types of Autoencoder

講解了 AutoEncoder 的基本原理之後,那就可以來看一下 Autoencoder 的延伸進階使用,讓大家看一下 Autoencoder 的廣泛使用!

2–1. Unet:

Unet 可以作為 image segmentation 實作的其中一個手段,而 Unet 的架構也可以看作為 Autoencoder 的變型。但訓練時 input 為一個 image,而 ouput 則是 segmentation 的 mask。

Source: Unet

2–2. Recursive Autoencoders:

這是一個將新的輸入文字結合其他輸入的 latent space的網路,這個網路的目的是情緒分類,而如此這個網路便可以提取不斷輸入的 sparse 文字,找出重要的 latent space。這個也可以看作是 Autoencoder 的變形。

Source: https://www.youtube.com/watch?v=FSKag11y8yI

2–3. Seq2Seq:

Sequence to Sequence 是前陣子很紅的生成式模型 ,它精彩地解決了 RNN 類型無法處理不定長配對的困境,在 chatbot、文字生成等主題上都有很好的表現。而這個也可以看做一種 Autoencoder 的架構。

3. Applications of Autoencoder

看完了千奇百怪的 Autoencoder 變形後,來看看 Autoencoder 還可以在哪些場合使用吧!

3–1. Model pretrained weight

Autoencoder 也可以用於 weight 的 pretrain,pretrain 的意思即為讓模型找到一個較好的起始值。用下圖來舉例,當我們想要完成的目標模型如 target。hidden layer 分別為: [1000, 1000, 500],因此在一開始我們使用autoencoder 的概念輸入784維,中間的 latent space 為 1000 維先去做 pretrain,因此這 1000 維就可以很好的保留住 input 的資訊,接著我們把原本的output拔掉,在接上第二層,以此類推的做下去。這樣子整個模型就會得到一個比較好的起始值。

咦! 有個地方怪怪的…如果你用 1000 neuron 去表示 784 維的 input 的話,不就代表 network 只要全部複製一遍就好了嗎!? 還需要什麼訓練呀 ˋˊ! 沒錯,所以有在像這樣的 pre-train 時,通常我們都會加上 L1 norm 的 regularizer,讓hidden layer 不要全部複製一遍。

source: 李宏毅老師

根據李宏毅老師的說法,在過去比較會使用如此的方法去做 pre-train,現在由於 training skill 的增加,已經不需要使用這種方法了。但是如果你有的 label data 非常少,但卻有一堆的沒 label data 時,你就可以用這樣的方法去做 weight pre-train ,因為 Autoencoder 本身就是一個 unsupervised learning 的方法,我們用沒 label 過的 data 先得到 weight 的 pre-train,再用有 label 的 data 去 fine-tune 權重,如此一來就可以得到不錯的模型。詳細的細節可以再看李老師的影片,講解的很好!

3–2. Image segmentation

剛剛看到的 Unet 模型,我們就再來看看,因為這基本上就是台灣製造業最常見到的 defect detection 的問題。

首先我們要先將 input data label 好,這會是我們的 output,我們要做的事情就是建構一個 network,輸入原始的圖片(左圖,牙齒 X 光照)後,要產生output ( 右圖,牙齒構造分類) 。那在這種 case 上,encoder & decoder 都會是圖形判斷較為強大的 convolution layers,萃取出有意義的特徵,並在 decoder 裡 deconvolution 回去,便可以得到 segmentation 的結果。

source: image segmentation

3–3. Video to Text

像這樣的 image caption 問題,想當然爾的就用到 sequence to sequence 模型拉,input data 是一堆的照片,output 則是描述照片的一段文字,在這邊的sequence to sequence 模型,我們會使用 LSTM + Conv net 當作 encoder & decoder,可以很好的描述一連串的有順序性的動作 & 使用 CNN kernel 來提取 image 中必須要 latent space。但這個 task 用想的就很難,就讓有興趣的大家去試試看摟!

Sequence to Sequence — Video to Text

3–4. Image Retrieval

Image Retrieval 要做的事情就是輸入一張圖片,然後試著去找出最相近的,但若以 pixel-wise 的去比照,那麼其實很容易找到完全不相干的東西,因為機器根本沒有學到特別的特徵,只是一個 pixel 一個 pixel 的去算 loss。若使用 Autoencoder 的方式,先將圖片壓縮到 latent space,再對 image 的 latent space 計算 similarity,那麼出來的結果便會好上許多,因為在 latent space 裡的每一個維度,可能就代表了某種特徵。若在 latent space 上算距離,便很合理的可以找到相似的圖片。尤其這會是一種 unsupervised learning 的方法,不用去 label data ,是個很棒的做法!

在latent space 上,計算距離

以下是著名的 Deep Learning 大神 Georey E. Hinton 提出的論文,左上角的圖示想要搜索的圖,而其他的皆為被 autoencoder 認為很像的圖,的確 autoencoder 似乎能夠看到 input data 的精髓,但也有些抓出來的圖片怪怪的XDD

Using Very Deep Autoencoders for
Content-Based Image Retrieval

3–5. Anomaly Detection

找不到很好的圖片,只好用這張了LOL
尋找 anomalies 也是超級常見的製造業問題,那這個問題也能拿 Autoencoder 來試試看!先來談談實際的 anomalies 的發生狀況,anomaly 發生次數通常都很少,比如說機台的訊號異常,溫度突然飆升……等。這種狀況了不起一個月發生一次(再多應該機器要被強迫退休了),如果每 10 秒都搜集一次 data,那麼每個月會搜集到26萬筆 data,但是卻只有一段時間的資料是 anomalies,那其實這就會是一筆非常 unbalance 的資料。

那麼對於這種狀況,最好的方法就是去拿原有的資料,畢竟那是我們擁有最大量的資料!若我們能將好的資料拿去訓練出一個好的 Autoencoder,這時若有 anomalies 進來,那麼自然地 reconstruct 後的圖形就會壞掉。這便是我們使用 autoencoder 去找出 anomalies 的起始想法!

finding-anomalies

4. Implementation

在此我們使用 Mnist 當作 toy example,並使用 Tensorflow.keras 高階API 實作一個 Autoencoder! 由於 tf.keras 的新套件釋出不久,我們就練習使用文件裡的 Model subclassing 作法實作 autoencoder。

4–1. Create a Model — Vallina_AE:

import Tensorflow

首先先 import tensorflow!

快速的裝好了Tensorflow 2.0 preview (* ̄▽ ̄)/‧☆*”`’*-.,_,.-*’`”*-.,_☆

tf.keras 的使用方法就這麼簡單,打上tf.keras 就是了!(不知所云的一段話lol)

Load data & model preprocess

首先我們先把 Mnist data 從 tf.keras.dataset 拿出來,且做一下preprocess

Nomalize: 將值壓縮到 0 ~ 1之間,訓練會較易收斂

Binarization: 將比較明顯的地方凸顯出來, training 會得到比較好的結果。

Create a Model — Vallina_AE:

這個是 Tensorflow Document 提供的創建模型方法。Subclassing 提供了較靈活的繼承方式,但可能會比較複雜。
我目前看下來的心得是,在__init __的地方,創建 layer,並 define forward pass 在 call 裡面。

因此我們用兩個 sequential model 去分別創建 Encoder & decoder。兩個是一個對稱的結構,encoder 先接上 input layer 負責承接 input data 再接上三個 dense layer。Decoder 一樣,用 input layer 承接 latent space,再使用三個dense layer 做 reconstruction。

再來在 call 下面,我們要將 encoder & decoder 串接起來,首先先定義 latent space 為 self.encoder 的 output,然後 reconstruction 為 通過 decoder 的結果。接著我們使 tf.keras.Model() 將兩個 model 我們在 __init__定義的model 接起來。AE_model = tf.keras.Model(inputs = self.encoder.input, outputs = reconstruction) 指定 input 為 encoder 的 input,output 為 decoder 的 ouput 這樣就 OK 哩!再來就是 return 接起來的 AE_model 就可以摟!

Model Compile & training

Keras 在訓練模型前,必須要先 compile,之後才能丟進去訓練。在 compile 中指定要使用的 optimizer 跟想要計算的 loss。

訓練的話就使用 VallinaAE.fit 把資料餵進去就可以了,但要記得我們是要還原自己,所以 X 跟 Y 要丟入一樣的資料。

我們來看一下訓練了 100 個 epoch 的結果,看起來 reconstruct 的結果並沒有想像中的好。

4–2. Create a Model — Conv_AE:

顧名思義,我們可以使用 Convolution layer 作為 hidden layer 去學習更能夠reconstruct 回去的特徵。模型建立方法也非常的類似,只是我們的 encoder & decoder 架構稍微改變了一下,改成了 Conv layer 跟 max pooling layer。

那改了模型後,可以再來看一下結果,看是不是有進步呢?

看起來 Reconstruction 的結果好非常多,訓練下去大概 10 個 epochs 左右就快速收斂到了非常低的 loss。

4–3. Create a Model — denoise_AE:

另外,autoencoder 也可以實現去雜訊的功能,這邊我們試著製作一個有去噪功能的 denoise-autoencoder!

首先可以先將原始圖片加入 noise,加入 noise 的邏輯為在原始的 pixel 先做一個簡單 shift 之後再加上random的數字。這個當作我們的有 noise 的 input data。Image preprocess 的部份我們可以簡單的做 clip 小於 0 的就為 0,大於1 的就為 1。如下圖,在經過 clip 的影像處理後,我們可以讓圖片變得更銳利,明顯的地方變得更明顯一些。如此一來在丟進 Autoencoder 時可以得到更好的結果。

有無clip的差異

而模型本身跟 Conv_AE 沒有差異,只是在 fit 的時候要改成

denoise_AE.fit(train_images_noise, train_images, epochs=100, batch_size=128, shuffle=True)

要將原始的 noise_data 還原成原始 input data

可以看到,在 Mnist 上,簡單的 Autoencoder 就可以很快速的達到去噪的效果。

5. Great examples

這邊提供一下很好的學習資源給有興趣的人可以繼續參閱

  1. Building Autoencoders in Keras autoencoder系列的實作都寫得很清楚,可以當作入門去看看
  2. Tensorflow 2.0官方文件 tutorial,東西很完整,只是寫的有點難,要花蠻多時間去看的(至少我拉XD)

3. 李宏毅老師的 deep learning 也是非常推薦,講得很清晰易懂,非本科系的也能夠聽得懂的解釋,堪稱 machine learning 界的最紅 youtuber!

6. Conclusion

使用這篇文章快速地向大家建立 Autoencoder 的基本概念,一些 Autoencoder 的變形以及運用場景。簡單的說 Autoencoder 除了最基本的 latent reprsentation 外,還有這麼多的運用

接下來的幾篇會往 generative models 著手,從 autoencoder 的概念延伸,VAE,再到 GAN,還有一路下去的延伸與變形。

喜歡文章的話可以多按幾個 claps(不要只按一次喔) 作為鼓勵!
閱讀本文完整程式碼:https://github.com/EvanstsaiTW/Generative_models/blob/master/AE_01_keras.ipynb

--

--