美文网首页
Tensorflow神经网络之DCGAN

Tensorflow神经网络之DCGAN

作者: AI异构 | 来源:发表于2019-02-27 18:39 被阅读0次

    DCGAN简介

    DCGAN在GAN的基础上优化了网络结构,加入了 convbatch_norm 等层,使得网络更容易训练,网络结构如下:

    DCGAN网络结构图
    注意:本图只是示例,与下面实际网络参数不对应。

    Tensorflow实现DCGAN

    from __future__ import division, print_function, absolute_import
    
    import matplotlib.pyplot as plt
    import numpy as np
    import tensorflow as tf
    

    导入数据集

    # Import MNIST data
    from tensorflow.examples.tutorials.mnist import input_data
    mnist = input_data.read_data_sets("./data/", one_hot=True)
    

    Extracting ./data/train-images-idx3-ubyte.gz
    Extracting ./data/train-labels-idx1-ubyte.gz
    Extracting ./data/t10k-images-idx3-ubyte.gz
    Extracting ./data/t10k-labels-idx1-ubyte.gz
    

    设置参数

    # 训练参数
    num_steps = 10000 # 总迭代次数
    batch_size = 128 # 批量大小
    lr_generator = 0.002 # 生成器学习率
    lr_discriminator = 0.002 # 判别器学习率
    
    # 网络参数
    image_dim = 784 # 28*28 pixels * 1 channel
    noise_dim = 100 # Noise data points
    

    构建DCGAN网络

    # 构建网络
    # 网络输入
    noise_input = tf.placeholder(tf.float32, shape=[None, noise_dim])  # 生成器输入 噪声 batch*100,none后面被赋值batch
    real_image_input = tf.placeholder(tf.float32, shape=[None, 28, 28, 1]) # 判别器输入 真实图像 batch*28*28*1
    # A boolean to indicate batch normalization if it is training or inference time
    # 判断是否在训练
    is_training = tf.placeholder(tf.bool)
    
    # 定义激活函数 LeakyReLU,在判别器网络中用
    # LeakyReLU 是 ReLU 的变种 [^1]
    def leakyrelu(x, alpha=0.2):
        return 0.5 * (1 + alpha) * x + 0.5 * (1 - alpha) * abs(x)
    
    # 定义生成器网络
    # 输入:噪声  输出:图像
    # 训练时,才使用batch_normalization
    def generator(x, reuse=False):
        with tf.variable_scope('Generator', reuse=reuse):
            # 第一层为全连接层,含神经元个数为7*7*128,输入是噪声batch*100
            x = tf.layers.dense(x, units=7 * 7 * 128)
            # tf.layers.batch_normalization() 的第二个参数axis表示在哪一个维度做normalize,通常数据排布顺序为(batch, height, width, channels),固默认为-1
            # 全连接层channel=1,所以是对所有数据做normalize
            x = tf.layers.batch_normalization(x, training=is_training)
            # 激活函数 rule
            x = tf.nn.relu(x)
            # Reshape为4维: (batch, height, width, channels),这里是 (batch, 7, 7, 128)
            x = tf.reshape(x, shape=[-1, 7, 7, 128])
            # 反卷积层1
            # 卷积核大小5*5*128,64个,步长2(tf.layers.conv2d_transpose函数前几个参数为input,filters(输出feature map通道数),kernel_size, strides,padding)
            # 输入x shape:(batch,7,7,128), 输出image shape: (batch, 14, 14, 64)
            x = tf.layers.conv2d_transpose(x, 64, 5, strides=2, padding='same')
            # batch normalization,在channel维度上做normalize
            x = tf.layers.batch_normalization(x, training=is_training)
            # 激活函数 relu
            x = tf.nn.relu(x)
            # 反卷积层2
            # 卷积核大小5*5*128,1个,步长2
            # 输入x shape:(batch,14,14,64), 输出image shape: (batch, 28, 28, 1)
            x = tf.layers.conv2d_transpose(x, 1, 5, strides=2, padding='same')
            # 激活函数 tanh
            # Apply tanh for better stability - clip values to [-1, 1].
            x = tf.nn.tanh(x)
            return x
    
    
    # 定义判别器网络
    # 输入:图像, 输出: 预测结果(Real/Fake Image)
    # 同样训练时,才使用batch_normalization
    def discriminator(x, reuse=False):
        with tf.variable_scope('Discriminator', reuse=reuse):
            # 卷积层1,输入x,卷积核大小5x5,64个,步长2
            x = tf.layers.conv2d(x, 64, 5, strides=2, padding='same')
            x = tf.layers.batch_normalization(x, training=is_training)
            # 激活函数 leakyrelu
            x = leakyrelu(x)
            # 卷积层2,输入第一个卷积层的输出,卷积核大小5x5,128个,步长2
            x = tf.layers.conv2d(x, 128, 5, strides=2, padding='same')
            x = tf.layers.batch_normalization(x, training=is_training)
            # 激活函数 leakyrelu
            x = leakyrelu(x)
            # 展平
            x = tf.reshape(x, shape=[-1, 7*7*128])
            # 全连接层,含1024个神经元
            x = tf.layers.dense(x, 1024)
            x = tf.layers.batch_normalization(x, training=is_training)
            # 激活函数 leakyrelu
            x = leakyrelu(x)
            # 输出2个类别: Real and Fake images
            x = tf.layers.dense(x, 2)
        return x
    
    # 构建生成器
    gen_sample = generator(noise_input)
    
    # 构建两个判别器(一个是真实图像输入,一个是生成图像)
    disc_real = discriminator(real_image_input)
    disc_fake = discriminator(gen_sample, reuse=True)
    
    # Build the stacked generator/discriminator
    # 用于计算生成器的损失
    stacked_gan = discriminator(gen_sample, reuse=True)
    
    # 创建损失函数,交叉熵
    # 真实图像,标签1
    disc_loss_real = tf.reduce_mean(tf.nn.sparse_softmax_cross_entropy_with_logits(
        logits=disc_real, labels=tf.ones([batch_size], dtype=tf.int32)))
    # 生成图像,标签0
    disc_loss_fake = tf.reduce_mean(tf.nn.sparse_softmax_cross_entropy_with_logits(
        logits=disc_fake, labels=tf.zeros([batch_size], dtype=tf.int32)))
    # 判别器损失函数是两者之和
    disc_loss = disc_loss_real + disc_loss_fake
    # 生成器损失函数 (生成器试图骗过判别器,因此这里标签是1)
    gen_loss = tf.reduce_mean(tf.nn.sparse_softmax_cross_entropy_with_logits(
        logits=stacked_gan, labels=tf.ones([batch_size], dtype=tf.int32)))
    
    # 创建优化器(采用Adam方法)
    optimizer_gen = tf.train.AdamOptimizer(learning_rate=lr_generator, beta1=0.5, beta2=0.999)
    optimizer_disc = tf.train.AdamOptimizer(learning_rate=lr_discriminator, beta1=0.5, beta2=0.999)
    
    # Training Variables for each optimizer
    # By default in TensorFlow, all variables are updated by each optimizer, so we
    # need to precise for each one of them the specific variables to update.
    # 生成网络的变量
    gen_vars = tf.get_collection(tf.GraphKeys.TRAINABLE_VARIABLES, scope='Generator') # tf.get_collection:从一个结合中取出全部变量,是一个列表
    # 判别器网络的变量
    disc_vars = tf.get_collection(tf.GraphKeys.TRAINABLE_VARIABLES, scope='Discriminator')
    
    # 创建训练操作
    # TensorFlow UPDATE_OPS collection holds all batch norm operation to update the moving mean/stddev
    gen_update_ops = tf.get_collection(tf.GraphKeys.UPDATE_OPS, scope='Generator')
    # `control_dependencies` ensure that the `gen_update_ops` will be run before the `minimize` op (backprop)
    with tf.control_dependencies(gen_update_ops):
        train_gen = optimizer_gen.minimize(gen_loss, var_list=gen_vars)
    disc_update_ops = tf.get_collection(tf.GraphKeys.UPDATE_OPS, scope='Discriminator')
    with tf.control_dependencies(disc_update_ops):
        train_disc = optimizer_disc.minimize(disc_loss, var_list=disc_vars)
    
    # 变量全局初始化
    init = tf.global_variables_initializer()
    

    训练

    # Start Training
    # Start a new TF session
    sess = tf.Session()
    
    # Run the initializer
    sess.run(init)
    
    # Training
    for i in range(1, num_steps+1):
    
        # Prepare Input Data
        # Get the next batch of MNIST data (only images are needed, not labels)
        batch_x, _ = mnist.train.next_batch(batch_size)
        batch_x = np.reshape(batch_x, newshape=[-1, 28, 28, 1])
        # Rescale to [-1, 1], the input range of the discriminator
        batch_x = batch_x * 2. - 1.
    
        # Discriminator Training
        # Generate noise to feed to the generator
        z = np.random.uniform(-1., 1., size=[batch_size, noise_dim])
        _, dl = sess.run([train_disc, disc_loss], feed_dict={real_image_input: batch_x, noise_input: z, is_training:True})
    
        # Generator Training
        # Generate noise to feed to the generator
        z = np.random.uniform(-1., 1., size=[batch_size, noise_dim])
        _, gl = sess.run([train_gen, gen_loss], feed_dict={noise_input: z, is_training:True})
    
        if i % 500 == 0 or i == 1:
            print('Step %i: Generator Loss: %f, Discriminator Loss: %f' % (i, gl, dl))
    

    Step 1: Generator Loss: 4.064141, Discriminator Loss: 1.679586
    Step 500: Generator Loss: 1.472707, Discriminator Loss: 0.974612
    Step 1000: Generator Loss: 1.918907, Discriminator Loss: 0.964812
    Step 1500: Generator Loss: 2.567637, Discriminator Loss: 0.717904
    Step 2000: Generator Loss: 2.398796, Discriminator Loss: 0.512406
    Step 2500: Generator Loss: 3.057401, Discriminator Loss: 1.235215
    Step 3000: Generator Loss: 2.620444, Discriminator Loss: 0.539795
    Step 3500: Generator Loss: 3.193395, Discriminator Loss: 0.265896
    Step 4000: Generator Loss: 5.071162, Discriminator Loss: 0.409445
    Step 4500: Generator Loss: 5.213869, Discriminator Loss: 0.203033
    Step 5000: Generator Loss: 6.087250, Discriminator Loss: 0.350634
    Step 5500: Generator Loss: 5.467363, Discriminator Loss: 0.424895
    Step 6000: Generator Loss: 4.910432, Discriminator Loss: 0.196554
    Step 6500: Generator Loss: 3.230242, Discriminator Loss: 0.268745
    Step 7000: Generator Loss: 4.777361, Discriminator Loss: 0.676658
    Step 7500: Generator Loss: 4.165446, Discriminator Loss: 0.150221
    Step 8000: Generator Loss: 5.681596, Discriminator Loss: 0.108955
    Step 8500: Generator Loss: 6.023059, Discriminator Loss: 0.114312
    Step 9000: Generator Loss: 4.660669, Discriminator Loss: 0.182506
    Step 9500: Generator Loss: 4.492438, Discriminator Loss: 0.411817
    Step 10000: Generator Loss: 5.906080, Discriminator Loss: 0.088082
    

    测试

    # Testing
    # Generate images from noise, using the generator network.
    n = 6
    canvas = np.empty((28 * n, 28 * n))
    for i in range(n):
        # Noise input.
        z = np.random.uniform(-1., 1., size=[n, noise_dim])
        # Generate image from noise.
        g = sess.run(gen_sample, feed_dict={noise_input: z, is_training:False})
        # Rescale values to the original [0, 1] (from tanh -> [-1, 1])
        g = (g + 1.) / 2.
        # Reverse colours for better display
        g = -1 * (g - 1)
        for j in range(n):
            # Draw the generated digits
            canvas[i * 28:(i + 1) * 28, j * 28:(j + 1) * 28] = g[j].reshape([28, 28])
    
    plt.figure(figsize=(n, n))
    plt.imshow(canvas, origin="upper", cmap="gray")
    plt.show()
    
    image

    相关文章

      网友评论

          本文标题:Tensorflow神经网络之DCGAN

          本文链接:https://www.haomeiwen.com/subject/tsxquqtx.html