# 李宏毅_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

[Video_Youtube](https://www.youtube.com/watch?v=HGYYEUSm-0Q)
### Review: Generation

GAN首先談生成,Generation,給機器看唐詩來產生詩,或是看動漫來產生圖。
### Review: Auto-encoder

要生成資料可以利用Auto-encoder,利用`nn`來壓縮,再利用`nn`來解壓,而我們希望輸入與輸出愈接近愈好。
訓練好`nn`之後,後段的`Decoder`就可以拿來做生成器使用。
### Review: Auto-encoder

上圖是實際案例,在不同的向量中取值得到不同的輸出結果。
### Review: Auto-encoder

在橫縱軸等距取值來看的話可以看的到數值的變化:
* 由左至右是圈到豎的變化
* 由上至下是角度的變化
### Review: VAE Auto-encoder

標準的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

VAE的一個問題,我們並不是真的要利用VAE去學習產生一張照片,而是要輸入跟輸出愈接近愈好,意思是它所輸出的照片跟輸入照片是否接近與『人』覺得它是不是真的是不一樣的事情。
上圖可以看到,左、右產生兩張7,各與真實照片差一個Pixel,左圖於人來看是較為真實<sub>(Realistic)</sub>,但對機器來說兩張都是接近正確答案的,它們是一樣好的。
### The evolution of generation

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

首先,我們需要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

由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 - 二次元人物頭像鍊成

這次李弘毅老師要生成的是二次元人物,利用[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 - 二次元人物頭像鍊成

上圖是100代之後的樣貌
### GAN - 二次元人物頭像鍊成

上圖是1000代之後的樣貌
### GAN - 二次元人物頭像鍊成

上圖是2000代之後的樣貌
### GAN - 二次元人物頭像鍊成

上圖是5000代之後的樣貌
### GAN - 二次元人物頭像鍊成

上圖是10000代之後的樣貌
### GAN - 二次元人物頭像鍊成

上圖是20000代之後的樣貌
### GAN - 二次元人物頭像鍊成

上圖是50000代之後的樣貌
### Maximum Likelihood Estimation

這邊開始說明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

這邊說明$\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

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

重新思考我們的問題:
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

先看$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

註1:實際上Generator由`nn`定義的話,不同參數就有不同形態,但課程中假定只有三個選擇。
註2:Discriminator也可以是`nn`,課程中以一維來表示。
### $max_DV(G,D)$

在確定$G$的情況下,那一個$D^*$可以最大化$V$?
假定,funtion-$V$是一個已經確定的函數,如下:
$V=E_{x\sim P_{data}}[logD(x)]+E_{x\sim P_G}[log(1-D(x))]$

兩個式子各取積分,再提出積分項,得到:
$\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)$

為了減化式子,如下調整:

其中$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之間。

### $max_DV(G,D)$

在推導之後就清楚明白知道,稍早簡報中的極值$D^*$該如何計算,有了$D^*$就可以帶入function-$V$來計算Divergence,來衡量$P_{data}$與$P_G$的差異。
### $max_DV(G,D)$

現在說明為何function-$V$可以計算差異,目前已知如何求出$max_DV(G,D)$,也就是在給定$G$之後就可以利用稍早推導出的結果來求得$D^*$

將計算得到的$D^*$帶入function-$V$,將求期望值的項目變更為積分項,再對分子、分母共同除$\dfrac{1}{2}$,取出log。
### $max_DV(G,D)$

整理公式得到如上簡報結果,推導過程有興趣可自行嚐試。

上圖簡單說明兩個項目分別計算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

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

整理一下目前為止確認的事情:
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

現在剩下找出$G$的問題,如何處理呢?
1. 將$max_DV(G,D)$定義為$L(G)$
* 此項目是在給定$G$的情況下找出$D$
* $L(G)$為Generator-$G$的loss function
* 利用gradient descent找出一組參數來最小化$L(G)$
舉一個簡單的範例,如下:

$f(x)=max\{D_1(x),D_2(x),D_3(x)\}$,假設該function內有三個$D(x)$,對$f(x)$計算偏微分的時候就看$x$落在那一個區域,誰的值最大,就對那一個$D(x)$做微分即可。
### Algorithm

現在明白,即使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

有一個不是問題的小問題,在給定$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$小。
如下圖所示,它的資料分佈就是這麼怪異:

因此必須假設$D^*_0\approx D^*_1$,而且也不能讓$G$一次更新太多。這跟做gradient descent一樣,如果學習效率設置過高可能會造成loss不減反增,因此才說不是問題的小問題。
### In practice

在實作中期望值是無法計算的,因此我們要計算一個近似值,我們無法對$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

上小節說明我們知道,整個式子我們計算的就是一個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數學式錯誤,兩個項目前面都應該加上負號。

### Algorithm

整個演算法流程如下:
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$而得
* 
* 
* 前半部$\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

這是一個實作上的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,而參數初始的時候值域較小,也另外造成訓練起步的困難。

因此調整優化的目標為$V=E_{x\sim P_G}[-log(D(x))]$<sub>(藍線)</sub>,這兩個函數是一致的,意思就是值域一起大、一起小,不同處在於初始值域的梯度,調整過後的函數梯度較大,收斂之後梯度較小,這符合我們的想法。

註1:x軸為$D(x)$
註2:這麼做並無法保證是較好的,但一個好處是可以將$P_G(x)$產生的資料看成是Positive
### Evaluating JS divergence

訓練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

我們知道Discriminator是用來衡量JS Divergence,但它告訴我們的訊息太少了,上面兩圖是用不同方式訓練出來的GAN<sub>(註~1~)</sub>,可以看的出來用DCGAN所產生的照片已經非常真實了,跟MLP所產生的有所落差,但兩者的JS Divergence幾乎都是平的,完全無法由此看出目前的生成照片是否是好的。
註~1~:
* MLP_fully connect
* DCGAN_Deep Convolution GAN
### Discriminator

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

2. 在理論上由資料本質來看,我們所考慮的資料往往都是高維度空間上的manifold
* 事實上Generator所產生的資料也會是高維空間中的mainfold,假設Generator的input是10維Vector,output雖然為100維,但它也是100維空間中的10維mainfold
* 假設要生成的空間是2維空間,那$P_{data},P_G$就可能是2維空間中的2條直線,而它們交集的地方非常的少,幾乎是0,也造成loss為log2。
* 
### Evaluation

之前課程提過,GAN就像是演化一樣,像眼睛從感光細胞一路演化成為眼睛也不是一次就到,而是經過很多階段演化而成。
### Evaluation

對GAN而言也是一樣,每一次的迭代更新都希望可以愈來愈好,讓$P_G$與$P_{date}$愈來愈接近,那才有辦法更新Generator。
上圖為例,$P_{G_0}$與$P_{G_{50}}$沒有任何交集,它們之間的JSD皆為$log2$,沒有形態上的變化,這使得它們無法更新到$P_{G_{100}}$
### Add Noise

解決方式有幾種:
1. 增加噪點資訊在輸入給Discriminator的資訊當中。
2. 將Discriminator的Label加入噪點,正的變負的,負的變正的
這樣子的方式可以讓低維空間中可能的兩條直線加寬變胖<sub>(上圖右下)</sub>,增加他們的交集區域,也可以避免Discriminator完美的分辨,有了loss就計算JSD,只是噪點必須隨時時間增長而減少,避免過度干擾Discriminator。
### Mode Collapse

訓練GAN的時候會有一種狀況稱為『Mode Collapse』,空間也許會有如藍色區域般的分佈,但Generator有可能只會從紅色區取樣,這造成什麼問題?
上圖右其實可以發現有不少重覆造型的人物,這就是『Mode Collapse』,這種情況在訓練GAN是非常常見的而且不容易發現,因為你只會看到產生的資料,沒有生成的呢?
### Mode Collapse

我們希望Generator可以完美的生成$P_{date}$的資料分佈<sub>(如右上圖)</sub>,但實際上Generator在生成的時候會發現,它只會在一個Gaussian上生成資料,一但發現一直被Disctiminator破解再往下一個Gaussian上生成資料,就形成一個貓捉老鼠的戲劇。

### Flaw in Optimization?

對於Mode Collapse的情況,Ian Goodfellow在tutorial提到,原本以為可能是在最佳化部份因為Divergence設計上的問題造成。
原本我們希望的是Maximum Likelihood,也就是Minimize KL Divergence$(P_{date}||P_G)$

什麼情況下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>

那產生無窮大的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

上圖條列出多種GAN
### Motivation

Conditional GAN不同於稍早所提的GAN,原始GAN中並無法控制空間中產出什麼,而Conditional GAN是可以控制產出什麼。
註:上圖描述的是輸入文字產出照片。
### Motivation

以文字產出照片雖然也可以單純的用`nn`來硬train一發,但這會造成輸出模糊。舉例來說,一樣是輸入『train』,以監督式學習架構來處理的話,或許有6張照片都是標記為『train』,那它的輸出或許就是這6張照片的平均,它輸出的是一個點,並非是一個資料分佈。
### Conditional GAN

我們希望利用GAN的Generator來生成$x$,而這個$x$的distribution是依$c$而生成$P(x|c)$,不同的$c$就有不同的分佈產生。

實作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


上圖是文獻上的附圖,可以發現生成的資料令人驚豔。
右上角是助教輸入一個資料集中沒有的敘述,結果真的生成了!
### Image-to-image Translation

上圖也都是Conditional GAN的應用,後續課程會說明。