1,WGAN
1.1,從GAN到WGAN,最核心的有這么幾點:
-
GAN的損失函數如下:
\[\min_{G}\max_{D}V\{D,G\}=E_{x\sim{P_{data(x)}}}[logD(x)]+E_{x\sim{P_{z(z)}}}[log(1-D(G(z)))] \tag{0} \]判別器模型前向傳播過程中最后需要加上sigmoid函數,結合nn.BCELoss()得到損失函數。
最優判別器為:
\[D(x)=\frac{P_{r}(x)}{P_r(x)+P_g(x)} \tag{1} \]這個結果從直觀上很容易理解,就是看一個樣本\(x\)來自真實分布和生成分布的可能性的相對比例。如果\(P_{r}(x)=0\)且\(P_{g}(x)\neq{0}\),最優判別器就應該非常自信地給出概率0;如果\(P_{r}(x)=P_{g}(x)\),說明該樣本是真是假的可能性剛好一半一半,此時最優判別器也應該給出概率0.5。
-
判別器最優時,GAN的損失函數由:
\[E_{x\sim{P_{r}}}[logD(x)]+E_{x\sim{P_{g}}}[log(1-D(G(z)))] \tag{2} \]變為
\[E_{x\sim{P_{r}}}[log\frac{P_{r}(x)}{\frac{1}{2}[P_{r}(x)+P_{g}(x)]}]+E_{x\sim{P_{g}}}[log\frac{P_{g}(x)}{\frac{1}{2}[P_{r}(x)+P_{g}(x)]}]-2log2 \tag{3} \]已知KL散度以及JS散度:
\[KL(P_{1}||P_{2})=E_{x\sim{P_{1}}}log\frac{P_{1}}{P_{2}} \tag{4} \]\[JS(P_{1}||P_{2})=\frac{1}{2}KL(P_{1}||\frac{P_1+P_2}{2})+\frac{1}{2}KL(P_{2}||\frac{P_1+P_2}{2}) \tag{5} \]則3式可以寫為
\[2JS(P_{r}||P_{g})-2log2 \tag{6} \]在最優判別器下,原始GAN定義的生成器loss等價變換為最小化真實分布\(P_{r}\)與生成分布\(P_{g}\)之間的JS散度。越訓練判別器,它就越接近最優,最小化生成器的loss也就會越近似於最小化\(P_{r}\)和\(P_{g}\)之間的JS散度。
-
JS散度存在問題
-
我們希望如果兩個分布之間越接近它們的JS散度越小,通過優化JS散度就能將\(P_{g}\)拉向\(P_{r}\),最終以假亂真。
-
這個希望在兩個分布有所重疊的時候是成立的,但是如果兩個分布完全沒有重疊的部分,或者它們重疊的部分可忽略,JS散度固定為常數\(log2\),而這意味着梯度為0。
-
JS散度固定為常數\(log2\)證明如下:
對於任意一個x,只存在四種可能
\[P_1(x)=0~~~~~P_2(x)=0~~~~~就是說樣本x不在P_1中也不在P_2中 \]\[P_1(x)\neq0~~~~~P_2(x)\neq0~~~~~就是說樣本x即在P_1中也在P_2中(在GAN中就意味着生成的樣本中存在樣本與真實數據分不一致) \]\[P_1(x)=0~~~~~P_2(x)\neq0 \]\[P_1(x)\neq0~~~~~P_2(x)=0 \] 在這四種可能中,第一種對JS散度無貢獻,第二種由於重疊部分可以忽略所以貢獻為零,第三種和第四種情況帶入式5可得
\[JS(P_{1}||P_{2})=\frac{1}{2}log\frac{P_{2}}{\frac{1}{2}(0+P_2)}+\frac{1}{2}log\frac{P_{1}}{\frac{1}{2}(P_1+0)}=log2 \] -
-
\(P_{g}\)與\(P_{r}\)不重疊或重疊部分可忽略的可能性非常大(當\(P_{r}\)與\(P_{g}\)的支撐集(support)是高維空間中的低維流形(manifold)時,\(P_{r}\)與\(P_{g}\)重疊部分測度(measure)為0的概率為1。而在數據生成時,\(P_{r}\)與\(P_{g}\)的支撐集是高維空間中的低維流形基本成立,因為生成器一般都是從某個低維(比如100維)的隨機分布中采樣出一個編碼向量,再經過一個神經網絡生成出一個高維樣本(比如64x64的圖片就有4096維)。當生成器的參數固定時,生成樣本的概率分布雖然是定義在4096維的空間上,但它本身所有可能產生的變化已經被那個100維的隨機分布限定了,其本質維度就是100,再考慮到神經網絡帶來的映射降維,最終可能比100還小,所以生成樣本分布的支撐集就在4096維空間中構成一個最多100維的低維流形,“撐不滿”整個高維空間。“撐不滿”就會導致真實分布與生成分布難以“碰到面”,這很容易在二維空間中理解:一方面,二維平面中隨機取兩條曲線,它們之間剛好存在重疊線段的概率為0;另一方面,雖然它們很大可能會存在交叉點,但是相比於兩條曲線而言,交叉點比曲線低一個維度,長度(測度)為0,可忽略。三維空間中也是類似的,隨機取兩個曲面,它們之間最多就是比較有可能存在交叉線,但是交叉線比曲面低一個維度,面積(測度)是0,可忽略。)
-
從其他角度論證梯度的消失:
- \(P_r\)與\(P_g\)之間幾乎不可能有不可忽略的重疊,無論它們之間的“縫隙”多狹小,都肯定存在一個最優分割曲面把它們隔開,最多就是在那些可忽略的重疊處隔不開而已。
- 由於判別器作為一個神經網絡可以無限擬合這個分隔曲面,所以存在一個最優判別器,對幾乎所有真實樣本給出概率1,對幾乎所有生成樣本給出概率0,而那些隔不開的部分就是難以被最優判別器分類的樣本,但是它們的測度為0,可忽略。
- 最優判別器在真實分布和生成分布的支撐集上給出的概率都是常數(1和0),導致生成器的loss梯度為0,梯度消失。
也就是說,在(近似)最優判別器下,最小化生成器的loss等價於最小化\(P_r\)與\(P_g\)之間的JS散度,而由於\(P_r\)與\(P_g\)幾乎不可能有不可忽略的重疊,所以無論它們相距多遠JS散度都是常數\(log2\),最終導致生成器的梯度(近似)為0,梯度消失。
-
-
原始GAN問題的根源可以歸結為兩點
- 等價優化的距離度量(KL散度、JS散度)不合理
- 生成器隨機初始化后的生成分布很難與真實分布有不可忽略的重疊
-
為了解決第二個問題,曾提出加噪聲的方法以將原本的兩個低維流形“彌散”到整個高維空間,強行讓它們產生不可忽略的重疊。
-
WGAN則從第一個問題出發,提出了Wasserstein距離以替代JS散度
Wasserstein距離又叫Earth-Mover(EM)距離,定義如下:
\[W(P_{r},P_{g})=\inf_{\gamma{\sim{\prod(P_{r},P_{g})}}}E_{(x,y)\sim{\gamma}}[||x-y||] \]Wasserstein距離相比KL散度、JS散度的優越性在於,即便兩個分布沒有重疊,Wasserstein距離仍然能夠反映它們的遠近。(關鍵在於由散度/概率度量轉變到了真正的距離)
在實際應用時由於Wasserstein距離定義中的\(\inf_{\gamma{\sim{\prod(P_{r},P_{g})}}}\)無法直接求解,將其變換為如下形式(轉換原理可以看原文:Wasserstein generative adversarial networks.)
\[W(P_{r},P_{g})=\frac{1}{K}\sup_{||f||_{L}\leq{K}}E_{x\sim{P_{r}}}[f(x)]-E_{x\sim{P_{g}}}[f(x)] \]公式的含義是:在要求函數\(f\)的Lipschitz常數\(||f||_L\)(函數導數的最大值)不超過\(K\)的條件下,對所有可能滿足條件的\(f\)取到\(E_{x\sim{P_{r}}}[f(x)]-E_{x\sim{P_{g}}}[f(x)]\)的上界,然后再除以\(K\)。特別的,可以用一組參數\(W\)定義一系列可能的函數\(f_{W}\)(神經網絡),此時損失函數近似為:
\[K\cdot{W(P_{r},P_{g})} \approx \max_{w:|f_{W}|_{L}\leq{K}}E_{x\sim{P_{r}}}[f_{W}(x)]-E_{x\sim{P_{g}}}[f_{W}(x)] \]並且我們其實並不關心\(|f_{W}|_{L}\leq{K}\)這個限制中的\(K\)具體是多少,只要不是正無窮就行,因為它只是會使得梯度變大\(K\)倍,並不會影響梯度的方向,所以作者采取了一個非常簡單的做法,就是限制神經網絡的所有\(f_{W}\)參數\(W\)的不超過某個范圍\([-c,c]\),比如\([-0.01,0.01]\),此時關於輸入樣本\(x\)的導數\(\frac{\partial{f_W}}{\partial{x}}\)也不會超過某個范圍,所以一定存在某個不知道的常數\(K\)使得的局部變動幅度不會超\(f_{W}\)過它,約束條件得以滿足。
-
總結:
-
到此為止,我們可以構造一個含參數\(W\)、最后一層不是非線性激活層的判別器網絡\(f_{W}\),在限制\(W\)不超過某個范圍的條件下,使得\(L=E_{x\sim{P_{r}}}[f_{W}(x)]-E_{x\sim{P_{g}}}[f_{W}(x)]\)盡可能取到最大,此時損失函數\(L\)就會近似真實分布與生成分布之間的Wasserstein距離(忽略常數倍數\(K\))。注意原始GAN的判別器做的是真假二分類任務,所以最后一層是sigmoid,但是現在WGAN中的判別器\(f_{W}\)做的是近似擬合Wasserstein距離,屬於回歸任務,所以要把最后一層的sigmoid拿掉。
-
接下來生成器要近似地最小化Wasserstein距離,即最小化\(L\),由於Wasserstein距離的優良性質,我們不需要擔心生成器梯度消失的問題。再考慮到\(L\)的第一項與生成器無關,就得到了WGAN的兩個loss。
\[-E_{x\sim{P_{g}}}[f_{W}(x)]~~~~~~~~~~~~~~~~生成器loss \]\[E_{x\sim{P_{g}}}[f_{W}(x)]-E_{x\sim{P_{r}}}[f_{W}(x)]~~~~~~~~~~~~~~~~判別器loss \]兩個都是min
-
訓練過程
-
1.2,相較於GAN,WGAN做了以下改進
-
判別器最后一層去掉sigmoid
-
生成器和判別器中的loss不取對數,損失函數如下:
\[W(P_{r},P_{g})=\frac{1}{K}\sup_{||f||_{L}\leq{K}}E_{x\sim{P_{r}}}[f(x)]-E_{x\sim{P_{g}}}[f(x)] \]實際應用時:
\[L(G)=-E_{x\sim{P_{g}}}[D(x)]~~~~~~~~~~~~~~~~生成器loss,相當於~~~~~~~~~~~~~~~~\min_{G}-E_{x\sim{P_{z(z)}}}[-D(G(z))] \]\[L(D)=E_{x\sim{P_{g}}}[D(x)]-E_{x\sim{P_{r}}}[D(x)]~~~~~~~~~~~~~~~~判別器loss,相當於~~~~~~~~~~~~~~~~\min_{D}-E_{x\sim{P_{data(x)}}}D(x)+E_{x\sim{P_{z(z)}}}D(G(z))) \]注意事項:
- 一般來說,Discrimnator比Genenrator訓練的多,比如訓練五次Discrimnator,再訓練一次Genenrator(WGAN論文是這么干的)。
-
每次更新判別器的參數,將其絕對值截斷到不超過一個固定常數c
for p in discriminator.parameters(): p.data.clamp_(clamp_lower, clamp_upper)
-
不要用基於動量的優化方法(momentum,Adam),推薦RMSProp,SGD也行(trick:作者發現如果使用Adam,判別器的loss有時候會崩掉,當它崩掉時,Adam給出的更新方向與梯度方向夾角的cos值就變成負數,更新方向與梯度方向南轅北轍,這意味着判別器的loss梯度是不穩定的,所以不適合用Adam這類基於動量的優化算法。作者改用RMSProp之后,問題就解決了,因為RMSProp適合梯度不穩定的情況。)
2,WGAN-GP
2.1,WGAN直接對權重的值進行約束的方式存在兩個問題
-
Capacity undersure(網絡容量不足)
體現訓練后的網絡只是對簡單函數的近似(其實很容易理解,畢竟將w都限制死了,潛在的可學習到的函數肯定大大受限)
-
Exploding and vanishing gradients(梯度消失和爆炸)
若把clipping threshold設的較小,每經過一個網絡,梯度就會變小,多級之后會成為指數衰減;反之,較大,則會使得指數爆炸.這個平衡區域可能很小。
2.2,改進
為了解決上述問題,WGAN-GP引入了gradient penalty,並將其與WGAN的判別器Loss函數相加構成新的判別器Loss函數:
-
\(\hat{x}\sim{P_{\hat{x}}}\)的獲取方法:\(\tilde{x}\sim{P_g},x\sim{P_r},\epsilon\sim{[0,1]}\Rightarrow{\hat{x}}=\epsilon{\tilde{x}+(1-\epsilon)x}\)
epsilon = torch.rand(real.size(0), 1).expand(real.size()).cuda() realFake = epsilon * real + ((1-epsilon)) * fake
-
Our gradient penalty對梯度直接進行了限制
'''V1''' disResult = discriminator(realFake) gradients = autograd.grad(outputs=disResult, inputs=realFake, grad_outputs=torch.ones(disResult.size()).cuda(), create_graph=True, retain_graph=True, only_inputs=True)[0] gradient_penalty = ((gradients.norm(2, dim=1) - 1) ** 2).mean() '''V2''' disResult = discriminator(realFake) disResult.backward(torch.ones(disResult.size()).cuda()) gradients = realFake.grad gradient_penalty = ((gradients.norm(2, dim=1) - 1) ** 2).mean()
def compute_gradient_penalty(cuda, D, real_samples, fake_samples): Tensor = torch.cuda.FloatTensor if cuda else torch.FloatTensor alpha = Tensor(np.random.random((real_samples.size(0), 1, 1, 1))) interpolates = (alpha * real_samples + ((1 - alpha) * fake_samples)).requires_grad_(True) d_interpolates = D(interpolates) fake = autograd.Variable(Tensor(real_samples.shape[0], 1).fill_(1.0), requires_grad=False) gradients = autograd.grad( outputs=d_interpolates, inputs=interpolates, grad_outputs=fake, create_graph=True, retain_graph=True, only_inputs=True, )[0] gradients = gradients.view(gradients.size(0), -1) gradient_penalty = ((gradients.norm(2, dim=1) -1)**2).mean() return gradient_penalty
-
\(\lambda\)取10(原文中是這么取的)
-
優化算法用的Adam
參考博客:
https://blog.csdn.net/omnispace/article/details/54942668(深度好文,強烈推薦)
https://blog.csdn.net/junbaba_/article/details/106185743
https://www.cnblogs.com/kai-nutshell/p/12968454.html
https://www.cnblogs.com/kai-nutshell/p/12968484.html
3,Cycle-GAN
-
文獻:Unpaired Image-to-Image Translation using Cycle-Consistent Adversarial Networks Jun-Yan
-
概念及定義:
- paired samples(成對樣本)缺失導致的問題:
- 圖像到圖像轉換問題的目標是使用一組對齊的圖像對學習輸入圖像和輸出圖像之間的映射關系;但是在許多任務中,成對的訓練數據是無法獲取的;在沒有配對示例的情況下需要學習的是源域X到目標域Y的轉換方法:捕獲一個域/樣本集合的特殊特征並弄清楚如何將這些特征轉換為另一個域/樣本集合,一種不需要配對樣本的風格轉換方法。
- 使用經典方法優化后的\(G\)可以將域\(X\)轉換為與\(Y\)分布相同的域\(\hat{Y}\),但是並不能確保單獨的輸入和輸出樣本\(x\)和\(y\)是以一種有意義的方式配對的——有無限多種映射\(G\)可以產生相同的分布\(\hat{Y}\),但這些映射針對單獨的輸入\(x\)卻可能產生無限多種\(y\)。此外,模式崩潰問題導致很難孤立地優化對抗性目標,經常發生所有輸入圖像都映射到相同輸出圖像並且優化無法取得進展的現象。
- 循環一致性損失(cycle consistency loss):
- 學習的目標是映射關系:\(G:X\rightarrow{Y}\);而由於該映射是高度約束不足的(hightly under-constrained),將其與逆映射:\(F:Y\rightarrow{X}\)結合起來,引入循環一致性損失推動\(F(G(x))\approx{X}\)以及\(G(F(y))\approx{y}\)。
- paired samples(成對樣本)缺失導致的問題:
-
解決方案
包含兩個關聯的對抗判別器\(D_X\)(用於區分\(x\)和\(F(y)\))和\(D_Y\)(用於區分\(y\)和\(G(x)\)),引入兩個循環一致性損失:
-
前向循環一致性損失:\(x\rightarrow{G(x)}\rightarrow{F(G(x))}\approx{x}\)
-
反向循環一致性損失:\(y\rightarrow{F(y)}\rightarrow{G(F(y))}\approx{y}\)
-
損失函數:
-
判別器損失:
\[L_{GAN}(G,D_Y,X,Y)=E_{y\sim{p_{data}(y)}}[logD_Y(y)]+E_{x\sim{p_{data}(x)}}[log(1-D_Y(G(x)))] \]\[L_{GAN}(F,D_X,X,Y)=E_{x\sim{p_{data}(x)}}[logD_X(x)]+E_{y\sim{p_{data}(y)}}[log(1-D_X(F(y)))] \] -
循環一致性損失:
\[L_{cyc}(G,F)=E_{x\sim{p_{data}(x)}}[||F(G(x))-x||_1]+E_{y\sim{p_{data}(y)}}[||G(F(y))-y||_1] \]
-
-
該模型可以被視為訓練兩個自動編碼器
-
在訓練時,用到了兩個技巧:
-
用最小二乘損失替換負對數似然目標以產生更高質量的結果:
\[L_{LSGAN}(G,D_Y,X,Y)=E_{y\sim{p_{data}(y)}}[(D_Y(y)-1)^2]+E_{x\sim{p_{data}(x)}}[D_Y(G(x))^2] \]\[L_{LSGAN}(F,D_X,X,Y)=E_{x\sim{p_{data}(x)}}[(D_X(x)-1)^2]+E_{y\sim{p_{data}(y)}}[D_X(F(y))^2] \] -
為了減少模型振盪,遵循Shrivastava等人的策略並使用生成圖像的歷史版本而不是最新生成網絡生成的圖像更新鑒別器 DX 和 DY。 為此保留一個圖像緩沖區,用於存儲 50 個先前生成的圖像 。
-
-