欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

深度学习生成模型-DCGAN

程序员文章站 2022-03-15 19:16:26
...

原理分析

DCGAN 和GAN的原理是相同的,就是DCGAN和CNN结合,用CNN更有利于图形处理。
关于GAN的原理可以看一下这篇博客:GAN新手入门指南+keras&TensorFlow代码详解(WIN10)

然后我们可以具体看一下model实现:

实现生成器

这是最简单的Keras Sequnatial模型,我们可以发现他的输入为(None, 100),而输出则是(None, 28, 28, 1)。看到28就知道这是一个关于生成手写数字的GAN模型。

def make_generator_model():
    model = tf.keras.Sequential()
    model.add(tf.keras.layers.Dense(7 * 7 * 256, use_bias=False, input_shape=(100,)))
    model.add(tf.keras.layers.BatchNormalization())
    model.add(tf.keras.layers.LeakyReLU())

    model.add(tf.keras.layers.Reshape((7, 7, 256)))
    assert model.output_shape == (None, 7, 7, 256)  # Note: None is the batch size

    model.add(tf.keras.layers.Conv2DTranspose(128, (5, 5), strides=(1, 1), padding='same', use_bias=False))
    assert model.output_shape == (None, 7, 7, 128)
    model.add(tf.keras.layers.BatchNormalization())
    model.add(tf.keras.layers.LeakyReLU())

    model.add(tf.keras.layers.Conv2DTranspose(64, (5, 5), strides=(2, 2), padding='same', use_bias=False))
    assert model.output_shape == (None, 14, 14, 64)
    model.add(tf.keras.layers.BatchNormalization())
    model.add(tf.keras.layers.LeakyReLU())

    model.add(
        tf.keras.layers.Conv2DTranspose(1, (5, 5), strides=(2, 2), padding='same', use_bias=False, activation='tanh'))
    assert model.output_shape == (None, 28, 28, 1)

    return model

鉴别器

它的输入是应该是图像(None, 28, 28, 1),但是对于不同数据的时候它的输入 input_shape是 不一样。重要的不是输入而输出,输出维度为1用来表示是否这张图为真还是为假。

def make_discriminator_model():
    model = tf.keras.Sequential()
    model.add(tf.keras.layers.Conv2D(64, (5, 5), strides=(2, 2), padding='same'))
    model.add(tf.keras.layers.LeakyReLU())
    model.add(tf.keras.layers.Dropout(0.3))

    model.add(tf.keras.layers.Conv2D(128, (5, 5), strides=(2, 2), padding='same'))
    model.add(tf.keras.layers.LeakyReLU())
    model.add(tf.keras.layers.Dropout(0.3))

    model.add(tf.keras.layers.Flatten())
    model.add(tf.keras.layers.Dense(1))
    return model

loss函数

生成器损失函数

这个用来计算生成图像和真实图像之间的差异

def generator_loss(generated_output):
    return tf.losses.sigmoid_cross_entropy(tf.ones_like(generated_output), generated_output)
鉴别器损失函数
 def discriminator_loss(real_output, generated_output):
    # [1,1,...,1] with real output since it is true and we want our generated examples to look like it
    real_loss = tf.losses.sigmoid_cross_entropy(multi_class_labels=tf.ones_like(real_output), logits=real_output)

    # [0,0,...,0] with generated images since they are fake
    generated_loss = tf.losses.sigmoid_cross_entropy(multi_class_labels=tf.zeros_like(generated_output), logits=generated_output)

    total_loss = real_loss + generated_loss

    return total_loss

训练

每一步训练
def train_step(images):
  # generating noise from a normal distribution
  noise = tf.random_normal([batch_size, noise_dim])

  with tf.GradientTape() as gen_tape, tf.GradientTape() as disc_tape:
      generated_images = generator(noise, training=True)

      real_output = discriminator(images, training=True)
      generated_output = discriminator(generated_images, training=True)

      gen_loss = generator_loss(generated_output)
      disc_loss = discriminator_loss(real_output, generated_output)

  gradients_of_generator = gen_tape.gradient(gen_loss, generator.variables)
  gradients_of_discriminator = disc_tape.gradient(disc_loss, discriminator.variables)

  generator_optimizer.apply_gradients(zip(gradients_of_generator, generator.variables))
  discriminator_optimizer.apply_gradients(zip(gradients_of_discriminator, discriminator.variables))
训练函数
def train(dataset, epochs):
    for epoch in range(epochs):
        start = time.time()

        for images in dataset:
            train_step(images)

        display.clear_output(wait=True)
        generate_and_save_images(generator,
                                 epoch + 1,
                                 random_vector_for_generation)

        # saving (checkpoint) the model every 15 epochs
        if (epoch + 1) % 15 == 0:
            checkpoint.save(file_prefix=checkpoint_prefix)

        print('Time taken for epoch {} is {} sec'.format(epoch + 1,
                                                         time.time() - start))
    # generating after the final epoch
    display.clear_output(wait=True)
    generate_and_save_images(generator,
                             epochs,
                             random_vector_for_generation)

如果我们设置我们的batch_size = 256,因为我们知道我们的生成器的input_shape=(None, 100),所以我们现在每一步生成器的输入就(256, 100)的随机噪声矩阵。这个矩阵通过生成器之后就变成了(256, 28, 28, 1)的矩阵了,然后我们再将这个生成的东西丢入鉴别器中,就得到(256, 1)的矩阵,这个东西就是判断每张图像是否为真的依据。当然因为是前几个epoch所以值都无限接近与0(假),所以他和1(真)的gen_loss就比较大。然后我们再讲我们训练数据中的真图放入鉴别其中也会得到一个(256, 1)的输出,这个输出的都比较接近与1(真),所以disc_loss开始值就比较小。然后求梯度啊,就会发现gen_loss越来越小,disc_loss会越来越大,直到接近相等,训练完毕。

相关标签: 生成模型