1. 程式人生 > >VAE(Variational Autoencoder)的原理

VAE(Variational Autoencoder)的原理


Kingma, Diederik P., and Max Welling. "Auto-encoding variational bayes." arXiv preprint arXiv:1312.6114 (2013).

論文的理論推導見:https://zhuanlan.zhihu.com/p/25401928

中文翻譯為:變分自動編碼器

轉自:http://kvfrans.com/variational-autoencoders-explained/

下面是VAE的直觀解釋,不需要太多的數學知識。 

什麼是變分自動編碼器?

為了理解VAE,我們首先從最簡單的網路說起,然後再一步一步新增額外的部分。

 

一個描述神經網路的常見方法是近似一些我們想建模的函式。然而神經網路也可以被看做是攜帶資訊的資料結構。

 

假如我們有一個帶有解卷積層的網路,我們設定輸入為值全為1的向量,輸出為一張影象。然後,我們可以訓練這個網路去減小重構影象和原始影象的平均平方誤差。那麼訓練完後,這個影象的資訊就被保留在了網路的引數中。

 

 

現在,我們嘗試使用更多的圖片。這次我們用one-hot向量而不是全1向量。我們用[1, 0, 0, 0]代表貓,用[0, 1, 0, 0]代表狗。雖然這要沒什麼問題,但是我們最多隻能儲存4張圖片。當然,我們也可以增加向量的長度和網路的引數,那麼我們可以獲得更多的圖片。

 

但是,這樣的向量很稀疏。為了解決這個問題,我們想使用實數值向量而不是0,1向量。我們可認為這種實數值向量是原圖片的一種編碼,這也就引出了編碼/解碼的概念。舉個例子,[3.3, 4.5, 2.1, 9.8]代表貓,[3.4, 2.1, 6.7, 4.2] 代表狗。這個已知的初始向量可以作為我們的潛在變數。

 

如果像我上面一樣,隨機初始化一些向量去代表圖片的編碼,這不是一個很好的辦法,我們更希望計算機能幫我們自動編碼。在autoencoder模型中,我們加入一個編碼器,它能幫我們把圖片編碼成向量。然後解碼器能夠把這些向量恢復成圖片。

 

我們現在獲得了一個有點實際用處的網路了。而且我們現在能訓練任意多的圖片了。如果我們把這些圖片的編碼向量存起來,那以後我們就能通過這些編碼向量來重構我們的影象。我們稱之為標準自編碼器。

 

但是,我們想建一個產生式模型,而不是一個只是儲存圖片的網路。現在我們還不能產生任何未知的東西,因為我們不能隨意產生合理的潛在變數。因為合理的潛在變數都是編碼器從原始圖片中產生的。

 

這裡有個簡單的解決辦法。我們可以對編碼器新增約束,就是強迫它產生服從單位高斯分佈的潛在變數。正是這種約束,把VAE和標準自編碼器給區分開來了。

 

現在,產生新的圖片也變得容易:我們只要從單位高斯分佈中進行取樣,然後把它傳給解碼器就可以了。

 

事實上,我們還需要在重構圖片的精確度和單位高斯分佈的擬合度上進行權衡。

 

我們可以讓網路自己去決定這種權衡。對於我們的損失函式,我們可以把這兩方面進行加和。一方面,是圖片的重構誤差,我們可以用平均平方誤差來度量,另一方面。我們可以用KL散度(KL散度介紹)來度量我們潛在變數的分佈和單位高斯分佈的差異。

 

 

為了優化KL散度,我們需要應用一個簡單的引數重構技巧:不像標準自編碼器那樣產生實數值向量,VAE的編碼器會產生兩個向量:一個是均值向量,一個是標準差向量。

 

 

我們可以這樣來計算KL散度:

# z_mean and z_stddev are two vectors generated by encoder network

latent_loss = 0.5 * tf.reduce_sum(tf.square(z_mean) + tf.square(z_stddev) - tf.log(tf.square(z_stddev)) - 1,1)

 

當我們計算解碼器的loss時,我們就可以從標準差向量中取樣,然後加到我們的均值向量上,就得到了編碼需要的潛在變數。

 

 

VAE除了能讓我們能夠自己產生隨機的潛在變數,這種約束也能提高網路的產生圖片的能力。

 

為了更加形象,我們可以認為潛在變數是一種資料的轉換。

 

我們假設我們有一堆實數在區間[0, 10]上,每個實數對應一個物體名字。比如,5.43對應著蘋果,5.44對應著香蕉。當有個人給你個5.43,你就知道這是代表著蘋果。我們能用這種方法夠編碼無窮多的物體,因為[0, 10]之間的實數有無窮多個。

 

但是,如果某人給你一個實數的時候其實是加了高斯噪聲的呢?比如你接受到了5.43,原始的數值可能是 [4.4 ~ 6.4]之間的任意一個數,真實值可能是5.44(香蕉)。

 

如果給的方差越大,那麼這個平均值向量所攜帶的可用資訊就越少。

 

現在,我們可以把這種邏輯用在編碼器和解碼器上。編碼越有效,那麼標準差向量就越能趨近於標準高斯分佈的單位標準差。

 

這種約束迫使編碼器更加高效,並能夠產生資訊豐富的潛在變數。這也提高了產生圖片的效能。而且我們的潛變數不僅可以隨機產生,也能從未經過訓練的圖片輸入編碼器後產生。

 

VAE的效果:

我做了一些小實驗來測試VAE在MNIST手寫數字資料集上的表現:

 

這裡有一些使用VAE的好處,就是我們可以通過編碼解碼的步驟,直接比較重建圖片和原始圖片的差異,但是GAN做不到。

 

另外,VAE的一個劣勢就是沒有使用對抗網路,所以會更趨向於產生模糊的圖片。

 

這裡也有一些結合VAE和GAN的工作:使用基本的VAE框架,但是用對抗網路去訓練解碼器。更多細節參考:https://arxiv.org/pdf/1512.09300.pdf 和http://blog.otoro.net/2016/04/01/generating-large-images-from-latent-vectors/

 

你可以從這裡獲得一些這篇部落格的程式碼:https://github.com/kvfrans/variational-autoencoder 和一個整理好的版本: https://jmetzen.github.io/2015-11-27/vae.html