GAN and CGAN
关于GAN和CGAN的教程网上有好多,感兴趣的可以自己去找着看看。最重要的是要弄清楚,GAN是干嘛的?作者在论文和NIPS2016 tutorial里面都讲了很多设计GAN的初衷。简单来说,GAN就是用来拟合样本的分布的。
看了论文总觉得理解得不够透彻,就在网上找了一些简单的程序跑了跑,下面就直接来说说程序和实验结果吧。
GAN
GAN的结构如下图所示。
实验数据集采用了MNIST手写数字图像。代码参考github上的例子,使用TensorFlow1.2搭建了一个神经网络。准确来说是两个网络,判别器Discriminator和生成器Generator各是一个神经网络。两个网络的结构类似,都有两个全连接层,最后一个全连接层接输出的tanh或者sigmoid层。
code
代码参考了别人的,原作者是在ipython notebook里面写的代码,然后自己画图。我是使用的Tensorboard来进行可视化操作的,所以我把代码进行了相应的修改。下面只显示了主要的程序部分。请看完整代码,顺便说一句,这里还可以看到无水印的原图~
# reference https://github.com/NELSONZHAO/zhihu/tree/master/mnist_gan
def get_generator(noise_img, n_units, out_dim, reuse = False, alpha = 0.01):
"""
generator
noise_img: input of generator
n_units: # hidden units
out_dim: # output
alpha: parameter of leaky ReLU
"""
with tf.variable_scope("generator", reuse = reuse):
# hidden layer
hidden = tf.layers.dense(noise_img, n_units)
# leaky ReLU
relu = tf.maximum(alpha * hidden, hidden)
# dropout
drop = tf.layers.dropout(relu, rate = 0.5)
# logits & outputs
logits = tf.layers.dense(drop, out_dim)
outputs = tf.tanh(logits)
return logits, outputs
def get_discriminator(img, n_units, reuse = False, alpha = 0.01):
"""
discriminator
n_units: # hidden units
alpha: parameter of leaky Relu
"""
with tf.variable_scope("discriminator", reuse=reuse):
# hidden layer
hidden = tf.layers.dense(img, n_units)
relu = tf.maximum(alpha * hidden, hidden)
# dropout
drop = tf.layers.dropout(relu, rate = 0.5)
# logits & outputs
logits = tf.layers.dense(drop, 1)
outputs = tf.sigmoid(logits)
return logits, outputs
...
with tf.Graph().as_default():
real_img, noise_img = get_inputs(real_img_size, noise_img_size)
# generator
g_logits, g_outputs = get_generator(noise_img, g_units, real_img_size)
sample_images = tf.reshape(g_outputs, [-1, 28, 28, 1])
tf.summary.image("sample_images", sample_images, 10)
# discriminator
d_logits_real, d_outputs_real = get_discriminator(real_img, d_units)
d_logits_fake, d_outputs_fake = get_discriminator(g_outputs, d_units, reuse = True)
# discriminator loss
d_loss_real = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(logits = d_logits_real,
labels = tf.ones_like(d_logits_real)) * (1 - smooth))
d_loss_fake = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(logits = d_logits_fake,
labels = tf.zeros_like(d_logits_fake)))
# loss
d_loss = tf.add(d_loss_real, d_loss_fake)
# generator loss
g_loss = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(logits = d_logits_fake,
labels = tf.ones_like(d_logits_fake)) * (1 - smooth) )
...
实验结果
我使用了TF的tensorboard来进行可视化,通过tensorboard可以看到生成的网络的结构。同时我也保存了Generator在训练的过程中生成的样本图片,还有Generator和Discriminator的Loss。
Graph
Loss
把最后30个epoch的Loss值显示出来
('Epoch 271/300', 'Discriminator loss: 0.8802(Real: 0.5291 + Fake: 0.3511)', 'Generator loss: 2.0067')
('Epoch 272/300', 'Discriminator loss: 0.8302(Real: 0.4576 + Fake: 0.3727)', 'Generator loss: 1.8738')
('Epoch 273/300', 'Discriminator loss: 0.7560(Real: 0.3527 + Fake: 0.4033)', 'Generator loss: 1.8327')
('Epoch 274/300', 'Discriminator loss