對抗生成網絡GAN系列——WGAN原理及實戰演練

語言: CN / TW / HK

theme: hydrogen highlight: atelier-dune-dark


本文為稀土掘金技術社區首發簽約文章,14天內禁止轉載,14天后未獲授權禁止轉載,侵權必究!

🍊作者簡介:禿頭小蘇,致力於用最通俗的語言描述問題

🍊往期回顧:對抗生成網絡GAN系列——GAN原理及手寫數字生成小案例   對抗生成網絡GAN系列——DCGAN簡介及人臉圖像生成案例   對抗生成網絡GAN系列——AnoGAN原理及缺陷檢測實戰   對抗生成網絡GAN系列——EGBAD原理及缺陷檢測實戰

🍊近期目標:寫好專欄的每一篇文章

🍊支持小蘇:點贊👍🏼、收藏⭐、留言📩

 

對抗生成網絡GAN系列——WGAN原理及實戰演練

寫在前面

​  在前面我已經寫過好幾篇關於GAN的文章,感興趣的可以點擊下列鏈接瞭解詳情:

​  在文章[5]的最後,我們從訓練結果中可以看出效果並不是很理想,其實難以訓練是GAN網絡訓練普遍存在的問題。本篇文章將為大家帶來WGAN(Wasserstein Generative Adversarial Networks ),旨在解決GAN難train的問題。這篇論文中有大量的理論推導,我不會帶着大家一個個推,當然很多我也不會,但是我儘可能的把一些關鍵部分給大家敍述清楚,讓大家從心底認可WGAN,覺得WGAN是合理的,是美妙的。

​  準備好了嗎,就讓我們一起來學學WGAN吧!🚖🚖🚖

 

WGAN原理詳解

GAN為什麼訓練困難

​  上文我們談到GAN普遍存在訓練困難的問題,而WGAN是用來解決此問題的。所謂對症下藥,我們第一步應該要知道GAN為什麼會存在訓練難的問題,這樣我們才能從本質上對其進行改進。下面就跟隨我的步伐一起來看看吧!!!🌼🌼🌼

​  還記得我們在[1]中給出的GAN網絡的損失函數嗎?如下圖所示:

image-20220714095708540

​  為了方便表述,對上圖公式做如下調整:

​ $$\mathop {\min }\limits_G \mathop {\max }\limits_D V = {E_{x \sim {{\rm{p}}r}}}[\log D(x)] + {E{x \sim {{\rm{p}}_g}}}[\log (1 - D(x))]$$

​  即把後一項的$G(z)$用x來表示,x為生成器生成的分佈。

​  我們現在希望求得生成器固定是最大化的判別器D。首先,我們對於一個隨機的樣本,它可能是真實樣本,也可能是生成的樣本,那麼對於這個樣本的損失為:

​ $${{\rm{P}}_r}(x)\log D(x) + {P_g}(x)\log [1 - D(x)]$$

​  預求最大化的D,則對上式的D(x)求導,並讓上式導函數為0,即:

​ $$\frac{{{{\rm{P}}_r}(x)}}{{D(x)}} - \frac{{{{\rm{P}}_g}(x)}}{{1 - D(x)}} = 0$$

​  化簡上式,得最優的D表達式為:

​ $${D^*}(x) = \frac{{{{\rm{P}}_r}(x)}}{{{{\rm{P}}_r}(x) + {{\rm{P}}_g}(x)}}$$        ———— 式1

​  我們可以來看看這個式1是否符合我們的直覺。若$p_r(x)=0、p_g(x)\ne 0$表示x完全服從生成分佈,是假圖像,所以最優判別器D給出的概率為0;若$p_r(x) \ne 0、p_g(x)= 0$表示x完全服從真實分佈,是真圖像,所以最優判別器D給出的概率為1;若$p_r(x)=p_g(x)$,表示x服從生成分佈和服從真實分佈的數據一樣多,因此最優判別器D給出的概率為50%。

​  如今我們已經找到了最大化的D,現要將其固定,尋找最小化的G,即求下式:

​ $$\mathop {\min }\limits_G V = {E_{x \sim {{\rm{p}}r}}}[\log D(x)] + {E{x \sim {{\rm{p}}_g}}}[\log (1 - D(x))]$$    ———— 式2

​  將最大化的D即式1的$D^*(x)$代入式2得:

​ $$\mathop {\min }\limits_G V = {E_{x \sim {{\rm{p}}r}}}[\log (\frac{{{{\rm{p}}_r}(x)}}{{{{\rm{p}}_r}(x) + {{\rm{p}}_g}(x)}})] + {E{x \sim {{\rm{p}}_g}}}[\log (\frac{{{{\rm{p}}_g}(x)}}{{{{\rm{p}}_r}(x) + {{\rm{p}}_g}(x)}})]$$

​  再化簡一步得式3:

​ $$\mathop {\min }\limits_G V = {E_{x \sim {{\rm{p}}r}}}[\log (\frac{{{{\rm{p}}_r}(x)}}{{\frac{1}{2}{{\rm{p}}_r}(x) + {{\rm{p}}_g}(x)}})] + {E{x \sim {{\rm{p}}_g}}}[\log (\frac{{{{\rm{p}}_g}(x)}}{{\frac{1}{2}{{\rm{p}}_r}(x) + {{\rm{p}}_g}(x)}})] - 2\log 2$$    ———— 式3

​  化簡成式3的形式是為了和KL散度和JS散度相聯繫。我們先來介紹KL散度和JS散度的定義:【大家不要覺得散度這個詞好像很高大上一樣,大家其實就可以理解為距離】

  • KL散度

$$KL(P_1||P_2)=E_{x \sim P_1}log \frac {P_1}{P_2}$$

上式是用期望來表示KL散度的,我們也可以用積分或求和形式來表達,如下:

$$KL(P_1||P_2)=\int\limits_x {{P_1}\log \frac{{{P_1}}}{{{P_2}}}} dx$$ 或 $$KL(P_1||P_2)= \sum {{p_1}\log } \frac{{{P_1}}}{{{P_2}}}$$

我來大致的解釋一下KL散度的含義,用$KL(P_1||P_2)=\sum {{P_1}( - log{P_2} - ( - log{P_1}))}$解釋,如下圖:

image-20221004162943163

​  關於KL散度我就介紹這麼多,它還有一些性質,像非對稱性等等,我這裏就不過多介紹了,感興趣的可以自己去閲讀閲讀相關資料。

 

  • JS散度 $$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})$$

可以看出,JS散度是根據KL散度來定義的,它具有對稱性。


​  有了JS散度的定義,我們就可以將式3變換成如下形式:

​ $$\mathop {\min }\limits_G V = 2JS({P_r}||{P_g}) - 2\log 2$$      ———— 式4

​  這時候肯定很多人會想了,為什麼我們需要把式3化成式4這個JS散度的形式,這是因為我們的GAN訓練困難很大原因就是這個JS散度搗的鬼。🍵🍵🍵

​  為什麼説訓練困難是JS散度搗的鬼呢?通過上文我們知道,我們將判別器訓練的越好,即判別器越接近最優判別器,此時生成器的loss會等價為式4中的JS散度的形式,當我們訓練生成器來最小化生成器損失時也就是最小化式4中的JS散度。這這過程看似非常的合理,只要我們不斷的訓練,真實分佈和生成分佈越來越接近,JS散度應該越來越小,直到兩個分佈完全一致,此時JS散度為0。

​  但是理想很豐滿,現實很骨感,JS散度並不會隨着真實分佈和生成分佈越來越近而使其值越來越小,而是很大概率保持$log2$不變。

image-20221004183627189

​  如上圖所示,隨着$p_g$和$p_{data}$(也就是上文中所述的$p_r$)越來越近,它們的JS散度卻不發生變化,一直等於log2,只有當$p_g$和$p_{data}$有重疊時才會發生變化,當完全重疊時,JS散度的值為0。也就是説,不論$p_g$和$p_{data}$相距多遠,只要它們沒有重疊,那麼它們的JS散度就一直是常數log2,也就是在訓練過程中loss一直不發生變化,這也意味着生成器的梯度一直為0,即生成器產生了梯度消失的現象。

​  讀了上文,我覺得你至少應該有兩個疑問,其一是為什麼兩個分佈不重合,它們JS散度一直為log2,其二為既然只要$p_g$和$p_{data}$有重疊,那麼它們的JS散度就不是log2,這樣我們是不是就可以更新梯度了呢?那麼它們重疊的概率大嗎?我們一個一個的來解決大家的疑惑。🥂🥂🥂

  1. 什麼兩個分佈不重合,它們JS散度一直為log2

這個其實是由JS散度的性質來決定的,這裏帶大家推一推。首先JS散度的表達式如下:

​ $$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})$$

上文我也給出了KL散度的公式,將KL散度公式代入上式,得:

​ $$JS({P_1}||{P_2}) = \frac{1}{2}\sum {{p_1}(x)\log } \frac{{2{p_1}(x)}}{{{p_1}(x) + {p_2}(x)}} + \frac{1}{2}\sum {{p_2}(x)\log } \frac{{2{p_2}(x)}}{{{p_1}(x) + {p_2}(x)}}$$

再化簡上式,將log2提出來,注意這裏可以提是因為$\sum {{p_1}(x) = } \sum {{p_2}(x) = } 1$,提取後公式如下:

​ $$JS({P_1}||{P_2}) = \frac{1}{2}\sum {{p_1}(x)\log } \frac{{{p_1}(x)}}{{{p_1}(x) + {p_2}(x)}} + \frac{1}{2}\sum {{p_2}(x)\log } \frac{{{p_2}(x)}}{{{p_1}(x) + {p_2}(x)}} + \log 2$$

現在大家注意到上式已經有一個log2了,為證明我們的結論,我們只需證明兩個分佈不重合時上式左側兩項為0即可。我們以下圖為例進行講解:

​  對於上圖中的兩個分佈$P_1和P_2$,可以看出它們沒有重疊部分。我們設$p_1(x)$為x落在$P_1$分佈上的概率,設$p_2(x)$為x落在$P_2$分佈上的概率,我們來看$JS(P_1||P_2)$的左邊兩項,即$\frac{1}{2}\sum {{p_1}(x)\log } \frac{{{p_1}(x)}}{{{p_1}(x) + {p_2}(x)}} + \frac{1}{2}\sum {{p_2}(x)\log } \frac{{{p_2}(x)}}{{{p_1}(x) + {p_2}(x)}}$ ,

​  當$x<5$時,$p_2(x)$近似為0,則:

​ $\frac{1}{2}\sum {{p_1}(x)\log } \frac{{{p_1}(x)}}{{{p_1}(x) + {p_2}(x)}} + \frac{1}{2}\sum {{p_2}(x)\log } \frac{{{p_2}(x)}}{{{p_1}(x) + {p_2}(x)}} = \frac{1}{2}\sum {{p_1}(x)\log } \frac{{{p_1}(x)}}{{{p_1}(x) + 0}} + \frac{1}{2}\sum {0\log } \frac{0}{{{p_1}(x) + 0}} = 0$

​  當$x \ge 5$時,$p_1(x)$近似為0,則:

​ $\frac{1}{2}\sum {{p_1}(x)\log } \frac{{{p_1}(x)}}{{{p_1}(x) + {p_2}(x)}} + \frac{1}{2}\sum {{p_2}(x)\log } \frac{{{p_2}(x)}}{{{p_1}(x) + {p_2}(x)}} = \frac{1}{2}\sum {0\log } \frac{0}{{0 + {p_2}(x)}} + \frac{1}{2}\sum {{p_2}(x)\log } \frac{{{p_2}(x)}}{{0 + {p_2}(x)}} = 0$

​  因此對於任意的x都會有$\frac{1}{2}\sum {{p_1}(x)\log } \frac{{{p_1}(x)}}{{{p_1}(x) + {p_2}(x)}} + \frac{1}{2}\sum {{p_2}(x)\log } \frac{{{p_2}(x)}}{{{p_1}(x) + {p_2}(x)}}=0$ ,進而會有$JS(P_1||P_2)=log2$。🌱🌱🌱


這部分主要參考了這篇文章,我認為其對JS散度為什麼等於log2解釋的非常清楚🍦🍦🍦


  1. 任意的兩個分佈$p_g$和$p_{data}$重疊的概率有多大

​  首先,我直接給大家明確結論,重疊概率很小,特別小。我説明一下這裏所説的重疊概率指的是重疊部分不可忽略的概率,也就是説$p_g$和$p_{data}$可能會重疊,但是往往重疊部分都是可以忽略的。這部分大家可以參考這篇文章,寫的非常好,對於這部分的解釋也比較全面。

​  我從兩個角度幫助大家理解,其一,$p_g$和$p_{data}$假設為一條曲線,$p_g$開始往往都是隨機生成的,所以很難和$p_{data}$重合,往往都是有一些交點,而這些交點是可以忽略的。實際上,$p_g$和$p_{data}$的維度往往很高,它們完全重疊的概率非常之低。

image-20221004201438790

​  其二,我們往往是從$p_g$和$p_{data}$中採樣一些點出來訓練,即使$p_g$和$p_{data}$有重疊,但是經過採樣後,它們很大可能就沒有重疊了。


​  解釋了這麼多,大家應該知道為什麼GAN會訓練困難了吧。最後總結一下,這是因為當判別器訓練最優時,生成器的損失函數等價於JS散度,其梯度往往一直為0,得不到更新,所以很難train。


​  我不知道大家是否會有這樣的疑問,既然説生成器梯度得不大更新,為什麼我們在訓練GAN時還是能得到一些較好的圖片呢,不應該什麼也得不到呢。我是這樣認為的,我們上述的推導都是建立在最優判別器的基礎上的,但是在我們實操過程中往往一開始判別器性能是不理想的,所以生成器還是有梯度更新的。還有一點,就是我之前的文章代碼中生成器的損失其實使用的$-logD(x)$,這種損失函數也會存在一些問題,往往出現梯度不穩定,模式崩潰問題,但是梯度消失問題出現比較少,所以還是能訓練的。關於使用這種損失函數帶來的缺陷我這裏也不敍述了,大家感興趣的可以看看這篇文章。🍹🍹🍹

 

EM distance(推土機距離)的引入

​  我們上文詳細分析了普通GAN存在的缺陷,主要是由於和JS散度相關的損失函數導致的。大佬們就在思考能否有一種損失能夠代替JS散度呢?於是,WGAN應運而生,其提出了一種新的度量兩個分佈距離的標準——Wasserstein Metric,也叫推土機距離(Earth-Mover distance)。下面就讓我們來看看什麼是推土機距離吧!!!🌶🌶🌶


【這部分參考此篇文章

​  下圖左側有6個盒子,我們期望將它們都移動到右側的虛線框內。比如將盒子1從位置1移動到位置7,移動了6步,我們就將此步驟的代價設為6;同理,將盒子5從位置3移動到位置10,移動了7步,那麼此步驟的代價為7,依此類推。

1

                圖1 EM distance示例

​  很顯然,我們有很多種不同的方案,下圖給出了兩種不同的方案:

2

​  上圖中右側的表格表示盒子是如何移動的。比如在${\gamma _1}$中,其第一行第一列的值為1,表示有1個框從位置1移動到了位置7;第一行的第四列的值為2,表示有2個框從位置1移動到了位置10。上圖中給出的兩種方案的代價總和都為42,但是對於一個問題並不是所有的移動方案的代價都是固定的,比如下圖:

3

​  在這個例子中,上圖展示的兩種方案的代價是不同的,一個為2,一個為6。,而推土機距離就是窮舉所有的移動方案,最小的移動代價對應的就是推土機距離。對應本列來説,推土機距離等於2。

​  相信通過上文的表述,你已經對推土機距離有了一定了瞭解。現給出推土機距離是數學定義,如下:

​ $${\rm{W}}({P_r},{P_g}) = \mathop {\inf }\limits_{\gamma \in \prod ({P_r},{P_g})} {E_{(x,y)}}[||x - y||]$$

​  看到這個公式大家是不是都懵逼了呢,這裏做相關的解釋。${\prod ({P_r},{P_g})}$表示邊緣分佈$P_r和P_g$所有組合起來的聯合分佈$\gamma(x,y)$的集合。我們還是用圖1中的例子來解釋,${\prod ({P_r},{P_g})}$就表示所有的運輸方案$\gamma$,下圖僅列舉了兩種方案:

4

​ ${E_{(x,y)}}[||x - y||]$ 可以看成是對於一個方案$\gamma$ 移動的代價,$\mathop {\inf }\limits_{\gamma \in \prod ({P_r},{P_g})} {E_{(x,y)}}[||x - y||]$ 就表示在所有的方案中的最小代價,這個最小大家就是$W(P_r,P_g)$,即推土機距離。🍄🍄🍄


​  現在我們已經知道了推土機距離是什麼,但是我們還沒解釋清楚我們為什麼要用推土機距離,即推土機距離為什麼可以代替JS散度成為更優的損失函數?我們來看這樣的一個例子,如下圖所示:

img

​  上圖有兩個分佈$P_1和P_2$,$P_1$在線段AB上均勻分佈,$P_2$在CD上均勻分佈,參數$\theta$可以控制兩個分佈的距離。我們由前文對JS散度的解釋,可以得到:

​ $$JS({P_1}||{P_2}) = \left{ \begin{array}{l} \log 2{\rm{ }} \quad \theta \ne {\rm{0}}\ 0{\rm{ }} \quad \quad \ \ \theta {\rm{ = 0}} \end{array} \right.$$

​  而對於推土機距離來説,可以得到:

​ $$W(P_1,P_2)=|\theta|$$

​  這樣對比可以看出,推土機距離是平滑的,這樣在訓練時,即使兩個分佈不重疊推土機距離仍然可以提高梯度,這一點是JS散度無法實現的。🍋🍋🍋


WGAN的實現

​  現在我們已經有了推土機距離的定義,同時也解釋了推土機距離相較於JS散度的優勢。但是我們想要直接使用推土機距離來定義生成器的損失似乎是困難的,因為這個式子${\rm{W}}({P_r},{P_g}) = \mathop {\inf }\limits_{\gamma \in \prod ({P_r},{P_g})} {E_{(x,y)}}[||x - y||]$ 是難以直接求解的,但是呢,作者大大用了一個定理將上式變化成了如下形式:

​ $${\rm{W}}({P_r},{P_g}) = \frac{1}{k}\mathop {\sup }\limits_{||f|{|L} \le K} {E{x \sim {{\rm{P}}r}}}[f(x)] - {E{x \sim {{\rm{P}}_g}}}[f(x)]$$

​  注意上式中的f有一個限制,即${||f|{|_L} \le K}$,我們稱為lipschitz連續條件。這個限制其實就是限制了函數f的導數。它的定義如下:

​ $$|f(x_1)-f(x_2)| \le K|x_1-x2|$$

​ 即:

​ $$\frac{|f(x_1)-f(x_2)|}{|x_1-x2|} \le K$$

​  很顯然,lipschitz連續就限制了f的斜率的絕對值小於等於K,這個K稱為Libschitz常數。我們來舉個例子幫助大家理解,如下圖所示:

image-20221005103024152

​  上圖中log(x)的斜率無界,故log(x)不滿足lipschitz連續條件;而sin(x)斜率的絕對值都小於1,故sin(x)滿足lipschitz連續條件。


​  這樣,我們只需要找到一個lipschitz函數,就可以計算推土機距離了。至於怎麼找這個lipschitz函數呢,就是我們搞深度學習的那一套啦,只需要建立一個深度學習網絡來進行學習就好啦。實際上,我們新建立的判別器網絡和之前的的基本是一致的,只是最後沒有使用sigmoid函數,而是直接輸出一個分數,這個分數可以反應輸入圖像的真實程度。

​  呼呼呼~~,WGAN的原理就為大家介紹到這裏了,大家掌握了多少呢?其實我認為只看一篇文章是很難把WGAN的所有細節都理解的,大家可以看看本文的參考文獻,結合多篇文章看看能不能幫助大家解決一些困惑。🧅🧅🧅

 

WGAN代碼實戰

​  WGAN的代碼實戰我不打算貼出一堆代碼了,只説明一下WGAN相較於普通GAN做了哪些改變。首先我們給出論文中訓練WGAN的流程圖,如下:

image-20221005112701037

​  其實WGAN相較於原始GAN只做了4點改變,分別如下:

  1. 判別器最後不使用sigmoid函數
  2. 生成器和判別器的loss不取log
  3. 每次更新判別器參數後將判別器的權重截斷
  4. 不適應基於動量的優化算法,推薦使用RMSProp

現在代碼中分別對上述的4點做相關解釋:【很簡單,所以大家想要將原始GAN修改為WGAN就按照下列的幾點來修改就好了】

  1. 判別器最後不使用sigmoid函數

這個我們一般只需要刪除判別器網絡中的最後一個sigmoid層就可以了,非常簡單。但是我還想提醒大家一下,有時候你在看別人的原始GAN時,他的判別器網絡中並沒有sigmoid函數,而是在定義損失函數時使用了BCEWithLogitsLoss函數,這個函數會先對數據做sigmoid,相關代碼如下:

python # 定義損失函數 criterion = nn.BCEWithLogitsLoss(reduction='mean')

如果這時你想刪除sigmoid函數,只需將BCEWithLogitsLoss函數修改成BCELoss即可。關於BCEWithLogitsLossBCELoss的區別我這篇文章有相關講解,感興趣的可以看看。🌽🌽🌽

  1. 生成器和判別器的loss不取log

我們先來看原始GAN判別器的loss是怎麼定義的,如下:

python d_loss_real = criterion(d_out_real.view(-1), label_real) d_loss_fake = criterion(d_out_fake.view(-1), label_fake) d_loss = d_loss_real + d_loss_fake

原始GAN使用了criterion函數,這就是我們上文定義的BCEWithLogitsLossBCELoss,其內部是一個log函數,不清楚的同樣可以參考我的這篇文章

而WGAN判別器的損失直接是兩個期望(均值)的差,就對應理論中${E_{x \sim {{\rm{P}}r}}}[f(x)] - {E{x \sim {{\rm{P}}_g}}}[f(x)]$ 這部分啦【但是需要加個負號,因為我們都是使用的梯度下降方法,要最小化這個損失,上式是最大化的公式】,我們來看看代碼中的實現:

python d_loss = -(torch.mean(d_out_real.view(-1))-torch.mean(d_out_fake.view(-1)))

看完判別器的損失,我們再來看生成器的損失:

```python g_loss = criterion(d_out_fake.view(-1), label_real) #原始GAN損失


g_loss = -torch.mean(d_out_fake.view(-1)) #WGAN損失 ```

  1. 每次更新判別器參數後將判別器的權重截斷

首先來説説沒什麼要進行權重截斷,這是因為lipschitz連續條件不好確定,作者為了方便直接簡單粗暴的限制了權重參數在[-c,c]這個範圍了,這樣就一定會存在一個常數K使得函數f滿足lipschitz連續條件,具體的實現代碼如下:

python # clip D weights between -0.01, 0.01 權重剪裁 for p in D.parameters(): p.data.clamp_(-0.01, 0.01)

注意這步是在判別器每次反向傳播更新梯度結束後進行的。還需要提醒大家一點,在訓練WGAN時往往會多訓練幾次判別器然後再訓練一次生成器,論文中是訓練5次判別器後訓練一次生成器,關於這一點在上文WGAN的流程圖中也有所體現。為什麼要這樣做呢?我思考這樣做可能是想把判別器訓練的更好後再來訓練生成器,因為在前面的理論部分我們的推導都是建立在最優判別器的前提下的。🍵🍵🍵

  1. 不適應基於動量的優化算法,推薦使用RMSProp

這部分就屬於玄學部分了,作者做實驗發現像Adam這類基於動量的優化算法效果不好,然後使用了RMSProp優化算法。我決定這部分大家也不要糾結,直接用就好。同樣我們來看看代碼是怎麼寫的,如下:

python optimizerG = torch.optim.RMSprop(G.parameters(), lr=5e-5) optimizerD = torch.optim.RMSprop(D.parameters(), lr=5e-5)


​  這樣,WGAN的代碼實戰我就為大家介紹到這裏,不管你前文的WGAN原理聽明白了否,但是WGAN代碼相信你是一定會修改的,改動的非常之少,大家快去試試吧。🍄🍄🍄

 

小結

​  這部分的理論確實是有一定難度的,我也看了非常非常多的視頻和博客,寫了很多筆記。我覺得大家不一定要弄懂每一個細節,只要對裏面的一些關鍵公式,關鍵思想有清晰的把握即可;而這部分的實驗較原始GAN需要修改的僅有四點,非常簡單,大家都可以試試。最後希望大家都能夠有所收穫,就像WGAN一樣穩定的進步,一起加油吧!!!🥂🥂🥂

 

參考鏈接

令人拍案叫絕的Wasserstein GAN 🍁🍁🍁

GAN:兩者分佈不重合JS散度為log2的數學證明 🍁🍁🍁

GAN — Wasserstein GAN & WGAN-GP 🍁🍁🍁

GAN — Spectral Normalization 🍁🍁🍁

李宏毅【機器學習2021】生成式對抗網路 🍁🍁🍁

   

如若文章對你有所幫助,那就🛴🛴🛴          一鍵三連 (1).gif