深度学习条件gan

深度学习条件gan


百家号 04-16 19:45

前面的文章介绍了gan的原理,但是可以看到gan有一个很有意思的结果,就是gan可以生成,但是他是在指定学习的一堆原始图片基础上,随机生成的。那么如何才能够按照我们指定的意愿去生成内容呢?比如,MNIST数据集的生产,我希望我能指定生成一些我希望的数字,例如1,或者2等。

这就是条件gan了,即CGan和CDCGAN。

我们先来看看原理:

我们知道,对于原来的GAN网络(包括DCGAN)实际上是包含了两个网络G(z)生成网络,还有D(X)判别网络,然后由此两个网络进行相互的博弈,产生对应的结果,最后讲训练好的G(z)网络拿出来,生成图片。

而对于条件网络,实际上就是在两个网络的基础上都要增加新的条件标签:y。而两个网络G(z)和D(X)在构造的时候,都带上条件:G(z,y),D(X,y),这样训练出来的结果,带上y条件,就可以生成条件对应的图片了。

我们直接看例子:

如果,我们要将一个GAN网络改造成一个cGan怎么做呢?

首先要把y定义出来

y = tf.placeholder(tf.float32, shape=[None, y_dim])

然后,改造生成网络

def generator(z, y):

# Concatenate z and y

inputs = tf.concat(concat_dim=1, values=[z, y])

G_h1 = tf.nn.relu(tf.matmul(inputs, 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, y):

# Concatenate x and y

inputs = tf.concat(concat_dim=1, values=[x, y])

D_h1 = tf.nn.relu(tf.matmul(inputs, 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

由此可见,判别网络和生成网络一样,是将输入部分和条件标签拼接在一起,进行统一的学习工作。

中间的计算lost和进行梯度下降这些和原来一样,不再给出例子了。最后看看训练部分的伪代码:

X_mb, y_mb = mnist.train.next_batch(mb_size)

Z_sample = sample_Z(mb_size, Z_dim)

_, D_loss_curr = sess.run([D_solver, D_loss], feed_dict={X: X_mb, Z: Z_sample, y:y_mb})

_, G_loss_curr = sess.run([G_solver, G_loss], feed_dict={Z: Z_sample, y:y_mb})

每次训练,gan网络,都是公用一个y标签进行训练。

当然使用的时候很简单,把对应的条件y带上,就可以获取到训练的成果。

到这里,cGAN的设计就结束了,大家可以拿著名的MNIST数据集进行测试一下。

下面讲讲,如果是面对的是DCGAN,那么cDCGAN是怎么处理的呢?

只讲核心的,其实也就是在生成网络和判别网络构造的时候有所区别,其他都是一样的。

先看看生成网络:

def discriminator(x, y_fill, isTrain=True, reuse=False):

with tf.variable_scope('discriminator', reuse=reuse):

# initializer

w_init = tf.truncated_normal_initializer(mean=0.0, stddev=0.02)

b_init = tf.constant_initializer(0.0)

# concat layer

cat1 = tf.concat([x, y_fill], 3)

# 1st hidden layer

conv1 = tf.layers.conv2d(cat1, 128, [5, 5], strides=(2, 2), padding='same', kernel_initializer=w_init, bias_initializer=b_init)

lrelu1 = lrelu(conv1, 0.2)

# 2nd hidden layer

conv2 = tf.layers.conv2d(lrelu1, 256, [5, 5], strides=(2, 2), padding='same', kernel_initializer=w_init, bias_initializer=b_init)

lrelu2 = lrelu(tf.layers.batch_normalization(conv2, training=isTrain), 0.2)

# output layer

conv3 = tf.layers.conv2d(lrelu2, 1, [7, 7], strides=(1, 1), padding='valid', kernel_initializer=w_init)

o = tf.nn.sigmoid(conv3)

return o, conv3

如上,黑体字部分很关键,实际就是将标签合并到判别网络的原始图像的“深度”上。如此就可以利用y标签了。

再看看生成网络:

def generator(x, y_label, isTrain=True, reuse=False):

with tf.variable_scope('generator', reuse=reuse):

# initializer

w_init = tf.truncated_normal_initializer(mean=0.0, stddev=0.02)

b_init = tf.constant_initializer(0.0)

# concat layer

cat1 = tf.concat([x, y_label], 3)

# 1st hidden layer

deconv1 = tf.layers.conv2d_transpose(cat1, 256, [7, 7], strides=(1, 1), padding='valid', kernel_initializer=w_init, bias_initializer=b_init)

lrelu1 = lrelu(tf.layers.batch_normalization(deconv1, training=isTrain), 0.2)

# 2nd hidden layer

deconv2 = tf.layers.conv2d_transpose(lrelu1, 128, [5, 5], strides=(2, 2), padding='same', kernel_initializer=w_init, bias_initializer=b_init)

lrelu2 = lrelu(tf.layers.batch_normalization(deconv2, training=isTrain), 0.2)

# output layer

deconv3 = tf.layers.conv2d_transpose(lrelu2, 1, [5, 5], strides=(2, 2), padding='same', kernel_initializer=w_init, bias_initializer=b_init)

o = tf.nn.tanh(deconv3)

return o

其实和CGAN的生成网络是一样的,将y标签加入到最后一个维度上,但例子中给了一个多维度的,其实这个维度定义如下:

z = tf.placeholder(tf.float32, shape=(None, 1, 1, 100))

G_z = generator(z, y_label, isTrain)

好,其他就和普通的cGAN没有什么区别了,大家试试吧。

这里给出关于CGAN的参考:

https://wiseodd.github.io/techblog/2016/12/24/conditional-gan-tensorflow/

这篇是原理的介绍

代码在下面的链接里面:

https://github.com/wiseodd/generative-models/tree/master/GAN/conditional_gan

最后,cDCGAN的例子和资料相对较少,参见如下,有一个样例代码:

https://github.com/znxlwm/tensorflow-MNIST-cGAN-cDCGAN

为了实践,之前也说过,折腾阿里云的平台很长时间了,下一篇内容,将最近在个个平台上的实践,都写一遍。

不过,我先给出结论,机器学习目前平台还是推荐在AWS上,这个是最好的,没有之一!

猜你喜欢

转载自blog.csdn.net/jacke121/article/details/80920048
今日推荐