1. 程式人生 > >Generative Adversarial Nets(GAN Tensorflow)

Generative Adversarial Nets(GAN Tensorflow)

概率 制造 display 變量 pan clas cli tps OS

Generative Adversarial Nets(簡稱GAN)是一種非常流行的神經網絡。 它最初是由Ian Goodfellow等人在NIPS 2014論文中介紹的。 這篇論文引發了很多關於神經網絡對抗性訓練的興趣,論文的引用次數已接近2700+。 許多變形的GAN出現了:DCGAN,Sequence-GAN,LSTM-GAN等。在NIPS 2016中,甚至會有整個專門針對對抗訓練的研討會

首先,讓我們回顧一下這篇論文的要點。 之後,我們將嘗試使用TensorFlow和MNIST數據實現GAN。

Generative Adversarial Nets

考慮兩個人,一個是制造假幣的犯罪分子,另一個是鑒別假幣的警察。 我們可以想象下犯罪分子的目標

是什麽,以及假冒偽劣貨幣的目的是什麽? 讓我們列舉一下:

  • 成為一個成功偽造假幣的犯罪分子,從而欺騙警察的“法眼”,這樣警察就不能分辨出偽造的錢和真錢之間的區別
  • 維護“正義”,警察希望盡可能地發現假幣

在此,我們看到了犯罪分子和警察之間存在利益沖突。 這種情況可以看成是一個博弈論中的minimax Game。 我們把這個過程稱為對抗過程

生成對抗網絡(GAN)可以看成是對抗過程中的一個特例,其中警察和犯罪份子可以分別modeled as 神經網絡。 第一個網絡生成數據,第二個網絡試圖分辨真實數據和第一個網絡生成的假數據之間的差異。 第二個網絡將輸出表示實際數據概率

的標量[0,1]

在GAN中,第一個網絡被稱為生成器G(Z)(Generator Net),第二個網絡被稱為判別器D(X)(Discriminator Net)

技術分享圖片

若達到了minimax Game中的最優的平衡點,第一個網絡將非常的神奇的能夠對實際數據進行建模(生成“實際數據”,騙過判別器D(X)),第二個網絡將輸出0.5的概率,i.e. 第一個網絡的輸出=真實數據

到這裏,你可能會萌生一個問題,“GAN應該怎麽被訓練呢?”。 這是因為數據的概率分布Pdata可能是一個非常復雜的分布,非常難以推斷。 因此,如果有一臺生成器可以從Pdata

生成樣本,而無需處理令人討厭的概率分布(i.e. 不需要知道具體的概率分布表達式),那應該是極好的了吧! 有了這樣一個生成器(從Pdata采樣的過程),我們可以使用訓練的生成網相廉價地地獲取樣本。

GAN Implementation

根據GAN的定義,我們需要兩個網絡。 網絡的形式可以是五花八門的,無論是像convnet或只是一個兩層神經網絡復雜的網絡都是ok的。 為了方便起見,G(z)D(X)都使用兩層的神經網絡。使用的框架為TensorFlow。

技術分享圖片
# Discriminator Net
X = tf.placeholder(tf.float32, shape=[None, 784], name=X)

D_W1 = tf.Variable(xavier_init([784, 128]), name=D_W1)
D_b1 = tf.Variable(tf.zeros(shape=[128]), name=D_b1)

D_W2 = tf.Variable(xavier_init([128, 1]), name=D_W2)
D_b2 = tf.Variable(tf.zeros(shape=[1]), name=D_b2)

theta_D = [D_W1, D_W2, D_b1, D_b2]

# Generator Net
Z = tf.placeholder(tf.float32, shape=[None, 100], name=Z)

G_W1 = tf.Variable(xavier_init([100, 128]), name=G_W1)
G_b1 = tf.Variable(tf.zeros(shape=[128]), name=G_b1)

G_W2 = tf.Variable(xavier_init([128, 784]), name=G_W2)
G_b2 = tf.Variable(tf.zeros(shape=[784]), name=G_b2)

theta_G = [G_W1, G_W2, G_b1, G_b2]


def generator(z):
    G_h1 = tf.nn.relu(tf.matmul(z, G_W1) + G_b1)
    G_log_prob = tf.matmul(G_h1, G_W2) + G_b2
    G_prob = tf.nn.sigmoid(G_log_prob)

    return G_prob


def discriminator(x):
    D_h1 = tf.nn.relu(tf.matmul(x, D_W1) + D_b1)
    D_logit = tf.matmul(D_h1, D_W2) + D_b2
    D_prob = tf.nn.sigmoid(D_logit)

    return D_prob, D_logit
View Code

根據上面的代碼,generator(z)函數接受一個100維向量並return 786維向量,即MNIST圖像(28x28)。 註意,z(G(z))是先驗的。 以上述方式,生成器k學習先驗分布(隱變量z)到實際分布Pdata之間的映射。

discriminator(x)函數接受MNIST圖像並返回表示真實MNIST圖像概率的標量。

現在,闡述下Adversarial Process是如何訓練GAN的。 以下是論文中的訓練算法:

技術分享圖片

技術分享圖片
G_sample = generator(Z)
D_real, D_logit_real = discriminator(X)
D_fake, D_logit_fake = discriminator(G_sample)

D_loss = -tf.reduce_mean(tf.log(D_real) + tf.log(1. - D_fake))
G_loss = -tf.reduce_mean(tf.log(D_fake))
View Code

在上面,我們使用負號作為損失函數,TensorFlow優化器只能做最小化。

另外,根據其它資料的建議,最好使用tf.reduce_mean(tf.log(D_fake))最大化,而不是最小化上述算法中的tf.reduce_mean(1 - tf.log(D_fake))

然後,我們可以開始對抗訓練了:

技術分享圖片
# Only update D(X)‘s parameters, so var_list = theta_D
D_solver = tf.train.AdamOptimizer().minimize(D_loss, var_list=theta_D)
# Only update G(X)‘s parameters, so var_list = theta_G
G_solver = tf.train.AdamOptimizer().minimize(G_loss, var_list=theta_G)

def sample_Z(m, n):
    ‘‘‘Uniform prior for G(Z)‘‘‘
    return np.random.uniform(-1., 1., size=[m, n])

for it in range(1000000):
    X_mb, _ = mnist.train.next_batch(mb_size)

    _, D_loss_curr = sess.run([D_solver, D_loss], feed_dict={X: X_mb, Z: sample_Z(mb_size, Z_dim)})
    _, G_loss_curr = sess.run([G_solver, G_loss], feed_dict={Z: sample_Z(mb_size, Z_dim)})
View Code

到此,我們已經完成了! 我們可以通過抽樣查看培訓過程:

技術分享圖片

Generative Adversarial Nets(GAN Tensorflow)