深度理解變分自編碼器(VAE) | 從入門到精通

語言: CN / TW / HK

前言 本文介紹了深度理解變分自編碼器(VAE)的系列發展及相應的侷限性。

本文轉載自CVHub

作者丨派派星

歡迎關注公眾號CV技術指南,專注於計算機視覺的技術總結、最新技術跟蹤、經典論文解讀、CV招聘資訊。

計算機視覺入門1v3輔導班

導讀

本文是筆者早前寫過的一篇關於 VAE 的讀書筆記,先整理出來分享給大家。作為一名業餘的技(生)術(活)愛(所)好(迫)者,為了不在35歲前被社會淘汰,筆者也只能時不時跟進下最前沿的技術,包括但不僅限於這兩年大火的 AIGC 背後的底層技術——擴散概率模型。這是一類相比於 GAN 更先進的生成模型,由 Sohl-Dickstein 等人於2015年首次提出。然而,真正使其爆火的里程碑應該是 DDPM,即去噪擴散概率模型的出現。因為自 DDPM 面世以來,人們對擴散模型產生了濃厚的興趣,不斷有新的工作湧現出來,併成功的擴充套件到多個領域,包括但不僅限於語音建模、文字到語音、文字到影象以及多變數時間序列預測等等。

作為一個生成模型,擴散模型同樣有許多獨特而有趣的特性。例如,經過訓練的模型能夠輕鬆的執行 inpainting 和 zero-shot denoising 等任務。此外,DDPM 中使用的變分約束突出了與變分自動編碼器和神經壓縮的進一步聯絡。因此,在這篇文章中,我想先從簡單的變分自編碼器講起,後續有時間再單獨出一篇關於擴散模型的討論,通過聯絡不同模型之間的關係,進一步提出關於未來研究的想法。

以下是本文大綱:

一、基礎知識回顧

  1. Latent Variable

  2. Variations

  3. Gaussian Mixture Model

  4. Conditional Probability

  5. KL divergence

  6. Maximum Likelihood Estimate

二、自編碼器

  1. 編解碼器簡述

  2. 從 PCA 開始談起

  3. PCA 到 AE 的轉變

  4. 自編碼器有哪些應用?

  5. 自編碼器的侷限性在哪裡?

三、變分自編碼器

  1. 為什麼要引入 VAE?

  2. VAE 與 AE 的區別?

基礎知識回顧

Latent Variable

latent variable,隱變數或潛在變數,也稱為latent code。

A latent variable is a variable that is inferred using models from observed data.

隱變數是指通過模型從觀測資料中推斷出來的變數。比如,我們將一個輸入物件送入一個神經網路的編碼層(Nerual Network Encoder, NN-Encoder),得到的由隱含層輸出的向量就可以稱作 latent variable。

Variations

Variations,即變分法。在簡述變分之前我們應該瞭解什麼是泛函?回顧下從小到大我們所學習過的函式,它是將一個給定的輸入數值x,經過一系列的變化f(x),從而得到輸出數值y。注意這裡我們輸入的是一個數,輸出的也是一個數。那有沒有這種情況,如果我們的自變數是一個函式而不是一個數值?最經典的問題便是,給定兩個定點A和B,我們從A點可以經過任意一條路徑到達B點,求在什麼樣的路徑下使得A點到B點的時間最短?到這裡大多數人都有答案了——兩點之間直線段最短。像這種輸入變數是一個函式,輸出變數是一個數值的函式,稱為泛函。泛函通俗點理解就是函式的函式。

針對上圖,我門先求出點A(x1, y1)到點B(x2, y2)之間任意路徑長度的表示式。任取一小段微元,根據勾股定理我們可以得出:,其中我們將這條曲線定義為。現在讓我們對函式y進行求導,可以得到:,公式變形下就得到:,我們將其帶入到第一條公式,然後公式左右兩邊同時開方,可以得到:,到這裡我們便求出了一小段微元的長度了。接下來我們只將對x1到x2區間內所有的微元段累加起來便能得到總的路徑長度為:

在上面的式子中, 便是一個泛函。其中被積函式 我們稱為 Lagrange Function,即拉格朗日函式 。現在我們的任務便是要尋找一個合適的函式 使得泛函 的取值最小。

變分法便是用於求泛函數的極值。下面就不展開了,有興趣的可以自行查閱相關資料。這裡主要說一點的就是 VAE 中 V 是怎麼來的,筆者認為應該只是計算的過程中用到了變分法的思想去求解 ,所以就取名叫 VAE。

Gaussian Mixture Model

Gaussian Mixture Model,即高斯混合模型。生成模型比較主流的三個模型為:隱馬爾可夫模型HMM、樸素貝葉斯模型NB和高斯混合模型GMM。這裡我們主要為大家介紹下GMM。

混合模型是一個可以用於表示在總體分佈中含有N個子分佈的概率模型,它表示了觀測資料在總體中的概率分佈。利用混合模型計算總體分佈概率時我們並不需要知道原始觀測資料中子分佈的資訊。

如上所示, 代表圖中黑色的分佈曲線。以前學過《Signal Processing》的人都知道,由 Fourier Theory 可得,任意一個隨時間做週期性變化的波,都可以分解為一系列不同頻率、不同振幅、不同相位的正弦波。同樣地,我們也可以用多個正態分佈的疊加去逼近任意一個分佈。

Conditional Probability

Conditional Probability:條件概率。定義兩個事件A和時間B,求A和B同時發生的概率:

KL divergence

KL divergence:KL散度又稱為KL距離或相對熵,用於衡量兩個概率分佈之間的距離。給定真實分佈 和理論分佈 ,我們將它們之間的KL散度公式定義為:

此外,關於 KL 散度的一些性質如下:

  • KL散度是不對稱的:因為P到Q的距離不等於Q到P的距離,即KL(P||Q)≠KL(Q||P)。這很容易造成model collapse即模式坍縮——模型傾向於生成一些比較容易騙過判別器的樣本,加快模型的收斂,從而導致生成的多樣性變差,生成出來的效果也比較差,相當於走捷徑。

  • 當且僅當兩個分佈完全一致時,KL散度等於0。

Maximum Likelihood Estimate

Maximum Likelihood Estimate,MLE:極大似然估計。要理解什麼是極大似然估計,我們要先理解什麼是“似然”,它同一般的概率事件又有啥區別?給定一個函式 , 代表樣本點, 表示引數:

  • 當 為常量, 為變數時,我們稱 為關於 的概率函式;

  • 當 為常量, 為變數時,我們稱 為關於 的似然函式;

極大似然估計中樣本點的取樣都必須滿足 ,它尋找的是使得樣本點 能夠以最大概率發生的 的取值。

自編碼器

在正式介紹 VAE 之前,我們先簡要介紹下什麼是 AE。

編解碼器簡述

通常,我們都會將輸入圖片送入NN Encoder,得到一個latent code,通常這個latent code的維度是遠小於輸入物件的維度的,它是輸入物件的緊湊表示。接下來,我們將這個latent code送入NN Decoder進行解碼,輸出經過重構過的原始物件。

Auto-Encoder自編碼器是1986年由Rumelhart 提出,可用於高維複雜資料的處理, 它促進了神經網路的發展。自編碼神經網路是一種無監督學習演算法(訓練示例未標註),它使用了BP反向傳播演算法,致力於使輸出與輸入越接近越好。

AE網路一般有兩個特性:

  • dim(Hidden layer) << dim(Input layer),隱層維度應該遠小於輸入的維度;

  • 解碼層的Output用於重構Input,所以我們應該minimizer(Reconstruction error(Input, Output)),即最小化輸入和輸出之間的重構誤差。

AE的演算法描述:

  • Encoder負責將輸入資料進行壓縮,將n維輸入資料通過Hidden layer壓縮成m維的資料(m << n),即通過編碼器學習一組引數,得到一個latent code;

  • Decoder負責還原資料,在需要用到的時候儘可能地以損失最小的方式恢復原始資料。

AE應用範圍一般,但擴充套件能力很強,可以應用於機器學習中的資料降維、特徵抽取和資料視覺化分析等,也可擴充套件並應用於生成模型當中。

從 PCA 開始談起

PCA 和 SVD 本質上也是一種矩陣降維技術。PCA 通過將輸入進行正則化,減去平均值,然後輸入到只有一個 hidden layer 的 NN,得到 latent code,最後再直接解碼回去得到輸出。其主要成分是輸入變數的線性組合,其目標同樣是希望輸出與輸入要越接近越好。

PCA 到 AE 的轉變

簡單的觀察下PCA,我們可以發現,它其實只是用了一個hidden layer去學習簡單的線性變化,學習能力非常有限。學過Neural Network的人大概都知道,網路的學習能力在很大程度上取決於網路的深度和寬度:

  • CNN中標準的block組合無非是一個Conv+BN+ReLU,這是一個標準的非線性變換模組。網路越深,代表非線性對映的能力越powerful,意味著網路可以學習到更加複雜的變化,從而可以更好的擬合輸入的特徵;但是,網路加深到一定程度則會帶來梯度不穩定,造成網路退化的現象,從而導致效能下降。於是,ResNet便出現了,引入殘差對映,可以使梯度更好地回傳,從而使訓練深層網路變得可能。

  • NN中的每一層hidden layer都可以學習到“知識”,比如第一層hidden layer負責編碼諸如點、線、邊緣等淺層資訊;第二層hidden layer編碼簡單點的紋理、形狀等資訊;第三層hidden layer編碼諸如眼睛、鼻子等目標的形狀...,然後逐層學習,不斷地提取抽象的特徵,一氣呵成,最終學會了辨識花草樹木、飛禽走獸等等。

  • 那問題來了,既然網路的深度這麼重要,那增加網路的寬度又有啥作用?這個可以這麼理解,上面一點提到說每一層hidden layer可以學習不同的特徵,舉個例子,比如顏色、方向、紋理這三個。增加網路的寬度意味著同一個hidden layer有著更多的神經元,每一個神經元代表一種顏色,一個方向,一種紋理,組合起來便可以學習到更多不同的顏色資訊,各個不同的方向以及不同頻率的條紋資訊。

總的來說就是,網路越深,能夠學習到更加抽象的高階語義特徵;而網路越寬,則能夠讓每一層的hidden layer學習到更加豐富的特徵表示。所以,沿著這個思路,我們是不是可以將PCA改造下,提升下效能?於是Deep Auto-Encoder便出現了,如下圖所示:

下面我們看下通過增加層數的效果,可以看出由自編碼器Reconstructed過的影象變得更加清晰了:

自編碼器有哪些應用?

Auto-Encoder一般的應有有文字檢索,以圖搜圖,還可用於預訓練。下面以以圖搜圖為例。

直覺上我們想要通過一張圖片,然後去資料庫中尋找跟這張圖片類似的圖片我們會怎麼做?一種直白思路便是計算目標圖片與每一張圖片畫素與畫素之間的距離(如歐式距離)來搜尋圖片,所得到的結果是這樣子的:

可以看出搜尋出來的結果啼笑皆非。下面展示下用AE進行相似圖片搜尋的結果,可以看出搜尋的結果好了很多,但是得到的圖片會比較模糊:

另外,Auto-Encoder還可以用於CNN上,也就是我們常看到的類似U-Net的架構:

自編碼器的侷限性在哪裡?

上面我們通過AE構造出一個比PCA更加清晰的自編碼器模型,但這並不是真正意義上的生成模型。對於一個特定的生成模型,它一般應該滿足以下兩點:

  • 編碼器和解碼器是可以獨立拆分的(類比GAN的Generator和Discriminator)

  • 固定維度下任意取樣出來的編碼,都應該能通過解碼器產生一張清晰且真實的圖片

這裡解釋下第二點。如下圖所示,我們用一張全月圖和一張半月圖去訓練一個AE,經過訓練,模型能夠很好地還原出這兩張圖片。接下來,我們在latent code上中間一點,即兩張圖片編碼點中間處任取一點,將這點交給解碼器進行解碼,直覺上我們會得到一張介於全月圖和半月圖之間的圖片(比如陰影面積覆蓋3/4的樣子)。然而,實際當你那這個點去decode的時候你會發現AE還原出來的圖片不僅模糊而且還是亂碼的。

為什麼會出現這種現象?一個直觀上的解釋是AE的Encoder和Decoder都使用了DNN,DNN是一個非線性的變換過程,因此在latent space上點與點之間transform往往沒有規律可循。

如何解決這個問題呢?一個思想就是引入噪聲,擴大圖片的編碼區域,從而能夠覆蓋到失真的空白編碼區。其實說白了就是通過增加輸入的多樣性從而增強輸出的魯棒性。當我們給輸入圖片進行編碼之前引入一點噪聲,使得每張圖片的編碼點出現在綠色箭頭範圍內,這樣一來所得到的latent space就能覆蓋到更多的編碼點。此時我們再從中間點抽取去還原便可以得到一個我們比較希望得到的輸出,如下所示:

雖然我們為輸入圖片增添了一些噪聲使得latent space能夠覆蓋到比較多的區域,但是還是有不少地方沒有被覆蓋到,比如上圖右邊黃色的部分因為離得比較遠所以就沒編碼到。因此,我們是不是可以嘗試利用更多的噪音,使得對於每一個輸入樣本,它的編碼都能夠覆蓋到整個編碼空間?只不過這裡我們需要保證的是,對於源編碼附近的編碼我們應該給定一個高的概率值,而對於距離原編碼點距離較遠的,我們應該給定一個低的概率值。沒錯,總體來說,我們就是要將原先一個單點拉伸到整個編碼空間,即將離散的編碼點引申為一條連續的接近正態分佈的編碼曲線,如下所示:

到這裡,我們已經不知不覺到來到了 變分自編碼器VAE 的核心思想腹地。下面我們將詳細地敘述VAE的模型架構。

變分自編碼器

為什麼要引入 VAE?

首先,我們先介紹下VAE的模型架構:

在上面我們也介紹過了,VAE就是在原本的AE結構上,給編碼新增合適的噪聲。首先我們將input輸入到NN Encoder,計算出兩組編碼:一組編碼為均值編碼 ,另一組為控制噪聲干擾程度的方差編碼 。方差編碼 主要用來為噪音編碼 分配權重,圖中在為 分配權重之前為方差編碼 套上一層指數運算,只要原因是因為NN學習出來的權重值是有正負值的,所以這是為了保證分配到的權重是正值;最後,我們將原編碼 和經過權重分配後噪聲編碼進行疊加,就得到了新的latent code,然後再送入NN Decoder。觀察上圖可以看出,損失函式這一項除了之前傳統AE的 reconstruction error 以外,還多出了下面一項:

為什麼要加這一個loss?利用反證法的思想我們來推敲一遍——如果不新增這個損失函式,那麼模型為了保證所生成出來的圖片質量越高(因為我們最小化了construction error),那麼編碼器肯定希望噪聲對自身生成的圖片的干擾越小越好,於是分配給噪聲的權重越低越好。如果不加約束限制的話,網路只需要將方差編碼設定為接近負無窮大的值( )即可以消除噪聲帶來的影響。這會帶來一種什麼現象?就是你會發現它訓練得很好,但是往往生成的圖片很差。這樣的話那我們還這麼費勁地引入這個噪聲做啥?

逆向思維思考完,我們再來正面的理解下,為什麼加入這個輔助的loss就有用?公式怎麼得到的先不討論,後面有附錄給你參考。現在我們根據上面給出的公式對 進行求導,可得 ,令其等於0可求出當 處取得極小值,這樣一來便可以約束方差編碼不會一路開掛似的走向負無窮大,相當於起到正則化約束的作用。

從文字上解釋完,我們再從幾何上去觀察下:

這裡指數函式 畫出來就是藍色的曲線,而紅色線條就是 ,於是 就是藍色曲線減去紅色線條,得到的是圖中綠色的曲線,可以顯而易見地看到它的最小值為0。

文字和幾何講完還是理解不了的話,我這裡再舉一個簡單的例子幫助大家理解下:我們可以把VAE正在做的這件事情比作是在參加高考。一般為了能夠真正在考場取得好成績(模型預測),我們在平常的學習生活中需要做各式各樣的測試(模型訓練)。這些測試題一般是由老師佈置給我們,考試難度(方差編碼σ)也應該由老師來定,因為只有這樣我們才能客觀的檢驗我們的學習能力。假如沒有老師監督(輔助loss)的話,而是讓我們(網路)來決定考題的難度(分配給噪聲的權重),那麼我們肯定是偏向於讓測試題難度降到最低(使噪聲影響最小),最好是一點難度(噪聲)都沒有啦,從而能夠考滿分(使最終的重構誤差為0)。因此,為了能夠真正在高考上取得好成績,而不是以這種投機取巧的方式混日子,所以我們必須引入老師(輔助的loss)這個中間人來監督這個課堂測試(訓練過程)的難度。

其次,我們深入理解下VAE的原理:VAE是一種無監督的生成模型,其理論基礎是建立在高斯混合模型之上。

由VAE的模型結構,我們可以看到噪聲編碼 是由一個標準正態分佈所產生的向量,我們對這個分佈隨機取樣 個點,其中 服從多項式分佈 。每取樣一個點 ,我們將其對應到一個高斯分佈 ,於是一個多項式分佈利用混合模型就可以表示為:

這裡,經過以上操作,我們便可以將原先離散的、存在大量失真區域的編碼方式,轉換成連續有效的編碼方式。

既然我們得出了 的表示式,下面我們說下如何求解它。這裡 是已知變數, 是未知的變數,由於 ,所以轉換成求 和 這兩個函式的表示式。

第一步,我們利用NN Decoder來求解 和 ,等價於求出了 ;

第二步,我們利用NN Encoder來求解 ,其中 可以表示任何的分佈。

這裡NN Encoder的作用便是輔助NN Decoder 求解出 ,也是整個VAE演算法的核心。

VAE所需要求解的目標表達式為:,原則上我們希望這個分佈 越大越好,根據最大似然估計法,這等價於:

給定任意一個分佈 ,我們有 ,於是可以推匯出:

上面式子右邊那一項為 和 這兩個分佈的KL散度距離,根據KL散度公式的性質,我們可以知道右邊項恆大於等於0,於是我們找到了 的一個下确界:

這裡,我們將這個下界Lower bound記為:

帶入原式子,可寫成:

有趣的地方來了,原本我們是求使得 最大化的 ,現在轉換成同時求 和 ,是不是很莫名其妙怎麼搞這麼多操作還引入多一個求解變量出來了?下面我們觀察下這個 和 之間的關係:

精髓來了,根據公式 ,當我們固定 時,由於 是固定的,所以 也是固定,那麼 也就固定住了【對應上圖藍色線段】。而根據上面的推導,我們有:

如果此時我們通過調節 ,使得 越來越高,同時KL散度會越來越小。當我們調節到 與 這兩個分佈完全一致時,KL散度就等於0,此時 就完全等價於 .

簡而言之就是,無論 的值如何,我們總能通過調節 使得 等於它,又因為 是 的下确界,所以求解 最終就可以等價為求解: .

從巨集觀角度來看,調節 就是調節NN Decoder;調節 就是調節NN Encoder 於是,VAE模型的演算法便是:Decoder每改進一次,Encoder就調節成跟其一致,並且利用約束項迫使Decoder在訓練的時候“只能前進,不能後退”。

下面繼續求解:

現在又可以將 轉化為求解上式左半部分KL散度的最小值,以及右半部分的最大值,我們將其記為 和 .

先看 ,我們將這個KL散度公式進行展開,得到的其實就是約束項:

至於如何得到的,由於篇幅有限,有興趣的讀者可參考《Auto-Encoding Variational Bayes》中的附錄章節 Appendix B。

再看下 ,我們可以將其表達為:

上面的期望的含義可以表述為:在給定NN Encoder輸出 的情況下解碼器輸出 的值要儘可能地高。如果不考慮方差的話,這其實就類似於一個Auto-Encoder的損失函式。

最後,再讓我們一起來討論下VAE的侷限性。雖然VAE比普通的AE模型訓練出來的效果要好很多,但是訓練過VAE模型的人都知道,它生成出來的圖片相對GANs那種直接利用對抗學習的方式會比較模糊,這是由於它是通過直接計算生成圖片和原始圖片之間的均方誤差,所以得到的是一張“平均影象”。

VAE 與 AE 的區別?

這裡僅列舉三點主要區別:

  • AE中隱層表示的分佈是未知的,而VAE中隱變數是服從正態分佈的;

  • AE中學習的僅僅是NN Encoder和Decoder,而VAE還學習了隱變數的分佈,即高斯分佈的均值和方差;

  • AE只能從1個樣本x,得出對應的重構過的x;而VAE學習了隱變數z所服從的高斯分佈的引數,便可以源源不斷地產生新的z,從而生成新的樣本x。

歡迎關注公眾號CV技術指南,專注於計算機視覺的技術總結、最新技術跟蹤、經典論文解讀、CV招聘資訊。

【技術文件】《從零搭建pytorch模型教程》122頁PDF下載

QQ交流群:444129970。群內有大佬負責解答大家的日常學習、科研、程式碼問題。

模型部署交流群:732145323。用於計算機視覺方面的模型部署、高效能運算、優化加速、技術學習等方面的交流。

其它文章

深度理解變分自編碼器(VAE) | 從入門到精通

計算機視覺入門1v3輔導班

計算機視覺交流群

用於超大影象的訓練策略:Patch Gradient Descent

CV小知識討論與分析(5)到底什麼是Latent Space?

【免費送書活動】關於語義分割的億點思考

新方案:從錯誤中學習,點雲分割中的自我規範化層次語義表示

經典文章:Transformer是如何進軍點雲學習領域的?

CVPR 2023 Workshop | 首個大規模視訊全景分割比賽

如何更好地應對下游小樣本影象資料?不平衡資料集的建模的技巧和策

Transformer交流群

經典文章:Transformer是如何進軍點雲學習領域的?

CVPR 2023 Workshop | 首個大規模視訊全景分割比賽

如何更好地應對下游小樣本影象資料?不平衡資料集的建模的技巧和策

U-Net在2022年相關研究的論文推薦

用少於256KB記憶體實現邊緣訓練,開銷不到PyTorch千分之一

PyTorch 2.0 重磅釋出:一行程式碼提速 30%

Hinton 最新研究:神經網路的未來是前向-前向演算法

聊聊計算機視覺入門

FRNet:上下文感知的特徵強化模組

DAMO-YOLO | 超越所有YOLO,兼顧模型速度與精度

《醫學影象分割》綜述,詳述六大類100多個演算法

如何高效實現矩陣乘?萬文長字帶你從CUDA初學者的角度入門

近似乘法對卷積神經網路的影響

BT-Unet:醫學影象分割的自監督學習框架

語義分割該如何走下去?

輕量級模型設計與部署總結

從CVPR22出發,聊聊CAM是如何啟用我們文章的熱度!

入門必讀系列(十六)經典CNN設計演變的關鍵總結:從VGGNet到EfficientNet

入門必讀系列(十五)神經網路不work的原因總結

入門必讀系列(十四)CV論文常見英語單詞總結

入門必讀系列(十三)高效閱讀論文的方法

入門必讀系列(十二)池化各要點與各方法總結

TensorRT教程(三)TensorRT的安裝教程

TensorRT教程(一)初次介紹TensorRT

TensorRT教程(二)TensorRT進階介紹