轉自:https://blog.csdn.net/ch18328071580/article/details/96690016
概述
1、什么是GAN?
生成對抗網絡簡稱GAN,是由兩個網絡組成的,一個生成器網絡和一個判別器網絡。這兩個網絡可以是神經網絡(從卷積神經網絡、循環神經網絡到自編碼器)。我們之前學習過的機器學習或者神經網絡模型主要能做兩件事:預測和分類,這也是我們所熟知的。那么是否可以讓機器模型自動來生成一張圖片、一段語音?而且可以通過調整不同模型輸入向量來獲得特定的圖片和聲音。例如,可以調整輸入參數,獲得一張紅頭發、藍眼睛的人臉,可以調整輸入參數,得到女性的聲音片段,等等。也就是說,這樣的機器模型能夠根據需求,自動生成我們想要的東西。因此,GAN 應運而生!
2、發展歷史
生成對抗網絡是由Ian Goodfellow等人於2014年在論文《Generative Adversarial Networks》中提出的。學術界公開接受了GAN,業界也歡迎GAN。GAN的崛起是不可避免的。
隨着《Generative Adversarial Networks》提出后,GAN產生了廣泛流行的架構,如DCGAN,StyleGAN,BigGAN,StackGAN,Pix2pix,Age-cGAN,CycleGAN。這些架構展示了非常有前途的結果。而隨着GAN在理論與模型上的高速發展,它在計算機視覺、自然語言處理、人機交互等領域有着越來越深入的應用,並不斷向着其它領域繼續延伸。因此,本文將對GAN的理論與其應用做一個總結與介紹。
一、GAN模型
1、GAN的基本思想
GAN受博弈論中的零和博弈啟發,將生成問題視作判別器和生成器這兩個網絡的對抗和博弈:生成器從給定噪聲中(一般是指均勻分布或者正態分布)產生合成數據,判別器分辨生成器的的輸出和真實數據。前者試圖產生更接近真實的數據,相應地,后者試圖更完美地分辨真實數據與生成數據。由此,兩個網絡在對抗中進步,在進步后繼續對抗,由生成式網絡得的數據也就越來越完美,逼近真實數據,從而可以生成想要得到的數據(圖片、序列、視頻等)。
如果將真實數據和生成數據服從兩個分布,那么如圖所示:
圖中,藍色虛線為判別分布D,黑色許虛線為真實的數據分布 P d a t a P_{data} Pdata,綠色實線為生成分布 P g P_{g} Pg。GAN從概率分布的角度來看,就是通過D來將生成分布推向真實分布,緊接着再優化D,直至到達圖(d)所示,到達Nash均衡點,從而生成分布與真實分布重疊,生成極為接近真實分布的數據。
2、GAN的基本模型
以圖片為例,真實圖片集的分布 P d a t a ( x ) P_{data}{(x)} Pdata(x), x x x 是一個真實圖片,可以想象成一個向量,這個向量集合的分布就是 P d a t a P_{data} Pdata。我們需要生成一些也在這個分布內的圖片,如果直接就是這個分布的話,很難做到。
現在有的 generator 生成的分布可以假設為 P G ( x ; θ ) P_G(x;θ) PG(x;θ),這是一個由 θ θ θ 控制的分布, θ θ θ 是這個分布的參數(如果是高斯混合模型,那么 θ θ θ 就是每個高斯分布的平均值和方差)。
假設在真實分布中取出一些數據, x 1 , x 2 , . . . , x m {x^1, x^2, ... , x^m} x1,x2,...,xm,我們想要計算一個似然 P G ( x i ; θ ) P_G(x^i; θ) PG(xi;θ)。
對於這些數據,在生成模型中的似然就是:
L = ∏ i = 1 m P G ( x i ; θ ) L=\prod _{i=1}^mP_G(x^i;\theta) L=i=1∏mPG(xi;θ)
我們想要最大化這個似然,等價於讓 generator 生成那些真實圖片的概率最大。這就變成了一個最大似然估計的問題了,我們需要找到一個 θ ∗ θ^* θ∗ 來最大化這個似然。
尋找一個 θ* 來最大化這個似然,等價於最大化 log 似然。因為此時這 m 個數據,是從真實分布中取的,所以也就約等於,真實分布中的所有 x 在 P G P_G PG分布中的 log 似然的期望。
真實分布中的所有 x 的期望,等價於求概率積分,所以可以轉化成積分運算,因為減號后面的項和 θ 無關,所以添上之后還是等價的。然后提出共有的項,括號內的反轉,max 變 min,就可以轉化為 KL 散度的形式了,KL 散度描述的是兩個概率分布之間的差異。
所以最大化似然,讓 generator 最大概率的生成真實圖片,也就是要找一個 θ 讓 P G P_G PG更接近於 P d a t a P_{data} Pdata。
那如何來找這個最合理的 θ 呢?
我們可以假設 PG(x; θ) 是一個神經網絡。
首先隨機一個向量 z,通過 G ( z ) = x G(z)=x G(z)=x 這個網絡,生成圖片 x,如何比較兩個分布是否相似呢?
只需要取一組樣本 z,這組 z 符合一個分布,那么通過網絡就可以生成另一個分布 P G P_G PG,然后來比較與真實分布 P d a t a P_{data} Pdata。
神經網絡只要有非線性激活函數,就可以去擬合任意的函數。那么分布也是一樣,所以可以用一個直正態分布,或者高斯分布,取樣去訓練一個神經網絡,學習到一個很復雜的分布。
如何來找到更接近的分布,這就是 GAN 的貢獻了。先給出 GAN 的公式:
這個式子的好處在於,固定 G G G, m a x V ( G , D ) max V(G,D) maxV(G,D) 就表示 P G P_G PG 和 P d a t a P_{data} Pdata 之間的差異。然后要找一個最好的 G G G,讓這個最大值最小,也就是兩個分布之間的差異最小。
表面上看這個的意思是,對於判別器,D 要讓這個式子盡可能的大,也就是對於 x 是真實分布中,D(x) 要接近與 1;對於 x 來自於生成的分布,D(x) 要接近於 0。
對於生成器來說,G 要讓式子盡可能的小,讓來自於生成分布中的 x,需要生成的數據盡量真,D(x) 盡可能的接近 1。
現在我們先固定 G,來求解最優的 D,也就是說,需要D越大越好:
對於一個給定的 x,得到最優的 D 如上,范圍在 (0,1) 內,把最優的 D 帶入
可以得到:
JS 散度 是 KL 散度 的對稱平滑版本,表示了兩個分布之間的差異,這個推導就表明了上面所說的,固定 G。
表示兩個分布之間的差異,最小值是 − 2 l o g 2 -2log2 −2log2,最大值為 0。
現在我們需要找個 G G G,來最小化
觀察上式,當 P G ( x ) = P d a t a ( x ) P_G{(x)}=P_{data}(x) PG(x)=Pdata(x) 時,G 是最優的。
二、 GAN的訓練
有了上面推導的基礎之后,我們就可以開始訓練 GAN 了。結合開頭說的,兩個網絡交替訓練,我們可以在起初有一個 G 0 G_0 G0 和 D 0 D_0 D0,先訓練 D 0 D_0 D0 找到 :
然后固定 D 0 D_0 D0 開始訓練 G 0 G_0 G0, 訓練的過程都可以使用 gradient descent,以此類推,訓練 D 1 D_1 D1, G 1 G_1 G1, D 2 D_2 D2, G 2 G_2 G2,…
但是這里有個問題就是,你可能在 D 0 ∗ D_0^* D0∗ 的位置取到了:
然后更新 G 0 G_0 G0 為 G 1 G_1 G1,可能
但是並不保證會出現一個新的點 D 1 ∗ D_1^* D1∗使得
這樣更新 G 就沒達到它原來應該要的效果,如下圖所示:
避免上述情況的方法就是更新 G 的時候,不要更新 G 太多。
知道了網絡的訓練順序,我們還需要設定兩個 loss function,一個是 D 的 loss,一個是 G 的 loss。下面是整個 GAN 的訓練具體步驟:
上述步驟在機器學習和深度學習中也是非常常見,易於理解。
簡單的來說,就是:
- 給定 G 0 G_0 G0,最大化 V ( G 0 , D ) V(G_0,D) V(G0,D) 以求得 D 0 ∗ D_0^* D0∗,即 m a x [ J S ( P d a t a ( x ) ∣ ∣ P G 0 ( x ) ] max[JS(P_data(x)||P_G0(x)] max[JS(Pdata(x)∣∣PG0(x)];
- 固定 D 0 ∗ D_0^* D0∗,計算 θ G 1 θ_G1 θG1 ← θ G 0 θ_G0 θG0 − η ( d V ( G , D 0 ∗ ) / d θ G ) η(dV(G,D_0^*) /dθ_G) η(dV(G,D0∗)/dθG) 以求得更新后的 G 1 G_1 G1;
- 固定 G 1 G_1 G1,最大化 V ( G 1 , D 0 ∗ ) V(G_1,D_0^*) V(G1,D0∗) 以求得 D 1 ∗ D_1^* D1∗,即 m a x [ J S ( P d a t a ( x ) ∣ ∣ P G 1 ( x ) ] max[JS(P_data(x)||P_G1(x)] max[JS(Pdata(x)∣∣PG1(x)];
- 固定 D 1 ∗ D_1^* D1∗,計算 θ G 2 θ_G2 θG2 ← θ G 1 − η ( d V ( G , D 0 ∗ ) / d θ G ) θ_G1 −η(dV(G,D_0^*) /dθ_G) θG1−η(dV(G,D0∗)/dθG) 以求得更新后的 G 2 G_2 G2;
- 。。。
三、存在的問題
問題一
上面 G 的 loss function 還是有一點小問題,下圖是兩個函數的圖像:
l o g ( 1 − D ( x ) ) log(1-D(x)) log(1−D(x)) 是計算時 G 的損失函數。但是,在 D(x) 接近於 0 的時候,這個函數十分平滑,梯度非常的小。這就會導致,在訓練的初期,G 想要騙過 D,變化十分的緩慢,而上面的函數,趨勢和下面的是一樣的,都是遞減的。但是它的優勢是在 D(x) 接近 0 的時候,梯度很大,有利於訓練,在 D(x) 越來越大之后,梯度減小,這也很符合實際,在初期應該訓練速度更快,到后期速度減慢。
所以我們把 G 的 loss function 修改為:
這樣可以提高訓練的速度。
問題二
還有一個問題,就是經過實驗發現,經過許多次訓練,loss 一直都是平的,也就是:
JS 散度一直都是 l o g 2 log2 log2, P G P_G PG 和 P d a t a P_{data} Pdata 完全沒有交集,但是實際上兩個分布是有交集的,造成這個的原因是因為,我們無法真正計算期望和積分,只能使用 sample 的方法,如果訓練的過擬合了,D 還是能夠完全把兩部分的點分開,如下圖:
對於這個問題,我們是否應該讓 D 變得弱一點,減弱它的分類能力,但是從理論上講,為了讓它能夠有效的區分真假圖片,我們又希望它能夠 powerful,所以這里就產生了矛盾。
還有可能的原因是,雖然兩個分布都是高維的,但是兩個分布都十分的窄,可能交集相當小,這樣也會導致 JS 散度算出來 = l o g 2 =log2 =log2,約等於沒有交集。
解決的一些方法,有添加噪聲,讓兩個分布變得更寬,可能可以增大它們的交集,這樣 JS 散度就可以計算,但是隨着時間變化,噪聲需要逐漸變小。
問題三
還有一個問題叫 Mode Collapse,如下圖:
這個圖的意思是,data 的分布是一個雙峰的,但是學習到的生成分布卻只有單峰,我們可以看到模型學到的數據,但是卻不知道它沒有學到的分布。
造成這個情況的原因是,KL 散度里的兩個分布寫反了
這個圖很清楚的顯示了,如果是第一個 KL 散度的寫法,為了防止出現無窮大,所以有 P d a t a P_{data} Pdata 出現的地方都必須要有 P G P_G PG 覆蓋,就不會出現 Mode Collapse。