一文看懂生成式對抗網絡GANs:介紹指南及前景展望

 2017-08-08 16:07:19.0


神經網絡取得了長足的進步,目前識別圖像和聲音的水平已經和人類相當,在自然語言理解方面也達到了很好的效果。但即使如此,討論用機器來自動化人類任務看起來還是有些勉強。畢竟,我們做的不僅僅是識別圖像和聲音、或者了解我們周圍的人在說什麼,不是嗎?


讓我們看一些需要人類創造力的例子:


通過學習大數據文摘過去的文章,訓練一個可以撰寫文章並將數據科學概念以非常簡單的方式向社區解釋的人工智能作者


你不能從著名畫家那裡買到一幅名畫。但你可不可以創造一個人工智能畫家,通過從畫家過去的作品中學習,然後像任何藝術家一樣畫畫?



這些任務確實難以自動化,但是生成式對抗網絡(GAN)已經開始使其中的某些任務成為可能。


如果你感到被GAN的名字所嚇倒,別擔心,看完這篇科普文章你就會發現這不是一個高深莫測的東西。


在本文中,我將向您介紹GAN的概念,並解釋其工作原理和麵臨的挑戰。我還將讓你了解人們使用GAN所做的一些很酷的事情,並提供一些重要資源的鏈接,以深入了解這些技術。


不好意思,但是什麼是GAN?


深度學習領域的傑出代表Yann LeCun在Quora上寫道:


“生成式對抗網絡(GAN)及其相關的變化,是我認為的機器學習領域近十年最有趣的想法。”


當然他會有這樣的觀點。當我看到生成式對抗網絡被最大程度執行時的驚人表現,我也同樣印象深刻。


但是什麼是GAN呢?


讓我用個類比來解釋這個概念:


如果你想更加擅長某種東西,比如下棋,你會怎麼做?你可能會和比你更強的對手對弈。你會分析你做錯了什麼、對方做對了什麼,並思考下一場比賽如何才能擊敗他(她)。


你會重複這一步驟,直到你擊敗對手。這個概念可以被納入到構建更好的模型中。所以簡單來說,要獲得一個強大的英雄(即生成器generator),我們需要一個更強大的對手(即鑑別器discriminator)。


真實生活的另一個類比:


一個更真實的類比是偽造者和調查員之間的關係。




偽造者的任務是模仿著名藝術家的畫作。如果這個偽造的作品能夠超越原始的作品,那麼這個偽造者就可以賣出這張作品換很多錢。


另一方面,藝術品調查員的任務是抓住這些造假的偽造者。怎麼做呢,他知道什麼屬性能把原作和贗品區分開來。通過檢驗手中的作品是否是真的,他可以評估自己的知識。


偽造者與調查員的競賽繼續進行,最終催生了世界級的調查員(很不幸以及世界級的偽造者)。這是一場善與惡之間的鬥爭。



GANs如何工作


我們已經知道了GAN的概要,現在繼續去了解細節部分。


正如我們看到的,GAN有兩個主要組成部分,生成器神經網絡(Generator Neural Network)和鑑別器神經網絡(Discriminator Neural Network)。




生成網絡採用隨機輸入,嘗試輸出數據樣本。在上述圖像中,我們可以看到生成器G(z)從p(z)獲取了輸入z,其中z是來自概率分佈p(z)的樣本。生成器產生一個數據,將其送入鑑別器網絡D(x)。鑑別網絡的任務是接收真實數據或者生成數據,並嘗試預測輸入是真實還是生成的。它需要一個來自pdata(x)的輸入x,其中pdata(x)是我們的真實數據分佈。 D(x)然後使用Sigmoid函數解決二元分類問題,並輸出0到1的值。


我們先定義GAN的標記符號:


Pdata(x) -> 真實數據的分佈

X -> pdata(x)的樣本

P(z) -> 生成器的分佈

Z -> p(z)的樣本

G(z) -> 生成網絡

D(x) -> 鑑別網絡



現在作為生成器和鑑別器之間的鬥爭,GAN的訓練已經完成。可以用數學表示為:




在我們的函數V(D,G)中,第一項是來自實際分佈(pdata(x))的數據通過鑑別器(也稱為最佳情況)的熵(Entropy)。鑑別器試圖將其最大化為1。第二項是來自隨機輸入(p(z))的數據通過發生器的熵。生成器產生一個假樣本, 通過鑑別器識別虛假(也稱為最壞的情況)。在這一項中,鑑別器嘗試將其最大化為0(即生成的數據是偽造的的概率的對數是0)。所以總體而言,鑑別器正在嘗試最大化函數V(D,G)。


另一方面,生成器的任務完全相反,它試圖最小化函數V(D,G),使真實數據和假數據之間的區別最小化。這就是說,生成器和鑑別器像在玩貓和老鼠的遊戲。


注意:這種訓練GAN的方法源自於博弈論中的Minimax Game。




如何訓練GAN




概括來講訓練階段包括順序完成的兩個階段——


第一階段:訓練鑑別器,凍結生成器(凍結意思是不訓練,神經網絡只向前傳播,不進行Backpropagation反向傳播)

第二階段:訓練生成器,凍結鑑別器。





訓練GAN的步驟


第1步:定義問題。你想生成假的圖像還是文字?你需要完全定義問題並收集數據。


第2步:定義GAN的架構。 GAN看起來是怎麼樣的,生成器和鑑別器應該是多層感知器還是卷積神經網絡?這一步取決於你要解決的問題。


第3步:用真實數據訓練鑑別器N個epoch。訓練鑑別器正確預測真實數據為真。這裡N可以設置為1到無窮大之間的任意自然數。


第4步:用生成器產生假的輸入數據,用來訓練鑑別器。訓練鑑別器正確預測假的數據為假。


第5步:用鑑別器的出入訓練生成器。當鑑別器被訓練後,將其預測值作為標記來訓練生成器。訓練生成器來迷惑鑑別器。


第6步:重複第3到第5步多個epoch


第7步:手動檢查假數據是否合理。如果看起來合適就停止訓練,否則回到第3步。這是一個手動任務,手動評估數據是檢查其假冒程度的最佳方式。當這個步驟結束時,就可以評估GAN是否表現良好。


喘口氣,看一下這項技術有什麼樣的含義。假設你有一個功能完整的生成器,可以復制幾乎任何東西。給你一些例子,你可以生成假新聞、不可思議的書籍和小說、自動應答服務等等。你可以擁有一個近乎現實的人工智能,一個真正的人工智能!這就是夢想。


伴隨GAN而來的挑戰


你可能會問,如果我們知道這些美麗的生物(怪物)能做什麼,為什麼現在什麼也沒發生?這是因為我們還僅僅只接觸到它的表面。在創造一個足夠好的GAN的過程中有太多的障礙還沒有清除。有一整個學術領域就是為了找出如何訓練GAN。


訓練GAN時最重要的障礙是穩定。你開始訓練GAN,如果鑑別器比與其對應的發生器更強大,則發生器將無法有效訓練。這反過來又會影響你的GAN的訓練。另一方面,如果鑑別器過於寬鬆,理論上它可以允許生成器產生任何圖像。這意味著你的GAN是無用的。


瀏覽GAN的穩定性的另一種方法是將其看做一個整體收斂的問題。生成器和鑑別器都是相互競爭的,力求領先對方一步。此外,他們依賴彼此進行有效的培訓。如果其中一個失敗,整個系統就會失敗。所以你必須確保它們不會崩掉。


這就像波斯王子遊戲中的影子一樣。你必須保衛自己免受影子的襲擊,它試圖殺死你。如果你殺死你的影子,你會死;但如果你不做任何事情,你也一定會死!


關於其他的問題,請參考 http://www.iangoodfellow.com/slides/2016-12-04-NIPS.pdf


注意:下面提到的圖像是由ImageNet數據集訓練的GAN生成的。


計數問題:GAN無法區分特定對像在某個位置應發生的數量。正如我們在下面看到的,它在頭上生成的眼睛個數比自然狀態更多。




透視問題:GAN無法適應3D對象。它不理解視角,即前視圖和後視圖之間的差異。如下所示,它給出3D對象的平面(2D)展開。




全局結構問題:與透視問題相同,GAN不了解整體結構。例如,在左下角的圖像中,它給出了一隻四足牛的生成圖像,即母牛站立在其後腿上,同時又站立在所有四條腿上。這在現實中絕對不可能!




大量的研究正被用來處理這些問題。很多比過去擁有更好結果的新模型被提出,比如DCGAN, WassersteinGan。



實現一個簡單的GAN


讓我們實現一個簡化的GAN來加強理論。我們將嘗試通過在Identify the Digits數據集上訓練GAN來生成數字。數據集包​​含了28x28的黑白圖像,所有圖像都是“.png”格式。我們的任務中只需要訓練集。你可以在這裡下載到數據: https://datahack.analyticsvidhya.com/contest/practice-problem-identify-the-digits/。


你需要安裝一些Python的包:


numpy

pandas

tensorflow

keras

keras_adversarial



在開始編寫代碼之前,讓我們先了解內部工作的原理,訓練GAN的偽代碼如下:




來源: http://papers.nips.cc/paper/5423-generative-adversarial


注意:這是在論文中發表的GAN的第一個實現。在最近論文的偽碼中可以看到許多改進和更新,例如在生成和鑑別網絡中添加批量歸一化(Batch Normalization),訓練生成器k等。


現在開始寫代碼!


首先導入所有模塊。

# import modules

%pylab inline


import os

import numpy as np

import pandas as pd

from scipy.misc import imread


import keras

from keras.models import Sequential

from keras.layers import Dense, Flatten, Reshape, InputLayer

from keras.regularizers import L1L2




為了讓確定性的隨機可複現,設置一個Seed值。


# to stop potential randomness

seed = 128

rng = np.random.RandomState(seed)



設置數據和工作目錄的路徑。


# set path

root_dir = os.path.abspath('.')

data_dir = os.path.join(root_dir, 'Data')



加載數據。


# load data

train = pd.read_csv(os.path.join(data_dir, 'Train', 'train.csv'))

test = pd.read_csv(os.path.join(data_dir, 'test.csv'))


temp = []

for img_name in train.filename:

    image_path = os.path.join(data_dir, 'Train', 'Images', 'train', img_name)

    img = imread(image_path, flatten=True)

    img = img.astype('float32')

    temp.append(img)

    

train_x = np.stack(temp)


train_x = train_x / 255.



我們繪製一個圖形看看數據是什麼樣的。


# print image

img_name = rng.choice(train.filename)

filepath = os.path.join(data_dir, 'Train', 'Images', 'train', img_name)


img = imread(filepath, flatten=True)


pylab.imshow(img, cmap='gray')

pylab.axis('off')

pylab.show()





定義稍後將要使用的變量。


# define variables


# define vars g_input_shape = 100 d_input_shape = (28, 28) hidden_​​1_num_units = 500 hidden_​​2_num_units = 500 g_output_num_units = 784 d_output_num_units = 1 epochs = 25 batch_size = 128


現在定義生成網絡和鑑別網絡。


# generator

model_1 = Sequential([

    Dense(units=hidden_1_num_units, input_dim=g_input_shape, activation='relu', kernel_regularizer=L1L2(1e-5, 1e-5)),


    Dense(units=hidden_2_num_units, activation='relu', kernel_regularizer=L1L2(1e-5, 1e-5)),

        

    Dense(units=g_output_num_units, activation='sigmoid', kernel_regularizer=L1L2(1e-5, 1e-5)),

    

    Reshape(d_input_shape),

])


# discriminator

model_2 = Sequential([

    InputLayer(input_shape=d_input_shape),

    

    Flatten(),

        

    Dense(units=hidden_1_num_units, activation='relu', kernel_regularizer=L1L2(1e-5, 1e-5)),


    Dense(units=hidden_2_num_units, activation='relu', kernel_regularizer=L1L2(1e-5, 1e-5)),

        

    Dense(units=d_output_num_units, activation='sigmoid', kernel_regularizer=L1L2(1e-5, 1e-5)),

])





這裡是我們神經網絡的架構。






我們現在定義GAN。首先導入一些重要模塊。


from keras_adversarial import AdversarialModel, simple_gan, gan_targets

from keras_adversarial import AdversarialOptimizerSimultaneous, normal_latent_sampling



編譯GAN並開始訓練。


gan = simple_gan(model_1, model_2, normal_latent_sampling((100,)))

model = AdversarialModel(base_model=gan,player_params=[model_1.trainable_weights, model_2.trainable_weights])

model.adversarial_compile(adversarial_optimizer=AdversarialOptimizerSimultaneous(), player_optimizers=['adam', 'adam'], loss='binary_crossentropy')


history = model.fit(x=train_x, y=gan_targets(train_x.shape[0]), epochs=10, batch_size=batch_size)


這是我們的GAN的樣子。




我們訓練10個Epoch後得到的圖表。


plt.plot(history.history['player_0_loss'])

plt.plot(history.history['player_1_loss'])

plt.plot(history.history['loss'])





訓練100個Epoch後,生成的圖像如下。


zsamples = np.random.normal(size=(10, 100))

pred = model_1.predict(zsamples)

for i in range(pred.shape[0]):

    plt.imshow(pred[i, :], cmap='gray')

    plt.show()






瞧!你已經建立了你的第一個生成模型!




GAN的應用


我們了解了這些事情的工作原理,以及訓練過程中的挑戰。我們現在將要看到使用GAN完成的前沿研究。


預測視頻中的下一幀:在視頻序列上訓練GAN,並預測下一步會發生什麼


                            


論文 : https://arxiv.org/pdf/1511.06380.pdf


增加圖像分辨率:從較低分辨率照片生成高分辨率照片




論文: https://arxiv.org/pdf/1609.04802.pdf


交互式圖像生成:繪製簡單的筆劃,讓GAN為你畫出令人印象深刻的圖畫


__ke_temp_url__


鏈接: https://github.com/junyanz/iGAN


圖像翻譯:從一個圖像生成另一個圖像。例如,左邊給出了帶標籤的街景,你可以用GAN生成真實的照片。在右邊,給出簡單的手提包繪畫草稿,你會得到真正的手提包。




論文: https://arxiv.org/pdf/1611.07004.pdf


文本到圖像生成:只需向GAN說你想看到什麼,就可以獲得一個所描述物體的真實照片。




論文: https://arxiv.org/pdf/1605.05396.pdf


資源


這裡有一些資源可以幫助你更深入地了解GAN:


關於GAN的論文: https://github.com/zhangqianhui/AdversarialNetsPapers


DeepLearning書中的有關章節:


http://www.deeplearningbook.org/contents/generative_models.html


Ian Goodfellow關於GAN的講座: https://channel9.msdn.com/Events/Neural-Information-Processing-Systems-Conference/Neural-Information-Processing-Systems-Conference-NIPS-2016/Generative-Adversarial-Networks


NIPS 2016關於訓練GAN的講座: https://www.youtube.com/playlist?list=PLJscN9YDD1buxCitmej1pjJkR5PMhenTF


我希望你現在對未來感到興奮,就像我第一次讀到GAN時一樣。它們將改變機器能為人類所做的事。想想吧,從準備新的食譜到創造圖畫,GAN擁有無限的可能性。


原文鏈接: https://www.analyticsvidhya.com/blog/2017/06/introductory-generative-adversarial-networks-gans/

文章來源:大数据文摘