GAN的目的
一些生成模型可以從模型的分佈中生成樣本,GAN也是生成模型的一種,主要用於通過分佈生成樣本。
你可能想知道爲什麼生成模型值得學習,尤其在瞭解到生成模型只能夠製造數組而不是提供一個預測的密度函數更是如此。
學習生成模型的目的如下:
- 生成樣本,這是最直接的理由。
- 訓練並不包含最大似然估計。
- 由於生成器不會看到訓練數據,過擬合的風險更低。
- GAN十分擅長捕獲模型的分佈。
GAN的組成
1、生成器
生成器網絡以隨機的噪聲作爲輸入並試圖生成樣本數據。
2、判別器
判別器網絡以真是數據或者生成數據作爲輸入,並試圖預測當前輸入是真實數據還是生成數據。
GAN的實現
選擇個helloworld級別的來簡單根據GAN的定義來實現生成器和判定器網絡,採用tensorflow框架搭建兩層神經網絡,實現minist數據集的生成和判定。
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
import os
from tensorflow.examples.tutorials.mnist import input_data
def xavier_init(size):
input_dim = size[0]
xavier_variance = 1. / tf.sqrt(input_dim/2.)
return tf.random_normal(shape=size, stddev=xavier_variance)
def plot(samples):
fig = plt.figure(figsize=(4, 4))
gs = gridspec.GridSpec(4, 4)
gs.update(wspace=0.05, hspace=0.05)
for i, sample in enumerate(samples):
ax = plt.subplot(gs[i])
plt.axis('off')
ax.set_xticklabels([])
ax.set_yticklabels([])
ax.set_aspect('equal')
plt.imshow(sample.reshape(28, 28), cmap='Greys_r')
return fig
# Random noise setting for Generator
Z = tf.placeholder(tf.float32, shape=[None, 100], name='Z')
#Generator parameter settings
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]
#Input Image MNIST setting for Discriminator [28x28=784]
X = tf.placeholder(tf.float32, shape=[None, 784], name='X')
#Discriminator parameter settings
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 Network
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
# Discriminator Network
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
G_sample = generator(Z)
D_real, D_logit_real = discriminator(X)
D_fake, D_logit_fake = discriminator(G_sample)
# Loss functions from the paper
D_loss = -tf.reduce_mean(tf.log(D_real) + tf.log(1. - D_fake))
G_loss = -tf.reduce_mean(tf.log(D_fake))
# Update D(X)'s parameters
D_solver = tf.train.AdamOptimizer().minimize(D_loss, var_list=theta_D)
# Update G(Z)'s parameters
G_solver = tf.train.AdamOptimizer().minimize(G_loss, var_list=theta_G)
def sample_Z(m, n):
return np.random.uniform(-1., 1., size=[m, n])
batch_size = 128
Z_dim = 100
sess = tf.Session()
sess.run(tf.global_variables_initializer())
mnist = input_data.read_data_sets('MNIST/', one_hot=True)
if not os.path.exists('output/'):
os.makedirs('output/')
i = 0
for itr in range(1000000):
if itr % 1000 == 0:
samples = sess.run(G_sample, feed_dict={Z: sample_Z(16, Z_dim)})
fig = plot(samples)
plt.savefig('output/{}.png'.format(str(i).zfill(3)), bbox_inches='tight')
i += 1
plt.close(fig)
X_mb, _ = mnist.train.next_batch(batch_size)
_, D_loss_curr = sess.run([D_solver, D_loss], feed_dict={X: X_mb, Z: sample_Z(batch_size, Z_dim)})
_, G_loss_curr = sess.run([G_solver, G_loss], feed_dict={Z: sample_Z(batch_size, Z_dim)})
if itr % 1000 == 0:
print('Iter: {}'.format(itr))
print('D loss: {:.4}'. format(D_loss_curr))
print('G_loss: {:.4}'.format(G_loss_curr))
print()
GAN的應用
- 利用CycleGAN進行圖像轉換。
- 利用StackGAN自動從文本中製作逼真的圖像。
- 探索式GAN(DiscoveryGAN,DiscoGAN)進行圖像風格轉換。
- 利用SRGAN通過與訓練模型提升圖像的品質,製作高清晰度的圖像。
- 通過特徵成逼真圖像:設想根據人的描述來生成他的照片,然後進行圖像搜素查找。
GAN的挑戰與問題
訓練GAN的目的是生成器網絡G(z)和判別器網絡D(z)相互競爭達到最優,更準確的說是到納什平衡的一個過程。
- 啓動和初始化的問題
- 模型坍塌
- 計數方面的問題
- 角度方面的問題
- 全局結構方面的問題
優化的方向
- 特徵匹配
- 小批量
- 歷史平均
- 單側標籤平滑
- 輸入規範化
- 批規範化
- 利用Relu和MaxPool避免稀疏梯度
- 優化器和噪聲
具體想了解更多可以根據這些去詳細查看更多的細節,剛剛接觸,先整體後局部。