天天看點

最簡單易懂的GAN(生成對抗網絡)教程:從理論到實踐(附代碼)

gan網絡是近兩年深度學習領域的新秀,火的不行,本文旨在淺顯了解傳統gan,分享學習心得。現有gan網絡大多數代碼實作使用python、torch等語言,這裡,後面用matlab搭建一個簡單的gan網絡,便于了解gan原理。

● 分享一個目前各類gan的一個論文整理集合 ● 再分享一個目前各類gan的一個代碼整理集合

我們知道gan的思想是是一種二人零和博弈思想(two-player game),博弈雙方的利益之和是一個常數,比如兩個人掰手腕,假設總的空間是一定的,你的力氣大一點,那你就得到的空間多一點,相應的我的空間就少一點,相反我力氣大我就得到的多一點,但有一點是确定的就是,我兩的總空間是一定的,這就是二人博弈,但是呢總利益是一定的。

引申到gan裡面就是可以看成,gan中有兩個這樣的博弈者,一個人名字是生成模型(g),另一個人名字是判别模型(d)。他們各自有各自的功能。

相同點是:

● 這兩個模型都可以看成是一個黑匣子,接受輸入然後有一個輸出,類似一個函數,一個輸入輸出映射。

不同點是:

● 生成模型功能:比作是一個樣本生成器,輸入一個噪聲/樣本,然後把它包裝成一個逼真的樣本,也就是輸出。

● 判别模型:比作一個二分類器(如同0-1分類器),來判斷輸入的樣本是真是假。(就是輸出值大于0.5還是小于0.5);

直接上一張個人覺得解釋的好的圖說明: 

最簡單易懂的GAN(生成對抗網絡)教程:從理論到實踐(附代碼)

在之前,我們首先明白在使用gan的時候的2個問題

● 我們有什麼? 

比如上面的這個圖,我們有的隻是真實采集而來的人臉樣本資料集,僅此而已,而且很關鍵的一點是我們連人臉資料集的類标簽都沒有,也就是我們不知道那個人臉對應的是誰。

● 我們要得到什麼 

至于要得到什麼,不同的任務得到的東西不一樣,我們隻說最原始的gan目的,那就是我們想通過輸入一個噪聲,模拟得到一個人臉圖像,這個圖像可以非常逼真以至于以假亂真。

好了再來了解下gan的兩個模型要做什麼。首先判别模型,就是圖中右半部分的網絡,直覺來看就是一個簡單的神經網絡結構,輸入就是一副圖像,輸出就是一個機率值,用于判斷真假使用(機率值大于0.5那就是真,小于0.5那就是假),真假也不過是人們定義的機率而已。其次是生成模型,生成模型要做什麼呢,同樣也可以看成是一個神經網絡模型,輸入是一組随機數z,輸出是一個圖像,不再是一個數值而已。從圖中可以看到,會存在兩個資料集,一個是真實資料集,這好說,另一個是假的資料集,那這個資料集就是有生成網絡造出來的資料集。好了根據這個圖我們再來了解一下gan的目标是要幹什麼:

● 判别網絡的目的:就是能判别出來屬于的一張圖它是來自真實樣本集還是假樣本集。假如輸入的是真樣本,網絡輸出就接近1,輸入的是假樣本,網絡輸出接近0,那麼很完美,達到了很好判别的目的。

● 生成網絡的目的:生成網絡是造樣本的,它的目的就是使得自己造樣本的能力盡可能強,強到什麼程度呢,你判别網絡沒法判斷我是真樣本還是假樣本。

有了這個了解我們再來看看為什麼叫做對抗網絡了。判别網絡說,我很強,來一個樣本我就知道它是來自真樣本集還是假樣本集。生成網絡就不服了,說我也很強,我生成一個假樣本,雖然我生成網絡知道是假的,但是你判别網絡不知道呀,我包裝的非常逼真,以至于判别網絡無法判斷真假,那麼用輸出數值來解釋就是,生成網絡生成的假樣本進去了判别網絡以後,判别網絡給出的結果是一個接近0.5的值,極限情況就是0.5,也就是說判别不出來了,這就是納什平衡了。

由這個分析可以發現,生成網絡與判别網絡的目的正好是相反的,一個說我能判别的好,一個說我讓你判别不好。是以叫做對抗,叫做博弈。那麼最後的結果到底是誰赢呢?這就要歸結到設計者,也就是我們希望誰赢了。作為設計者的我們,我們的目的是要得到以假亂真的樣本,那麼很自然的我們希望生成樣本赢了,也就是希望生成樣本很真,判别網絡能力不足以區分真假樣本位置。

知道了gan大概的目的與設計思路,那麼一個很自然的問題來了就是我們該如何用數學方法解決這麼一個對抗問題。這就涉及到如何訓練這樣一個生成對抗網絡模型了,還是先上一個圖,用圖來解釋最直接: 

最簡單易懂的GAN(生成對抗網絡)教程:從理論到實踐(附代碼)

需要注意的是生成模型與對抗模型可以說是完全獨立的兩個模型,好比就是完全獨立的兩個神經網絡模型,他們之間沒有什麼聯系。

好了那麼訓練這樣的兩個模型的大方法就是:單獨交替疊代訓練。

什麼意思?因為是2個網絡,不好一起訓練,是以才去交替疊代訓練,我們一一來看。 

假設現在生成網絡模型已經有了(當然可能不是最好的生成網絡),那麼給一堆随機數組,就會得到一堆假的樣本集(因為不是最終的生成模型,那麼現在生成網絡可能就處于劣勢,導緻生成的樣本就不咋地,可能很容易就被判别網絡判别出來了說這貨是假冒的),但是先不管這個,假設我們現在有了這樣的假樣本集,真樣本集一直都有,現在我們人為的定義真假樣本集的标簽,因為我們希望真樣本集的輸出盡可能為1,假樣本集為0,很明顯這裡我們就已經預設真樣本集所有的類标簽都為1,而假樣本集的所有類标簽都為0. 有人會說,在真樣本集裡面的人臉中,可能張三人臉和李四人臉不一樣呀,對于這個問題我們需要了解的是,我們現在的任務是什麼,我們是想分樣本真假,而不是分真樣本中那個是張三label、那個是李四label。況且我們也知道,原始真樣本的label我們是不知道的。回過頭來,我們現在有了真樣本集以及它們的label(都是1)、假樣本集以及它們的label(都是0),這樣單就判别網絡來說,此時問題就變成了一個再簡單不過的有監督的二分類問題了,直接送到神經網絡模型中訓練就完事了。假設訓練完了,下面我們來看生成網絡。

對于生成網絡,想想我們的目的,是生成盡可能逼真的樣本。那麼原始的生成網絡生成的樣本你怎麼知道它真不真呢?就是送到判别網絡中,是以在訓練生成網絡的時候,我們需要聯合判别網絡一起才能達到訓練的目的。什麼意思?就是如果我們單單隻用生成網絡,那麼想想我們怎麼去訓練?誤差來源在哪裡?細想一下沒有,但是如果我們把剛才的判别網絡串接在生成網絡的後面,這樣我們就知道真假了,也就有了誤差了。是以對于生成網絡的訓練其實是對生成-判别網絡串接的訓練,就像圖中顯示的那樣。好了那麼現在來分析一下樣本,原始的噪聲數組z我們有,也就是生成了假樣本我們有,此時很關鍵的一點來了,我們要把這些假樣本的标簽都設定為1,也就是認為這些假樣本在生成網絡訓練的時候是真樣本。那麼為什麼要這樣呢?我們想想,是不是這樣才能起到迷惑判别器的目的,也才能使得生成的假樣本逐漸逼近為正樣本。好了,重新順一下思路,現在對于生成網絡的訓練,我們有了樣本集(隻有假樣本集,沒有真樣本集),有了對應的label(全為1),是不是就可以訓練了?有人會問,這樣隻有一類樣本,訓練啥呀?誰說一類樣本就不能訓練了?隻要有誤差就行。還有人說,你這樣一訓練,判别網絡的網絡參數不是也跟着變嗎?沒錯,這很關鍵,是以在訓練這個串接的網絡的時候,一個很重要的操作就是不要判别網絡的參數發生變化,也就是不讓它參數發生更新,隻是把誤差一直傳,傳到生成網絡那塊後更新生成網絡的參數。這樣就完成了生成網絡的訓練了。

在完成生成網絡訓練好,那麼我們是不是可以根據目前新的生成網絡再對先前的那些噪聲z生成新的假樣本了,沒錯,并且訓練後的假樣本應該是更真了才對。然後又有了新的真假樣本集(其實是新的假樣本集),這樣又可以重複上述過程了。我們把這個過程稱作為單獨交替訓練。我們可以實作定義一個疊代次數,交替疊代到一定次數後停止即可。這個時候我們再去看一看噪聲z生成的假樣本會發現,原來它已經很真了。

看完了這個過程是不是感覺gan的設計真的很巧妙,個人覺得最值得稱贊的地方可能在于這種假樣本在訓練過程中的真假變換,這也是博弈得以進行的關鍵之處。

文字的描述相信已經讓大多數的人知道了這個過程,下面我們來看看原文中幾個重要的數學公式描述,首先我們直接上原始論文中的目标公式吧:

最簡單易懂的GAN(生成對抗網絡)教程:從理論到實踐(附代碼)

上述這個公式說白了就是一個最大最小優化問題,其實對應的也就是上述的兩個優化過程。有人說如果不看别的,能達看到這個公式就拍案叫絕的地步,那就是機器學習的頂級專家,哈哈,真是前路漫漫。同時也說明這個簡單的公式意義重大。

這個公式既然是最大最小的優化,那就不是一步完成的,其實對比我們的分析過程也是這樣的,這裡現優化d,然後在取優化g,本質上是兩個優化問題,把拆解就如同下面兩個公式:

優化d:

最簡單易懂的GAN(生成對抗網絡)教程:從理論到實踐(附代碼)

優化g:

最簡單易懂的GAN(生成對抗網絡)教程:從理論到實踐(附代碼)

可以看到,優化d的時候,也就是判别網絡,其實沒有生成網絡什麼事,後面的g(z)這裡就相當于已經得到的假樣本。優化d的公式的第一項,使的真樣本x輸入的時候,得到的結果越大越好,可以了解,因為需要真樣本的預測結果越接近于1越好嘛。對于假樣本,需要優化是的其結果越小越好,也就是d(g(z))越小越好,因為它的标簽為0。但是呢第一項是越大,第二項是越小,這不沖突了,是以呢把第二項改成1-d(g(z)),這樣就是越大越好,兩者合起來就是越大越好。 那麼同樣在優化g的時候,這個時候沒有真樣本什麼事,是以把第一項直接卻掉了。這個時候隻有假樣本,但是我們說這個時候是希望假樣本的标簽是1的,是以是d(g(z))越大越好,但是呢為了統一成1-d(g(z))的形式,那麼隻能是最小化1-d(g(z)),本質上沒有差別,隻是為了形式的統一。之後這兩個優化模型可以合并起來寫,就變成了最開始的那個最大最小目标函數了。

是以回過頭來我們來看這個最大最小目标函數,裡面包含了判别模型的優化,包含了生成模型的以假亂真的優化,完美的闡釋了這樣一個優美的理論。

有人說gan強大之處在于可以自動的學習原始真實樣本集的資料分布,不管這個分布多麼的複雜,隻要訓練的足夠好就可以學出來。針對這一點,感覺有必要好好了解一下為什麼别人會這麼說。

我們知道,傳統的機器學習方法,我們一般都會定義一個什麼模型讓資料去學習。比如說假設我們知道原始資料屬于高斯分布呀,隻是不知道高斯分布的參數,這個時候我們定義高斯分布,然後利用資料去學習高斯分布的參數得到我們最終的模型。再比如說我們定義一個分類器,比如svm,然後強行讓資料進行東變西變,進行各種高維映射,最後可以變成一個簡單的分布,svm可以很輕易的進行二分類分開,其實svm已經放松了這種映射關系了,但是也是給了一個模型,這個模型就是核映射(什麼徑向基函數等等),說白了其實也好像是你事先知道讓資料該怎麼映射一樣,隻是核映射的參數可以學習罷了。所有的這些方法都在直接或者間接的告訴資料你該怎麼映射一樣,隻是不同的映射方法能力不一樣。那麼我們再來看看gan,生成模型最後可以通過噪聲生成一個完整的真實資料(比如人臉),說明生成模型已經掌握了從随機噪聲到人臉資料的分布規律了,有了這個規律,想生成人臉還不容易。然而這個規律我們開始知道嗎?顯然不知道,如果讓你說從随機噪聲到人臉應該服從什麼分布,你不可能知道。這是一層層映射之後組合起來的非常複雜的分布映射規律。然而gan的機制可以學習到,也就是說gan學習到了真實樣本集的資料分布。

再拿原論文中的一張圖來解釋: 

最簡單易懂的GAN(生成對抗網絡)教程:從理論到實踐(附代碼)

這張圖表明的是gan的生成網絡如何一步步從均勻分布學習到正太分布的。原始資料x服從正太分布,這個過程你也沒告訴生成網絡說你得用正太分布來學習,但是生成網絡學習到了。假設你改一下x的分布,不管什麼分布,生成網絡可能也能學到。這就是gan可以自動學習真實資料的分布的強大之處。

還有人說gan強大之處在于可以自動的定義潛在損失函數。 什麼意思呢,這應該說的是判别網絡可以自動學習到一個好的判别方法,其實就是等效的了解為可以學習到好的損失函數,來比較好或者不好的判别出來結果。雖然大的loss函數還是我們人為定義的,基本上對于多數gan也都這麼定義就可以了,但是判别網絡潛在學習到的損失函數隐藏在網絡之中,不同的問題這個函數就不一樣,是以說可以自動學習這個潛在的損失函數。

網絡結構很簡單,就定義成下面這樣子: 

最簡單易懂的GAN(生成對抗網絡)教程:從理論到實踐(附代碼)

将上述工具箱添加到路徑,然後運作下面代碼:

函數nn_g_out為:

看一下這個及其簡單的函數,其實最值得注意的就是中間那個交替訓練的過程,這裡我分了三步列出來:

● 重新計算假樣本(假樣本每次是需要更新的,産生越來越像的樣本) ● 訓練d網絡,一個二分類的神經網絡; ● 訓練g網絡,一個串聯起來的長網絡,也是一個二分類的神經網絡(不過隻有假樣本來訓練),同時d部分參數在下一次的時候不能變了。

就這樣調一調參數,最終輸出在fin_output裡面,多運作幾次顯示不同運作次數下的結果:

最簡單易懂的GAN(生成對抗網絡)教程:從理論到實踐(附代碼)

可以看到的是結果還是有點像模像樣的。

運作上述簡單的網絡我發現幾個問題:

● 網絡存在着不收斂問題;網絡不穩定;網絡難訓練;讀過原論文其實作者也提到過這些問題,包括gan剛出來的時候,很多人也在緻力于解決這些問題,當你實驗自己碰到的時候,還是很有意思的。那麼這些問題怎麼展現的呢,舉個例子,可能某一次你會發現訓練的誤差很小,在下一代訓練時,馬上又出現極限性的上升的很厲害,過幾代又發現訓練誤差很小,震蕩太嚴重。

● 其次網絡需要調才能出像樣的結果。交替疊代次數的不同結果也不一樣。比如每一代訓練中,d網絡訓練2回,g網絡訓練一回,結果就不一樣。

● 這是簡單的無條件gan,是以每一代訓練完後,隻能出現一個結果,那就是0-9中的某一個數。要想在一代訓練中出現好幾種結果,就需要使用到條件gan了。

現在的gan已經到了五花八門的時候了,各種gan應用也很多,了解底層原理再慢慢往上層擴充。gan還是一個很厲害的東西,它使得現有問題從有監督學習慢慢過渡到無監督學習,而無監督學習才是自然界中普遍存在的,因為很多時候沒有辦法拿到監督資訊的。要不 yann lecun 贊歎 gan 是機器學習近十年來最有意思的想法。

====================================分割線================================

本文作者:ai研習社

繼續閱讀