【问题标题】:How to disable discriminator training inside a Tensorflow GAN?如何在 Tensorflow GAN 中禁用鉴别器训练?
【发布时间】:2021-12-17 17:38:39
【问题描述】:

我有一个这样的生成器:

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

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

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

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

    model.add(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

还有一个鉴别器:

def make_discriminator_model():
    model = tf.keras.Sequential()
    model.add(layers.Conv2D(64, (5, 5), strides=(2, 2), padding='same',
                                     input_shape=[28, 28, 1]))
    model.add(layers.LeakyReLU())
    model.add(layers.Dropout(0.4))

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

    model.add(layers.Flatten())
    model.add(layers.Dense(1, activation='sigmoid'))
    opt = tf.keras.optimizers.Adam(lr=0.0002, beta_1=0.5)
    model.compile(loss='binary_crossentropy', optimizer=opt, metrics=['accuracy'])
    return model

我将它们分组到一个 GAN 中:

def make_gan(g_model, d_model):
    d_model.trainable = False #<-- Not working?
    model = tf.keras.Sequential()
    model.add(g_model)
    model.add(d_model)
    print("Trainable GAN params before:" + str(model.trainable_variables))
    d_model.trainable = False # <-- Also not working?
    print("Trainable GAN params after:" + str(model.trainable_variables)) #<-- The same as before
    opt = tf.keras.optimizers.Adam(lr=0.0002, beta_1=0.5)
    model.compile(loss='binary_crossentropy', optimizer=opt)
    return model

为了让 GAN 训练发挥作用,我需要分别训练生成器和判别器。 我使用 GAN 模型训练生成器,但我想在训练期间将鉴别器部分锁定到位。这似乎不起作用,因为我的鉴别器总是最终在 1 或 2 个时期内将所有内容归类为真实的。这导致我的 GAN 在大约 50 个 epoch 后没有任何进展。

为什么 d_model.trainable=False 在这种情况下不起作用?

这是我的火车循环:

def train(g_model, d_model, gan_model, dataset, latent_dim, n_epochs=100, n_batch=256):
    batch_per_epoch = int(dataset.shape[0] / n_batch)
    half_batch = int(n_batch / 2)
    for i in range(n_epochs):
        #train discriminator:
        for j in range(batch_per_epoch):
            X_real, y_real = generate_real_samples(dataset, half_batch)
            X_fake, y_fake = generate_fake_samples(g_model, latent_dim, half_batch)
            X, y = vstack((X_real, X_fake)), vstack((y_real, y_fake))
            d_fake_loss, _ = d_model.train_on_batch(X_real, y_real)
            d_real_loss, _ = d_model.train_on_batch(X_fake, y_fake)
            if j % 10 == 0:
                print('>Epoch %d - Training Discriminator epoch %d: %d/%d, d_real_loss=%.3f' % (i+1, k+1, j+1, batch_per_epoch, d_real_loss))
                    print('>Epoch %d - Training Discriminator epoch %d: %d/%d, d_fake_loss=%.3f' % (i+1, k+1, j+1, batch_per_epoch, d_fake_loss))
                    #print('>Epoch %d - Training Discriminator epoch %d: %d/%d, d_loss=%.3f' % (i+1, k+1, j+1, batch_per_epoch, d_loss))
        #train generator
        for j in range(batch_per_epoch):        
            X_gan = generate_latent_points(latent_dim, n_batch)
            y_gan = ones((n_batch, 1))
            g_loss = gan_model.train_on_batch(X_gan, y_gan)
            if j % 10 == 0:
                print('>Epoch %d - Training Generator: %d/%d, g_loss=%.3f' % (i+1, j+1, batch_per_epoch, g_loss))
        #call the generator to generate an image end the end of each epoch
        #x_generated, _ = generate_fake_samples(g_model, latent_dim, 100)
        #save_plot(x_generated, i)
        summarize_performance(i, g_model, d_model, dataset, latent_dim)

【问题讨论】:

    标签: python tensorflow machine-learning generative-adversarial-network


    【解决方案1】:

    在 tensorflow 中,无需显式锁定权重。 如代码所示,您执行以下操作:

    1. 在 GradientTape 中,您可以通过生成器传播数据, 将真实图像和生成图像传递给判别器,最后计算损失

    2. 获取关于损失的梯度。在这里,您只传递各自模型的可训练权重。

    3. 最后,将您计算的梯度应用到相应的模型。

      tf.GradientTape() 作为 gen_tape,tf.GradientTape() 作为 disc_tape: generated_images = self.generator(noise, training=True)

        real_output = self.discriminator(batch, training=True)
        fake_output = self.discriminator(generated_images, training=True)
      
        gen_loss = self.generator_loss(fake_output)
        disc_loss = self.discriminator_loss(real_output, fake_output)
      
      gradients_of_generator = gen_tape.gradient(gen_loss, self.generator.trainable_variables)
      gradients_of_discriminator = disc_tape.gradient(disc_loss, self.discriminator.trainable_variables)
      
      self.generator_optimizer.apply_gradients(zip(gradients_of_generator, self.generator.trainable_variables))
      self.discriminator_optimizer.apply_gradients(zip(gradients_of_discriminator, self.discriminator.trainable_variables))
      return [gen_loss, disc_loss]
      

    在本例中,with tf.GradientTape 范围内使用了两个渐变色带。原因是,只要使用tape.gradient() 检索值,就会释放磁带的内存。您也可以使用with tf.GradientTape(persistent=True) as gradient_tape:

    来使用单个磁带

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-11
      • 2019-01-28
      • 1970-01-01
      • 2019-02-12
      • 2021-11-20
      • 1970-01-01
      相关资源
      最近更新 更多