轉自:https://zhuanlan.zhihu.com/p/24767059,感謝分享html
生成式對抗網絡(GAN)是近年來大熱的深度學習模型。最近正好有空看了這方面的一些論文,跑了一個GAN的代碼,因而寫了這篇文章來介紹一下GAN。
本文主要分爲三個部分:python
說到GAN第一篇要看的paper固然是Ian Goodfellow大牛的Generative Adversarial Networks(arxiv:https://arxiv.org/abs/1406.2661),這篇paper算是這個領域的開山之做。git
GAN的基本原理其實很是簡單,這裏以生成圖片爲例進行說明。假設咱們有兩個網絡,G(Generator)和D(Discriminator)。正如它的名字所暗示的那樣,它們的功能分別是:github
在訓練過程當中,生成網絡G的目標就是儘可能生成真實的圖片去欺騙判別網絡D。而D的目標就是儘可能把G生成的圖片和真實的圖片分別開來。這樣,G和D構成了一個動態的「博弈過程」。算法
最後博弈的結果是什麼?在最理想的狀態下,G能夠生成足以「以假亂真」的圖片G(z)。對於D來講,它難以斷定G生成的圖片到底是不是真實的,所以D(G(z)) = 0.5。數據庫
這樣咱們的目的就達成了:咱們獲得了一個生成式的模型G,它能夠用來生成圖片。bash
以上只是大體說了一下GAN的核心原理,如何用數學語言描述呢?這裏直接摘錄論文裏的公式:網絡
簡單分析一下這個公式:框架
下面這幅圖片很好地描述了這個過程:dom
那麼如何用隨機梯度降低法訓練D和G?論文中也給出了算法:
這裏紅框圈出的部分是咱們要額外注意的。第一步咱們訓練D,D是但願V(G, D)越大越好,因此是加上梯度(ascending)。第二步訓練G時,V(G, D)越小越好,因此是減去梯度(descending)。整個訓練過程交替進行。
咱們知道深度學習中對圖像處理應用最好的模型是CNN,那麼如何把CNN與GAN結合?DCGAN是這方面最好的嘗試之一(論文地址:[1511.06434] Unsupervised Representation Learning with Deep Convolutional Generative Adversarial Networks)
DCGAN的原理和GAN是同樣的,這裏就不在贅述。它只是把上述的G和D換成了兩個卷積神經網絡(CNN)。但不是直接換就能夠了,DCGAN對卷積神經網絡的結構作了一些改變,以提升樣本的質量和收斂的速度,這些改變有:
DCGAN中的G網絡示意:
好了,上面說了一通原理,下面說點有意思的實踐部分的內容。
DCGAN的原做者用DCGAN生成LSUN的臥室圖片,這並非特別有意思。以前在網上看到一篇文章 Chainerで顔イラストの自動生成 - Qiita ,是用DCGAN生成動漫人物頭像的,效果以下:
這是個頗有趣的實踐內容。惋惜原文是用Chainer作的,這個框架使用的人很少。下面咱們就在Tensorflow中復現這個結果。
1. 原始數據集的蒐集
首先咱們須要用爬蟲爬取大量的動漫圖片,原文是在這個網站:http://safebooru.donmai.us/中爬取的。我嘗試的時候,發如今個人網絡環境下沒法訪問這個網站,因而我就寫了一個簡單的爬蟲爬了另一個著名的動漫圖庫網站:konachan.net - Konachan.com Anime Wallpapers。
爬蟲代碼以下:
import requests from bs4 import BeautifulSoup import os import traceback def download(url, filename): if os.path.exists(filename): print('file exists!') return try: r = requests.get(url, stream=True, timeout=60) r.raise_for_status() with open(filename, 'wb') as f: for chunk in r.iter_content(chunk_size=1024): if chunk: # filter out keep-alive new chunks f.write(chunk) f.flush() return filename except KeyboardInterrupt: if os.path.exists(filename): os.remove(filename) raise KeyboardInterrupt except Exception: traceback.print_exc() if os.path.exists(filename): os.remove(filename) if os.path.exists('imgs') is False: os.makedirs('imgs') start = 1 end = 8000 for i in range(start, end + 1): url = 'http://konachan.net/post?page=%d&tags=' % i html = requests.get(url).text soup = BeautifulSoup(html, 'html.parser') for img in soup.find_all('img', class_="preview"): target_url = 'http:' + img['src'] filename = os.path.join('imgs', target_url.split('/')[-1]) download(target_url, filename) print('%d / %d' % (i