# 李宏毅_ATDL_Lecture_14 ###### tags: `Hung-yi Lee` `NTU` `Advance Topics in Deep Learning` [課程撥放清單](https://www.youtube.com/channel/UC2ggjtuuWvxrHHHiaDH1dlQ/playlists) ## Generative Adversarial Network [課程連結](https://www.youtube.com/watch?v=0CKeqXl5IY0&list=PLJV_el3uVTsPMxPbjeX7PicgWbY7F8wW9&index=14) ### NIPS 2016 Tutorial: Generative Adversarial Networks ![](https://i.imgur.com/uiqye5b.png) [Video_Youtube](https://www.youtube.com/watch?v=HGYYEUSm-0Q) ### Review: Generation ![](https://i.imgur.com/Bq9M8iH.png) GAN首先談生成,Generation,給機器看唐詩來產生詩,或是看動漫來產生圖。 ### Review: Auto-encoder ![](https://i.imgur.com/4c7oz8p.png) 要生成資料可以利用Auto-encoder,利用`nn`來壓縮,再利用`nn`來解壓,而我們希望輸入與輸出愈接近愈好。 訓練好`nn`之後,後段的`Decoder`就可以拿來做生成器使用。 ### Review: Auto-encoder ![](https://i.imgur.com/2uIwInR.png) 上圖是實際案例,在不同的向量中取值得到不同的輸出結果。 ### Review: Auto-encoder ![](https://i.imgur.com/YdTTjz7.png) 在橫縱軸等距取值來看的話可以看的到數值的變化: * 由左至右是圈到豎的變化 * 由上至下是角度的變化 ### Review: VAE Auto-encoder ![](https://i.imgur.com/4RITZyB.png) 標準的Auto-encoder不適合當做生成器使用,如果要做為生成器,會建議使用VAE<sub>(Variational Auto Encoder)</sub>: 1. 產生一個3維Vector-$m$ 2. 產生一個3維Vector-$\sigma$ 3. 從正態分佈中隨機產生一個3維Vector-$e$ 4. $\sigma$取Exponential(轉正值)乘上噪點-$e$再加上$m$得到$c$ 5. ~~Minimize reconstruction error~~ 6. $\sum_{i=1}^3(exp(\sigma_i)-(1+\sigma_i)+(m_i)^2)$ 只有第5點的最佳化是不夠,原因在於$\sigma$也是一個噪點,它會干擾decoer做reconstruction,如果我們只是要輸入跟輸出接近的話,那最後可能就是學到$\sigma$為零,因此會以第6點的方式最佳化。 更詳細的說明可以參考之前課程: * [ML Lecture 17: Unsupervised Learning - Deep Generative Model (Part I)](https://hackmd.io/s/Hyl2f_mCm) * [ML Lecture 18: Unsupervised Learning - Deep Generative Model (Part II)](https://hackmd.io/s/SJIBK8s0m) ### Problems of VAE ![](https://i.imgur.com/iSdzG1L.png) VAE的一個問題,我們並不是真的要利用VAE去學習產生一張照片,而是要輸入跟輸出愈接近愈好,意思是它所輸出的照片跟輸入照片是否接近與『人』覺得它是不是真的是不一樣的事情。 上圖可以看到,左、右產生兩張7,各與真實照片差一個Pixel,左圖於人來看是較為真實<sub>(Realistic)</sub>,但對機器來說兩張都是接近正確答案的,它們是一樣好的。 ### The evolution of generation ![](https://i.imgur.com/tedMduj.png) GAN利用了類似演化的方式來生成照片: 1. Generator V1產生照片 2. Discriminator V1辨識照片是Generator產生或是實際照片,因此它是一個Binary Classifier的Output 3. 根據Discriminator V1產生Generator V2,在V2中產生的照片是可以騙過Discriminator V1,因此Discriminator需要進化 4. 進化為Discriminator V2,可以辨識出Generator V2與真實照片 5. ...... ### GAN - Discriminator ![](https://i.imgur.com/LjWb128.png) 首先,我們需要Discriminator-V1,這個`nn`輸入一個照片之後會輸出1/0,告訴我們是真實照片或是假照片,至於它是不是CNN、DNN...都是由個人自己決定。 接下來,我們會有一個Generator-V1,它做的事情與VAE-decoder是一樣的,輸入一個亂數生成的Vector,輸出一張照片,不同的地方在於訓練的方式,並不是以輸入、輸出愈接近愈好的方個來優化它。 訓練Discriminator方式說明如下: 1. 初始化Generator-V1,參數皆隨機產生 2. 產生一把假照片,標記為0 3. 從資料集中挑出一把真照片,標記為1 4. 將兩把照片輸入Discriminator-V1,以此學習辨識真假照片 ### GAN - Generator ![](https://i.imgur.com/oWT3XKh.png) 由Generator-V1產生的照片經過Discriminator-V1輸出之後,Discriminator-V1知道它是假照片,因此需輸是非常小的數值。 所以Generator-V1會更新參數,升級為Generator-V2,讓它的輸出照片可以更Realistic,最基本就是要可以騙過Discriminator-V1,也就是Generator-V2的輸出照片經過Discriminator-V1的輸出應該是1.0 訓練Generator的方式不難,只要將Generator與Discriminator接起來,就是一個`nn`,前段屬於Generator,後段屬於Discriminator,中間剛好會有一段的維度會跟生成照片一樣,它是Generator的Output,可以想成就是一個比較寬的hidden layer,以MNIST為例,中間那段就是28x28。 最後再利用Gradient Descent來更新參數,讓Discriminator-V1的輸出愈接近1愈好,但要注意到這時候要將Discriminator-V1的參數固定住,因為現在的目標是要Generator-V2可以騙過Discriminator-V1。 ### GAN - 二次元人物頭像鍊成 ![](https://i.imgur.com/4bkCwqS.png) 這次李弘毅老師要生成的是二次元人物,利用[DCGAN](https://github.com/carpedm20/DCGAN-tensorflow)來訓練,與GAN的差異就在於它的layer都是CNN<sub>(DC: Deep Convolutional)</sub> 註:[keras version DCGAN](https://github.com/jacobgil/keras-dcgan) ### GAN - 二次元人物頭像鍊成 ![](https://i.imgur.com/KP5UEB9.png) 上圖是100代之後的樣貌 ### GAN - 二次元人物頭像鍊成 ![](https://i.imgur.com/YkmkTA6.png) 上圖是1000代之後的樣貌 ### GAN - 二次元人物頭像鍊成 ![](https://i.imgur.com/Vpfr5H2.png) 上圖是2000代之後的樣貌 ### GAN - 二次元人物頭像鍊成 ![](https://i.imgur.com/pGDsGg2.png) 上圖是5000代之後的樣貌 ### GAN - 二次元人物頭像鍊成 ![](https://i.imgur.com/XsbgHpX.png) 上圖是10000代之後的樣貌 ### GAN - 二次元人物頭像鍊成 ![](https://i.imgur.com/hwQ4CrO.png) 上圖是20000代之後的樣貌 ### GAN - 二次元人物頭像鍊成 ![](https://i.imgur.com/rai6Gz0.png) 上圖是50000代之後的樣貌 ### Maximum Likelihood Estimation ![](https://i.imgur.com/cm2F6cj.png) 這邊開始說明GAN的原理,由Maximum Likelihood Estimation說起: 1. 首先,我們擁有一個資料分佈$P_{data}(x)$ * 可以將$x$想起是一張image 3. 找一個分佈$P_G(x;\theta)$,由$\theta$所控制,決定$P_G$的樣貌 * $P_G(x;\theta)$可以是一個Gaussian Mixture Model,$\theta$即可以是Gaussians的means與variances * 我們不以Gaussian Mixture Model來表示,因為我們準備使用`nn`來表示 * 找一組$\theta$讓$P_G(x;\theta)$與$P_{data}(x)$愈接近愈好 如果是Gaussian Mixture Model可以這麼做: 1. 從$P_{data}(x)$sample資料$\{x^1...,x^m\}$ 2. 假設已經給定參數$\theta$,並且我們可以計算出$P_G(x^i;\theta)$的機率 3. 定義Likelihood計算給定$\theta$的情況下,$P_G$產生$x^1...x^m$的可能性有多大 * $L=\prod^m_{i=1}P_G(x^i;\theta)$ * 將sample出來的每一筆資料$x^1...x^m$都計算$P_G(x^i;\theta)$,再乘起來,即為Likelihood * 尋找$\theta^*$可以讓Likelihood最大化 * 如果是Gaussian Mixture Model,那就是尋找mean、variance、Mixture's weight * 上圖為例,有三個Mixture,那找到的mean就是三個黃星星點,而variance即為三個藍色圈 ### Maximum Likelihood Estimation ![](https://i.imgur.com/DoHSDqI.png) 這邊說明$\theta$的推導,將連乘積取log,接著將log移內變為加總,即: * $arg \space max_\theta\sum_{i=1}^mlogP_G(x^i;\theta)$ * 目前$x^1..x^m$是由$P_{data}(x)$中sample出來的 * 項目計算的其實是從$P_{data}$中sample出$x$,計算$x$產生的機率取$log$的期望值 * $arg \space max_\theta E_{x\sim P_{data}}[logP_G(x;\theta)]$ * 因為無法直接對$P_{data}$計算積分,因此利用sample的方式計算 * 將期望值項目取積分 * 後面減掉的項目僅與$P_{data}$有關,因此不影響$\theta$的計算 * 這麼做的原因在於要將Maximum Likelihood化減為Minimum KL Divergence<sub>(KLD)</sub> * $arg \space min_\theta KL(P_{data}(x)||P_G(x;\theta))$ 我們要Maximum Likelihood所做的事就是找一個參數$\theta$,根據$\theta$定義的$P_G$,它與$P_{data}$的KL Divergence愈接近愈好。 $P_G$在一開始的時候我們定義為Gaussian Mixture Model,但它是有限制的,因此如果使用Gaussian Mixture Model來生成照片那效果非常不好。 註:KL Divergence計算兩個資料分佈有多接近,所得愈小即代表愈相近。 ### Now $P_G(x;\theta)$ is a NN ![](https://i.imgur.com/ZsIEfGD.png) GAN讓我們知道,我們可以有一個很複雜、一般化的$P_G$,那就是使用`nn`,$\theta$即為`nn`的參數。 假定,我們有一個`nn`,即function-$G(z)$<sub>($z$為Vector,通常維度較預計生成照片維度小)</sub>,$z$為function-$G$的input,output為$x$,$x$的維度與預生成照片維度相同。 `nn`可以input-vector,output-vector,但它如何定義distirbution?如果input-$z$是一個distribution,那output-$x$我們就可以把它也看成是distribution。 另外一點,我們不需要擔心$z$如果由Normal Distribution所sample出來,經過`nn`得到的的output-$x$是否會有上一小節所說的Gaussian Mixture Model效果不好,得不到一個複雜分佈的問題,基本上`nn`即使只擁有一個layer,只要夠寬,它也可以模擬任何Continuous Function,即使你的input再簡單,只是一個Normal distribution,經過`nn`之後也可以得到一個複雜的結果,這樣子就可以利用一個`nn`來定義distribution。 因此,現在我們只需要尋找一組參數,讓它所產出的分佈與實際資料分佈愈接近愈好。 $P_G(x)=\int_zP_{prior}(z)I_{[G(z)=x]}dz$ * 從`nn`(P_G)中sample出$x$的機率 * 積分所有可能的$z$ * 正態分佈中每一個$z$出現的機率不一樣,有的高有的低,因此需要乘上$P_{prior}(z)$ * $I_{[G(z)=x]}$ * $I$代表identity function,恆等函數(傳回和其輸入值相同的函數的稱呼) * 每一個$z$通過function-$G$得到$x$,這個$x$是不是相等於我們要的$x$,如果是則$I$的output為1,如果不是則為0 即使我們知道了也非常難以計算Likelihood,我們已知$P_{prior}(z)$的分佈,但function-$G$過於複雜,GAN最大的貢獻就是解決這個問題。 ### Basic Idea of GAN ![](https://i.imgur.com/CAKoMJK.png) 重新思考我們的問題: 1. 假設我們有一個Generator-G * G可以是任意function,即使不是`nn` * 輸出(x)、入(z)皆為Vector * 給定一個prior distribution-$P_{prior}(z)$,依function-G定義出$P_G(x)$ 目前算不出$P_G(x)$ 2. Discriminator-D * function-D * 輸入是x,輸出是一個數值 * 用來衡量$P_G(x)$與$P_{data}(x)$有多接近 * GAN中計算的不是KL Divergence,但也是一種Divergence 解Divergence的方式如下 3. 定義function-V(G,D) * 輸入G,D,輸出數值 尋找跟$P_{data}(x)$最接近的function-$G^*$ * $G^*=arg\space min_G\space max_DV(G,D)$ * $max_DV(G,D)$: 找一個$D$來最大化$V(G,D)$ * $min_G\space max_DV(G,D)$: 找一個$G$來最小化最大化$V(G,D)$ ### Basic Idea ![](https://i.imgur.com/HgWzL6N.png) 先看$max_DV(G,D)$,要找一個$D$來最大化$V(G,D)$,假設$G$就是Generator,並且只有三個選擇$G_1,G_2,G_3$<sub>(註1)</sub>。 在固定住$G$之後,不同的$D$就會有不同的數值產生<sub>(註2)</sub>,而$max_DV(G,D)$就是指,下三圖中的紅點數值,而$min_G\space max_DV(G,D)$所指的就是$G_3$ 在給定$G$的情況下,$max_DV(G,D)$某種角度來看就是計算$P_G$與$P_{data}$的Divergence 所以,圖上的最高點至X軸的高度就是兩者之間的差距,因此就可以明白為何$G_3$是我們要找的Generator ![](https://i.imgur.com/Hgbt6Pc.png) 註1:實際上Generator由`nn`定義的話,不同參數就有不同形態,但課程中假定只有三個選擇。 註2:Discriminator也可以是`nn`,課程中以一維來表示。 ### $max_DV(G,D)$ ![](https://i.imgur.com/YPR7Qjw.png) 在確定$G$的情況下,那一個$D^*$可以最大化$V$? 假定,funtion-$V$是一個已經確定的函數,如下: $V=E_{x\sim P_{data}}[logD(x)]+E_{x\sim P_G}[log(1-D(x))]$ ![](https://i.imgur.com/IQ07PUa.png) 兩個式子各取積分,再提出積分項,得到: $\int_x[P_{data}(x)logD(x)+P_G(x)log(1-D(x))]$ 假設,$D(x)$可以是任意函數,而輸出可以是任意數值,這種情況下我們可以分開考慮積分項內的項目,也就是不同的$x$都可以分開考慮,每一個$x$都找到可以讓積分內項目的值最大,那加總之後它自然就是最大值了。 積分項:$P_{data}(x)logD(x)+P_G(x)log(1-D(x))$ ### $max_DV(G,D)$ ![](https://i.imgur.com/eLQdXpU.png) 為了減化式子,如下調整: ![](https://i.imgur.com/RybRjkp.png) 其中$P_{data}$是已知的資料集,而$P_G$也是給定的,因此能調整的只有$D(x)$,找一個$D$讓$f(D)=alog(D)+blog(1-D)$最大,接下來就是利用微分來得到極值: $\dfrac{df(D)}{dD}=a \times \dfrac{1}{D} + b \times \dfrac{1}{1-D} \times(-1)=0$ 最後推導可得$D^*(x)=\dfrac{P_{data}(x)}{P_{data}(x)+P_G(x)}$,其值介於0,1之間,因此如果是`nn`的話,就可以在output的地方加一個Sigmoid,讓輸出介於0,1之間。 ![](https://i.imgur.com/6L6uzUN.png) ### $max_DV(G,D)$ ![](https://i.imgur.com/WWAb6Zd.png) 在推導之後就清楚明白知道,稍早簡報中的極值$D^*$該如何計算,有了$D^*$就可以帶入function-$V$來計算Divergence,來衡量$P_{data}$與$P_G$的差異。 ### $max_DV(G,D)$ ![](https://i.imgur.com/pIEDgPH.png) 現在說明為何function-$V$可以計算差異,目前已知如何求出$max_DV(G,D)$,也就是在給定$G$之後就可以利用稍早推導出的結果來求得$D^*$ ![](https://i.imgur.com/c9BahRL.png) 將計算得到的$D^*$帶入function-$V$,將求期望值的項目變更為積分項,再對分子、分母共同除$\dfrac{1}{2}$,取出log。 ### $max_DV(G,D)$ ![](https://i.imgur.com/vE0Fq6m.png) 整理公式得到如上簡報結果,推導過程有興趣可自行嚐試。 ![](https://i.imgur.com/1p4sYfK.png) 上圖簡單說明兩個項目分別計算KL Divergence,直觀來看,整個式子就是計算$P_{data}$與$P_G$之間的Divergence,雖然兩個項目是分別計算KL Divergence,但相加之後它們就會是對稱<sub>(註1)</sub>,稱為JS Divergence<sub>(註2)</sub>,因此後面的項目計算就是2倍$P_{data}(x)||P_G(x)$的JSD ![](https://i.imgur.com/3yrdAzW.png) JSD是對稱的,因此調整為$P_G(x)||P_{data}$也是可以的,到這邊我們確認,$max_DV(G,D)$,在給定$G$的情況下,找一個$D$讓function-$D$最大化的這個過程,確實是在衡量$G$與$data$之間的差距。 透過調整function-$V$可以有不同的定義,但目前先以最原始的GAN來說明。 註1:KL Divergence是非對稱型,因此將$P_{data}, P_{G}$調整得到結果是不一樣的 註2:Jensen-Shannon Divergence兩個資料分佈$P,Q$的JS Divergence即計算$P$與$M$的$\dfrac{1}{2}$KL Divergence與$Q$與$M$的$\dfrac{1}{2}$KL Divergence並加總,其中$M$為$P,Q$加總之後平均。 ### In the end ![](https://i.imgur.com/SDplDkP.png) 整理一下目前為止確認的事情: 1. 我們有Generator-$G$與Discriminator-$D$ 2. 定義一個function-$V$ 3. 尋找$G^*$ 4. 給定$G$讓function-$V$最大化<sub>(註1)(註2)</sub> 5. 找出$G$最小化$max_DV(G,D)$ * 當兩個資料分佈接近的時候,其JSD為0是最小的,也就是$P_G(x)=G_{data}(x)$ * How? 註1:兩個資料分佈就算沒有交集,其JSD最大就是log2,兩個資料分佈完全相同,其JSD為0 註2:依註1可知,function-$V$介於0與$-2log2$之間 ### Algorithm ![](https://i.imgur.com/6euYggl.png) 現在剩下找出$G$的問題,如何處理呢? 1. 將$max_DV(G,D)$定義為$L(G)$ * 此項目是在給定$G$的情況下找出$D$ * $L(G)$為Generator-$G$的loss function * 利用gradient descent找出一組參數來最小化$L(G)$ 舉一個簡單的範例,如下: ![](https://i.imgur.com/VKYZmWC.png) $f(x)=max\{D_1(x),D_2(x),D_3(x)\}$,假設該function內有三個$D(x)$,對$f(x)$計算偏微分的時候就看$x$落在那一個區域,誰的值最大,就對那一個$D(x)$做微分即可。 ### Algorithm ![](https://i.imgur.com/i3HcbXz.png) 現在明白,即使function-$V$中有max我們依然可以利用梯度下降硬train一發。尋找$G$來最小化$L(G)$流程作法如下: 1. 初始一個$G_0$ 2. 尋找$D^*_0$來最大化function-$V$,$V(G_0,D)$ * $V(G_0,D^*_0)$就是$P_{data}(x)$與$P_{G_0}(x)$的JSD 4. 計算梯度更新參數,進化為$G_1$ * 減少$P_{data}(x)$與$P_{G_0}(x)$的JSD 6. 給定$G_1$尋找$D^*_1$ * $V(G_1,D^*_1)$就是$P_{data}(x)$與$P_{G_1}(x)$的JSD 8. ...... ### Algorithm ![](https://i.imgur.com/lZx2AxU.png) 有一個不是問題的小問題,在給定$G_0$帶入$D_0^*$,經過function-$V$之後得到JS Divergence,經過一次的迭代更新之後得到$G_1$,並且在固定住$D_0^*$的情況下其JS Divergence會小於$V(G_0,D_0^*)$,但這並不保證新的$G_1$所得JS Divergence會比$G_0$小。 如下圖所示,它的資料分佈就是這麼怪異: ![](https://i.imgur.com/XDIG06v.png) 因此必須假設$D^*_0\approx D^*_1$,而且也不能讓$G$一次更新太多。這跟做gradient descent一樣,如果學習效率設置過高可能會造成loss不減反增,因此才說不是問題的小問題。 ### In practice ![](https://i.imgur.com/zGm16s0.png) 在實作中期望值是無法計算的,因此我們要計算一個近似值,我們無法對$P_{data},P_G$的分佈做積分,因為它的分佈空間是所有可能的資料,因此作法上就是從兩個空間都sample出m個點。 * from $P_{data}$: $\{x^1,x^2...x^m\}$ * from $P_{G}$: $\{\tilde{x}^1,\tilde{x}^2..\tilde{x}^m\}$ 因為我們無法直接計算期望值,因此以sample出來的m個點計算平均: $\tilde{V}=\dfrac{1}{m}\sum_{i=1}^mlogD(x^i)+\dfrac{1}{m}\sum_{i=1}^m(1-logD(\tilde{x}^i))$ 上面的數學式就是平常Binary Classifier的時候所用,最大化該數學式,或是最小化該數學式再加上一個負值<sub>(見下節說明)</sub>。 ### In practice ![](https://i.imgur.com/fdKiPOv.png) 上小節說明我們知道,整個式子我們計算的就是一個Binary Classifier問題,這樣想就簡單了,硬train一發,output就是$D(x)$,由$P_{data}(x)$中sample出$m$筆資料做為Positive examples,再用$P_G(x)$中sample出$m$筆資料做為Negative examples,接下來再Minimize Cross-entropy就可以。 我們在找一個$D$可以Maximize $\tilde{V}$,就可以求出JS Divergence,而實際上我們就是在訓練一個Binary Classifier Model,得到的loss小就代表JS Divergence大,反之loss大,就代表JSD小,這非常直觀可以理解。 註:簡報上的Minimize數學式錯誤,兩個項目前面都應該加上負號。 ![](https://i.imgur.com/D7oxVNn.png) ### Algorithm ![](https://i.imgur.com/RLYxAal.png) 整個演算法流程如下: 1. 初始化$\theta_d$、$\theta_g$,得到初始的Discriminator與Generator 2. 每次迭代中執行以下步驟 * 由$P_{data}(x)$中sample出$m$筆資料 * 由$P_{prior}(z)$中sample出$m$筆資料 * $P_{prior}$是一個簡單的分佈,平均分佈或正態分佈可自行決定 * 將$m$筆資料丟入Generator得到$\tilde{x}^1,\tilde{x}^2...\tilde{x}^m$ * 給定$G$的情況下更新Discriminator的參數$\theta_d$ * 即Maximize function-$\tilde{V}$ * 因為計算最大化,因此以Gradient Ascent求解 * 以上步驟為訓練Discriminator,重覆k次 * 重覆k次的原因在於求解過程要更新多次才能找到$max_DV(G,D)$ * 理論可得最佳解,但實際上可能只能得到區域解 * 固定Generator的情況下讓$\tilde{V}$的值變大 * 以下開始訓練Generator * 固定Discriminator的情況下,讓$\tilde{V}$的值變小 * 由$P_{prior}(z)$中sample出$m$筆資料 * 不一定需要另外sample,也可以用之前sample出來的$m$資料即可 * 更新Generator * 給定Discriminator情況下,最小化$\tilde{V}$ * 如下圖,$\tilde{x}$是將$z$帶入$G$而得 * ![](https://i.imgur.com/pMaXt11.png) * ![](https://i.imgur.com/gJeo5jK.png) * 前半部$\dfrac{1}{m}\sum^m_{i=1}logD(x^i)$是由$P_{data}$sample出$m$筆資料,再計算Discriminator的值,因此與Generator無關,可以拿掉,再更新參數$\theta_g$即可 * 更新Generator只會更新一次 * 更新太多次恐候無法讓JS Divergence降低 註:ian goodfellow在tutorial中說明,他訓練Discriminator的時候只會一次 ### Objective Function for Generator in Real Implementation ![](https://i.imgur.com/bSwnYR4.png) 這是一個實作上的issue,我們的目標是找一個Generator來最小化function-$V$,其中前項與$P_G(x)$無關可以無視,因此目標只有後面的$E_{x\sim P_G}[log(1-D(x))]$,但是實際上觀察$log(1-D(x))$<sub>(紅色線)</sub>,在$D(x)$很小值域的部份其線較為平滑,這造成Generator無法騙過Discriminator,而參數初始的時候值域較小,也另外造成訓練起步的困難。 ![](https://i.imgur.com/rqsGROS.png) 因此調整優化的目標為$V=E_{x\sim P_G}[-log(D(x))]$<sub>(藍線)</sub>,這兩個函數是一致的,意思就是值域一起大、一起小,不同處在於初始值域的梯度,調整過後的函數梯度較大,收斂之後梯度較小,這符合我們的想法。 ![](https://i.imgur.com/DcQUorr.png) 註1:x軸為$D(x)$ 註2:這麼做並無法保證是較好的,但一個好處是可以將$P_G(x)$產生的資料看成是Positive ### Evaluating JS divergence ![](https://i.imgur.com/Hpsbbll.png) 訓練GAN的時候會遇到一個問題,課程上提到,Discriminator的loss可以衡量JS Divergence,loss小,JSD就小,以此調整Generator,但這只是理想狀況,實際上,多數情況下Discriminator的loss都是0,也就是有100%的正確率。 上圖告訴我們的是,三個Generator,各自訓練不同的epoch,其中epochs-25所產生的照片非常真實。 但從上圖右可以看的出來,不管是那一個Generator,其Discriminator的accuracy都是100%,這代表Discriminator都可以一眼看穿這是假照片,即使是epochs-25所產生的照片。 ### Evaluating JS divergence ![](https://i.imgur.com/tgbxuLW.png) 我們知道Discriminator是用來衡量JS Divergence,但它告訴我們的訊息太少了,上面兩圖是用不同方式訓練出來的GAN<sub>(註~1~)</sub>,可以看的出來用DCGAN所產生的照片已經非常真實了,跟MLP所產生的有所落差,但兩者的JS Divergence幾乎都是平的,完全無法由此看出目前的生成照片是否是好的。 註~1~: * MLP_fully connect * DCGAN_Deep Convolution GAN ### Discriminator ![](https://i.imgur.com/VHcs6ok.png) Discriminator的loss為0,又或者該說$max_DV(G,D)=0$,這代表中間的JS Divergence所得為$log2$,也就是$P_{data}(x)$與$P_G(x)$都覺得生成出來的照片是可以的,這種問題有兩個原因: 1. 我們現在都是以sample方式來計算近似值,並非真的從空間中去計算積分 * 想像我們有紅色、藍色兩個空間,而它們是真的有重疊,計算的時候從兩個空間中隨機sample出幾個資料點,即使它們之間是有重疊,計算所得的JSD也不該是log2,但在Generator是非常Powerful的情況下,它還是可以硬是Positive與Negative分開,也造成loss趨近於0。 * 避免這種問題就是要綁住Discriminator,更新Discriminator次數要少,或者讓它變弱<sub>(較少的參數、加入Dropout...)</sub>,避免它Overfitting,但這麼做非常難以調校。 * 這也造成一種矛盾,我們希望Discriminator夠強,又希望它弱一點? ### Discriminator ![](https://i.imgur.com/LMqbqEa.png) 2. 在理論上由資料本質來看,我們所考慮的資料往往都是高維度空間上的manifold * 事實上Generator所產生的資料也會是高維空間中的mainfold,假設Generator的input是10維Vector,output雖然為100維,但它也是100維空間中的10維mainfold * 假設要生成的空間是2維空間,那$P_{data},P_G$就可能是2維空間中的2條直線,而它們交集的地方非常的少,幾乎是0,也造成loss為log2。 * ![](https://i.imgur.com/27fM1PG.png) ### Evaluation ![](https://i.imgur.com/NXojbKl.png) 之前課程提過,GAN就像是演化一樣,像眼睛從感光細胞一路演化成為眼睛也不是一次就到,而是經過很多階段演化而成。 ### Evaluation ![](https://i.imgur.com/xyyCtsv.png) 對GAN而言也是一樣,每一次的迭代更新都希望可以愈來愈好,讓$P_G$與$P_{date}$愈來愈接近,那才有辦法更新Generator。 上圖為例,$P_{G_0}$與$P_{G_{50}}$沒有任何交集,它們之間的JSD皆為$log2$,沒有形態上的變化,這使得它們無法更新到$P_{G_{100}}$ ### Add Noise ![](https://i.imgur.com/BG2umsH.png) 解決方式有幾種: 1. 增加噪點資訊在輸入給Discriminator的資訊當中。 2. 將Discriminator的Label加入噪點,正的變負的,負的變正的 這樣子的方式可以讓低維空間中可能的兩條直線加寬變胖<sub>(上圖右下)</sub>,增加他們的交集區域,也可以避免Discriminator完美的分辨,有了loss就計算JSD,只是噪點必須隨時時間增長而減少,避免過度干擾Discriminator。 ### Mode Collapse ![](https://i.imgur.com/tSBgHGd.png) 訓練GAN的時候會有一種狀況稱為『Mode Collapse』,空間也許會有如藍色區域般的分佈,但Generator有可能只會從紅色區取樣,這造成什麼問題? 上圖右其實可以發現有不少重覆造型的人物,這就是『Mode Collapse』,這種情況在訓練GAN是非常常見的而且不容易發現,因為你只會看到產生的資料,沒有生成的呢? ### Mode Collapse ![](https://i.imgur.com/Rp5nvWz.png) 我們希望Generator可以完美的生成$P_{date}$的資料分佈<sub>(如右上圖)</sub>,但實際上Generator在生成的時候會發現,它只會在一個Gaussian上生成資料,一但發現一直被Disctiminator破解再往下一個Gaussian上生成資料,就形成一個貓捉老鼠的戲劇。 ![](https://i.imgur.com/BB2FwK5.png) ### Flaw in Optimization? ![](https://i.imgur.com/2T4yOL0.png) 對於Mode Collapse的情況,Ian Goodfellow在tutorial提到,原本以為可能是在最佳化部份因為Divergence設計上的問題造成。 原本我們希望的是Maximum Likelihood,也就是Minimize KL Divergence$(P_{date}||P_G)$ ![](https://i.imgur.com/kyoPUS6.png) 什麼情況下KLD會產生無窮大的值?在$P_G=0$而$P_{date}$有值的情況下就會有這種情況,因此在Minimize KLD的時候我們會盡量避免這種情況發生,也就是$P_{data}$有值,那$P_G$也應該有值。 上小圖來看,$P_{data}$分佈為兩個Gaussian,理想上當然希望$P_G$也產生一樣的分佈,因為這種情況下的Divergence是最小的,但當$P_G$只能產生一個Gaussian的時候,它會傾向於包住$P_{data}$有的區域,避免得到KLD無窮大的結果,也比較不會得到Mode Collapse的情況。 如果現在Minimize的是reverse KLD的話<sub>(如下圖)</sub> ![](https://i.imgur.com/0QtIsXY.png) 那產生無窮大的KLD就會發生在$P_G$有值,而$P_{date}$沒有值的地方,也就是$P_G$在某一個$P_{date}$沒有資料的地方產生一筆資料,就會產生無窮大的Divergence,以生成照片為例,當$P_G$生成一張不像是真的照片的時候就會產生這種無窮大的Reverse KLD。 這也造成$P_G$在生成照片的時候會不斷生成相同的照片,因為它要避免產生無窮大的Divergence的情況發生,也因此,在$P_G$只能產生一個資料分佈的情況下,它會固守在某一個資料分佈,也因此造成Mode Collapse的情況。 原本大家以為就是Reverse KL造成Mode Collapse的問題,但並不全然。 ### So many GANs ![](https://i.imgur.com/DqR8av3.png) 上圖條列出多種GAN ### Motivation ![](https://i.imgur.com/iWi2u88.png) Conditional GAN不同於稍早所提的GAN,原始GAN中並無法控制空間中產出什麼,而Conditional GAN是可以控制產出什麼。 註:上圖描述的是輸入文字產出照片。 ### Motivation ![](https://i.imgur.com/Y0hLpsI.png) 以文字產出照片雖然也可以單純的用`nn`來硬train一發,但這會造成輸出模糊。舉例來說,一樣是輸入『train』,以監督式學習架構來處理的話,或許有6張照片都是標記為『train』,那它的輸出或許就是這6張照片的平均,它輸出的是一個點,並非是一個資料分佈。 ### Conditional GAN ![](https://i.imgur.com/sCgnbOt.png) 我們希望利用GAN的Generator來生成$x$,而這個$x$的distribution是依$c$而生成$P(x|c)$,不同的$c$就有不同的分佈產生。 ![](https://i.imgur.com/QvFdekk.png) 實作Conditional GAN會有一種狀況,即使從不同的分佈中隨機取樣做噪點還是會相同的產出,因此作法上就是在Generator中加入Dropout,而不從空間中隨機取樣。 而Discriminator有兩種方式: 1. 訓練一個Binary Classifier,輸入$x$<sub>(image)</sub>,輸出一個scalar,然後告訴你這照片是真是假,但這麼做的效果較差,較無法產生相關的照片。 2. 除了輸入$x$之外,再加入$c$,讓它成雙成對,這樣子的作法才能產生有相關性的照片。 實作上我們會採用上述方法2來處理,因此訓練資料的標記會是『述敘-$\hat{c}$』對應真正的『照片-$\hat{x}$』,這是Positive的資料。 而Negative example的資料即是$\hat{c}$與$G(\hat{c})$<sub>(Generator產生的照片)</sub>以及錯誤的敘述-$\hat{c'}$搭配正確的照片,讓Discriminator學習。 學習目標即是希望Generator生成的資料可以騙過Discriminator。 ### Text to Image - Results ![](https://i.imgur.com/1ttjPLQ.png) ![](https://i.imgur.com/NNR1G8t.png) 上圖是文獻上的附圖,可以發現生成的資料令人驚豔。 右上角是助教輸入一個資料集中沒有的敘述,結果真的生成了! ### Image-to-image Translation ![](https://i.imgur.com/5h0QekN.png) 上圖也都是Conditional GAN的應用,後續課程會說明。