新手必看:生成對抗網絡的初學者入門指導
https://mp.weixin.qq.com/s/GqfFh83Xo6q1un1V4KIOdA
本文為 AI 研習社編譯的技術博客,原標題 A Beginner's Guide to Generative Adversarial Networks (GANs)。
翻譯 | 江舟 校對 | 江舟 整理 | 志豪
原文鏈接:
https://skymind.ai/wiki/generative-adversarial-network-gan
你可能不認為程序員是藝術家,但編程的確是一門非常有創意的職業。它是一種基於邏輯的創造力體現。 - John Romero
生成對抗網絡(GANs)是由兩個網絡組成的深度神經網絡體系結構,它將一個網絡與另一個網絡相互對立(因此稱為“對抗性”)。
2014年,Ian Goodfellow和包括Yoshua Bengio在內的蒙特利爾大學的其他研究人員在一篇論文中介紹了GANs。Facebook的人工智能研究主管Yann LeCun稱對抗訓練是“在過去10年中最有趣的機器學習想法”。
GANs的潛力是巨大的,因為他們可以學習模仿任何數據分布。也就是說,GANs可以被教導在任何領域內創造與我們相似的世界:圖像、音樂、演講、散文。從某種意義上來說,他們是機器人藝術家,他們的作品令人印象深刻—甚至令人心酸。
生成算法與判別算法
為了理解GANs,你應該知道生成算法是如何工作的,為此,就可以將它與判別算法進行對比。 判別算法試圖對輸入數據進行分類; 也就是說,給定數據實例的特征,它們會預測數據所屬的標簽或類別。
例如,給定電子郵件中的所有單詞,判別算法可以預測消息是否為 spam (垃圾郵件)或者 not_spam (非垃圾郵件)。spam 是標簽之一,從電子郵件中收集的單詞袋構成了輸入數據的特征。當以數學方式表達此問題時,這個標簽被稱為 y 並且特征被稱為 x 。公式是 P(y|x),它用於表示“在給定x情況下的y發生的概率”,在前述問題情況下,這將轉換為“判斷給定包含的單詞下,電子郵件是垃圾郵件的概率”。
因此,判別算法是將特征映射到標簽。他們只關心這種相關性。 而生成算法是做相反的事情。 他們嘗試預測給定某個標簽的特征,而不是預測給定某些特征的標簽。
生成算法試圖回答的問題是:假設這封電子郵件是垃圾郵件,這些特征的可能性有多大? 雖然判別模型關心的是 y 和 x 的關系,生成模型關心的是“你怎樣得到 x 的”,然后得到 P(x|y) ,意思是給定 y 條件下的 x 發生的概率,或叫給定一個類的特征的概率。(也就是說,生成算法也可以用作分類器。恰好它們能做的不僅僅是對輸入數據進行分類)
另一種思考方式是將判別與生成區分開來,如下所示:
- 判別模型學習類之間的界限。
- 生成模型對單個類的分布進行建模。
GANs是如何工作的
生成器,是一個用來生成新的數據實例的神經網絡;鑒別器,則是用來評估其真實性的神經網絡。即,鑒別器決定它所審查的每個數據實例是否屬於實際訓練數據集。
讓我們做些比模仿蒙娜麗莎要平庸的事情。我們將生成類似於MNIST數據集的手寫數字,該數據集取自真實世界。 當從真實的MNIST數據集中顯示實例給鑒別器時,鑒別器的目標是將它們識別為真的。
與此同時,生成器在創建新的圖像,並將其傳遞給鑒別器。這樣做是希望它們也能被認為是真實的,即使它們是假的。生成器的目標是生成可通過檢測的手寫數字,以便在即使說謊下也不被抓住。 鑒別器的目標是將來自生成器的圖像識別為假的。
以下是生成對抗網絡運行的步驟:
- 生成器接收一系列隨機數並返回一張圖像。
- 將生成的圖像與從實際數據集中獲取的圖像流一起送到鑒別器中。
- 鑒別器接收真實和假圖像並返回概率值,這是一個介於0和1之間的數字,1代表為真,0則代表假。
所以就會有一個雙重反饋回路:
- 鑒別器處在包含圖像真相的反饋回路中。
- 生成器處在鑒別器的反饋回路中。
圖像來源: O’Reilly
你可以認為GAN是貓鼠游戲中偽造者和警察的組合,偽造者在學習傳遞假鈔,警察在學習檢測假鈔。兩者都是動態的;也就是說,警察也在接受培訓(也許中央銀行正在標記漏報的賬單),雙方都在不斷升級中學習對方的方法。
鑒別器網絡是標准的卷積網絡,它可以將饋送給它的圖像分類,它用二項式分類器標記圖像是真的還是假的。從某種意義上說,生成器是一個反向卷積網絡:當標准卷積分類器獲取圖像並對其進行下采樣以產生概率時,發生器獲取隨機噪聲向量並將其上采樣得到圖像。第一個通過下采樣技術(如maxpooling)丟棄數據,第二個生成新數據。
兩個網絡都試圖在零和博奕中優化不同的且對立的目標函數,或者說損失函數。這本質上是一個演員-評論模型。當鑒別器改變其行為時,生成器也隨之改變,反之亦然。他們的損耗也相互抗衡。
如果你想了解更多關於生成圖像的信息,Brandon Amos寫了一篇關於將圖像解釋為概率分布樣本的文章。
GANs、自動編碼器和變分自編碼器(VAE)
將生成對抗性網絡與其他神經網絡(如自動編碼器和變分自動編碼器)進行比較會是有幫助的。
自動編碼器將輸入數據編碼為向量。它創建原始數據的隱藏或壓縮表示。這在降維方面很有用;也就是說,用作隱藏表示的向量將原始數據壓縮成一個較小的主要維度。自動編碼器可以與所謂的解碼器配對,這允許基於隱藏的表示來重建輸入數據,這和受限玻爾茲曼機是相同的。
圖片來源: Keras博客
變分自動編碼器是一種生成算法,它為輸入數據的編碼增加了一個額外的約束,即把隱藏表示標准化。變分自動編碼器既能像自動編碼器一樣壓縮數據,又能像GAN一樣合成數據。然而,雖然GANs能以精細、細致的細節生成數據,VAEs生成的圖像則往往更加模糊。Deeplearning4j’s包中包括自動編碼器和變分自動編碼器。
生成算法可分成三種類型:
- 給定一個標簽,他們預測相關的特征(朴素貝葉斯)
- 給定一個隱藏表示,預測相關的特征( 變分自編碼器,生成對抗網絡 )
- 給定一些特征,預測其余特征(修復、插補)
訓練生成對抗網絡的技巧
訓練鑒別器時,保持生成器的值不變;訓練生成器時,則保持鑒別器不變。這使生成器能夠更好地讀取它必須學習的梯度變化。
同樣,在開始訓練生成器之前,要對用於MNIST數據集的鑒別器進行預訓練,這可以建立一個更佳清晰的梯度。
生成對抗網絡的每一方都可以壓制另一方。如果鑒別器太好,它將返回非常接近0或1的值,以至於生成器將難以讀取梯度。如果生成器太好,它會持續利用鑒別器中的弱點導致漏報情況。這可以通過網絡各自的學習率來緩解這種壓制。
GANs需要很長時間來訓練。在單個GPU上,GAN可能需要幾個小時,而在單個CPU上可能需要一天以上的時間。盡管GANs很難調整,因此也很難使用,但它激發了許多有趣的研究和寫作。
直接展示下代碼吧
以下是用Keras編碼的GAN示例,可以將模型導入Deeplearning4j。
class GAN():
def __init__(self):
self.img_rows = 28
self.img_cols = 28
self.channels = 1
self.img_shape = (self.img_rows, self.img_cols, self.channels)
optimizer = Adam(0.0002, 0.5)
# Build and compile the discriminator
self.discriminator = self.build_discriminator()
self.discriminator.compile(loss='binary_crossentropy',
optimizer=optimizer,
metrics=['accuracy'])
# Build and compile the generator
self.generator = self.build_generator()
self.generator.compile(loss='binary_crossentropy', optimizer=optimizer)
# The generator takes noise as input and generated imgs
z = Input(shape=(100,))
img = self.generator(z)
# For the combined model we will only train the generator
self.discriminator.trainable = False
# The valid takes generated images as input and determines validity
valid = self.discriminator(img)
# The combined model (stacked generator and discriminator) takes
# noise as input => generates images => determines validity
self.combined = Model(z, valid)
self.combined.compile(loss='binary_crossentropy', optimizer=optimizer)
def build_generator(self):
noise_shape = (100,)
model = Sequential()
model.add(Dense(256, input_shape=noise_shape))
model.add(LeakyReLU(alpha=0.2))
model.add(BatchNormalization(momentum=0.8))
model.add(Dense(512))
model.add(LeakyReLU(alpha=0.2))
model.add(BatchNormalization(momentum=0.8))
model.add(Dense(1024))
model.add(LeakyReLU(alpha=0.2))
model.add(BatchNormalization(momentum=0.8))
model.add(Dense(np.prod(self.img_shape), activation='tanh'))
model.add(Reshape(self.img_shape))
model.summary()
noise = Input(shape=noise_shape)
img = model(noise)
return Model(noise, img)
def build_discriminator(self):
img_shape = (self.img_rows, self.img_cols, self.channels)
model = Sequential()
model.add(Flatten(input_shape=img_shape))
model.add(Dense(512))
model.add(LeakyReLU(alpha=0.2))
model.add(Dense(256))
model.add(LeakyReLU(alpha=0.2))
model.add(Dense(1, activation='sigmoid'))
model.summary()
img = Input(shape=img_shape)
validity = model(img)
return Model(img, validity)
def train(self, epochs, batch_size=128, save_interval=50):
# Load the dataset
(X_train, _), (_, _) = mnist.load_data()
# Rescale -1 to 1
X_train = (X_train.astype(np.float32) - 127.5) / 127.5
X_train = np.expand_dims(X_train, axis=3)
half_batch = int(batch_size / 2)
for epoch in range(epochs):
# ---------------------
# Train Discriminator
# ---------------------
# Select a random half batch of images
idx = np.random.randint(0, X_train.shape[0], half_batch)
imgs = X_train[idx]
noise = np.random.normal(0, 1, (half_batch, 100))
# Generate a half batch of new images
gen_imgs = self.generator.predict(noise)
# Train the discriminator
d_loss_real = self.discriminator.train_on_batch(imgs, np.ones((half_batch, 1)))
d_loss_fake = self.discriminator.train_on_batch(gen_imgs, np.zeros((half_batch, 1)))
d_loss = 0.5 * np.add(d_loss_real, d_loss_fake)
# ---------------------
# Train Generator
# ---------------------
noise = np.random.normal(0, 1, (batch_size, 100))
# The generator wants the discriminator to label the generated samples
# as valid (ones)
valid_y = np.array([1] * batch_size)
# Train the generator
g_loss = self.combined.train_on_batch(noise, valid_y)
# Plot the progress
print ("%d [D loss: %f, acc.: %.2f%%] [G loss: %f]" % (epoch, d_loss[0], 100*d_loss[1], g_loss))
# If at save interval => save generated image samples
if epoch % save_interval == 0:
self.save_imgs(epoch)
def save_imgs(self, epoch):
r, c = 5, 5
noise = np.random.normal(0, 1, (r * c, 100))
gen_imgs = self.generator.predict(noise)
# Rescale images 0 - 1
gen_imgs = 0.5 * gen_imgs + 0.5
fig, axs = plt.subplots(r, c)
cnt = 0
for i in range(r):
for j in range(c):
axs[i,j].imshow(gen_imgs[cnt, :,:,0], cmap='gray')
axs[i,j].axis('off')
cnt += 1
fig.savefig("gan/images/mnist_%d.png" % epoch)
plt.close()
if __name__ == '__main__':
gan = GAN()
gan.train(epochs=30000, batch_size=32, save_interval=200)
圖片提供:《紐約客》
生成對抗網絡的學習資源
生成性學習算法 —吳恩達斯坦福學習筆記
鑒別器與生成器:邏輯回歸與朴素貝葉斯比較。作者:Andrew Ng和Michael I. Jordan
生成對抗網絡背后的數學
生成對抗網絡應用案例
文本到圖像的生成
圖像到圖像的轉換
圖像分辨率的提高
預測下一個視頻幀
關於生成對抗網絡的著名論文
生成對抗網絡(Ian Goodfellow的突破性論文)
未分類論文和資源
GAN Hacks:如何訓練GAN?讓GAN發揮作用的技巧和訣竅
使用拉普拉斯金字塔形的對抗網絡的深層生成圖像模型
對抗性自動編碼器
基於深度網絡生成具有感知相似性度量的圖像
用循環對抗網絡生成圖像
自然圖像流形上的生成視覺操縱
學習什么和在哪里畫
草圖檢索的對抗訓練
使用樣式和結構對抗網絡的生成圖像建模
生成對抗網絡作為能量模型的變分訓練(ICLR2017)
基於深度生成網絡合成神經元的首選輸入
SalGAN:利用生成對抗網絡的視覺顯著性預測
對抗性特征學習
高質量圖像的生成
采用深度卷積生成對抗網絡的無監督表示學習(使用卷積網絡的GAN ) ( ICLR )
生成對抗文本到圖像合成
改進的生成對抗網絡技術(Goodfellow的論文)
即插即用生成網絡:潛在空間圖像的條件迭代生成
StackGAN:采用生成對抗網絡的文本到照片般真實的圖像合成與疊加
對Wasserstein 生成對抗網絡的改進訓練
邊界均衡生成對抗網絡在Tensorflow中的實現
生成對抗網絡的質量、穩定性和變異性的穩步增長
半監督學習
半監督文本分類的對抗訓練方法(IanGoodfellow論文)
訓練GAN的改進技術(Goodfellow論文)
分類生成對抗網絡的無監督和半監督學( ICLR )
具有生成域自適應網絡的半監督QA(ACL 2017)
合奏
AdaGAN:提升生成模型(谷歌大腦)
聚類
采用分類生成對抗網絡的無監督和半監督學習(ICLR)
圖像混合
GP-GAN:高分辨率圖像混合的實現
圖像修復
具有感知和上下文損失的語義圖像修復(CVPR 2017)
上下文編碼器:通過修復進行特征學習
采用上下文條件生成對抗網絡的半監督學習
面部生成的實現(CVPR2017)
全球和本地一致的圖像完成(SIGGRAPH 2017)
聯合概率
對抗學習推論
超分辨率
經過深度學習的超分辨率圖像重建(僅適用於面部數據集)
使用生成對抗網絡生成照片般真實的超分辨率圖像(使用深度殘留網絡)
EnhanceGAN
去遮擋
采用魯棒性好的LSTM自動編碼器在野外去除遮擋
語義分割
用於乳腺腫塊分割的對抗性深層結構網絡
使用對抗網絡的語義分割(Soumith的論文)
對象檢測
用於小物體檢測的感知生成對抗網(CVPR 2017)
A-Fast-RCNN:通過對抗進行對象檢測的硬件生成(CVPR2017)
RNN - GANs
C-RNN-GAN:具有對抗訓練的連續遞歸神經網絡
條件對抗網絡
條件生成對抗網絡
InfoGAN:利用信息最大化生成對抗網絡的可解釋表示學習
輔助分類生成對抗網絡的條件圖像合成(GoogleBrain ICLR 2017)
像素級區域轉移
用於圖像編輯的可變條件生成對抗網絡
即插即用生成網絡:潛在空間圖像的條件迭代生成
StackGAN:采用生成對抗網絡的文本到照片般圖像的合成與疊加
MaskGAN:通過填寫_______更好地生成文本(Goodfellow論文)
視頻預測和生成
基於均方誤差的深度multi-scale視頻預測(Yann LeCun的論文)
使用場景動態生成視頻
MoCoGAN:使用分解動作及內容生成視頻
紋理合成和樣式轉換
預計算實時紋理合成與馬爾可夫生成對抗網絡(ECCV 2016)
圖像翻譯
無監督的跨領域圖像生成
基於條件對抗網進行圖像到圖像的轉譯
學習使用生成對抗網絡探索跨域之間的關系
使用循環一致對抗網絡對不成對圖像間的轉譯
CoGAN:耦合生成對抗網絡(NIPS 2016)
基於生成對抗網絡的無監督圖像間轉譯
無監督圖像間轉譯網絡
三角生成對抗網絡
生成對抗網絡理論
基於能量的生成對抗網絡(Lecun論文)
改進的訓練生成對抗網絡技術(Goodfellow的論文)
模式正則化生成對抗網絡(Yoshua Bengio,ICLR 2017)
利用去噪特征匹配改進生成對抗網絡(Yoshua Bengio,ICLR 2017)
采樣生成網絡
如何生成對抗網絡
訓練生成對抗網絡的原則性方法(ICLR 2017)
生成對抗網絡的展開論述(ICLR 2017)
最小二乘生成對抗網絡(ICCV 2017)
Wasserstein 生成對抗網絡
Wasserstein 生成對抗網絡的改進訓練(改進wgan)
訓練生成對抗網絡的原則方法
生成對抗網的泛化與均衡(ICML 2017)
三維生成對抗網絡
通過三維生成對抗建模學習對象形狀的概率潛在空間(2016 NIPS)
用於新型3D視圖合成的Transformation-Grounded圖像生成網絡(CVPR 2017)
音樂
MidiNet:一維和二維條件下音符生成的卷積生成對抗網絡
面部生成和編輯
使用已學習的相似性度量對像素進行自動編碼
耦合生成對抗網絡(NIPS)
用於圖像編輯的可變條件生成對抗網絡
為面部屬性操作學習殘留圖像(CVPR 2017)
采用Introspective對抗網絡的神經圖像編輯(ICLR 2017)
使用內在圖像解纏的神經面編輯(CVPR 2017)
GeneGAN:從不成對數據中學習對象變形和屬性子空間(BMVC 2017)
臉部旋轉:用於正面視圖合成的全局及局部感知生成對抗網絡(ICCV 2017)
對於離散分布
最大似然擴張離散生成對抗網絡
Boundary-Seeking生成對抗網絡
采用Gumbel-softmax分布的離散生成對抗網絡
改進分類器和識別器
用於多類開放集分類的生成OpenMax(BMVC 2017)
對抗性特征學習的可控不變性(NIPS 2017)
生成對抗網絡生成未標記樣例改善行人重識別基線(ICCV2017)
通過對抗訓練從模擬和非監督圖像中學習(Apple論文,CVPR 2017年最佳論文)
項目
對抗機器學習庫cleverhans
重置-CPPN-生成對抗網絡-Tensorflow(使用殘余生成對抗網絡和變分自動編碼器技術生成高分辨率圖像)
HyperGAN(專注於規模和可用性的開源GAN)
教程
[1] Ian Goodfellow的生成對抗網絡幻燈片(NIPS Goodfellow Slides)[中文翻譯版]
[2] PDF(NIPS Lecun 幻燈片)
[3]關於GANS的ICCV 2017教程
想要繼續查看該篇文章更多代碼、鏈接和參考文獻?
戳鏈接:
http://www.gair.link/page/TextTranslation/1050