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

[work] VAE(Variational Autoencoder)的原理

本篇部落格轉載自: 
VAE(Variational Autoencoder)的原理 
OpenAI實習生講解變分自編碼機


以上兩篇文章翻譯自Kevin Frans的英文部落格.

英文原文:Variational Autoencoders Explained

論文連結:Auto-encoding variational bayes

論文的理論推導:變分自編碼器(VAEs)

以下為正文


我曾經講解過一次生成式對抗網路(GAN),談的是用它來生成逼真影象的一個簡單例子。

但這中間有些問題,即單純使用GAN存在兩大不利因素。

首先,這裡的影象生成自某些隨機的噪點。如果你想生成的是一張特定細節的影象,除了遍歷初始噪點的整個分佈範圍,你沒有別的辦法來找出它們的值。

其次,生成式對抗模型只能區分出影象的“真”、“假”。你沒有辦法強制它所生成貓圖必須看起來像貓。這就造成了一個問題,就是它所生成的影象不是參照真實的物體,而是參照的他們在圖片中的樣子,風格上不會特別寫實。

如何解決這兩個問題呢?

我會在本文中介紹另一種神經網路——變分自編碼機,來解決這兩個問題。

什麼是變分自編碼機?

為了理解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)
  • 1
  • 2
  • 3

當我們計算解碼器的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的研究工作:採用相同的 編碼器-解碼器 配置,但使用對抗網路來訓練解碼器。

更多細節可以參考以下的論文和部落格: 
Autoencoding beyond pixels using a learned similarity metric 
Generating Large Images from Latent Vectors

你也可以從這裡獲得這篇部落格的程式碼,這是原始的程式碼