如何让我的判别器和生成器损失在 DCGAN 中收敛?

问题描述 投票:0回答:1

我正在尝试构建一个用于 T 恤设计生成的 DCGAN。我首先使用 MNIST 数据集创建一个 DCGAN,然后有信心为更复杂的用例制作一个 DCGAN。

我按照 DCGAN 研究论文中提供的架构指南创建了一个模型,如下所示:

稳定深度卷积 GAN 的架构指南

  • 用跨步卷积(鉴别器)和分数跨步替换任何池化层 卷积(生成器)。
  • 在生成器和判别器中都使用batchnorm。
  • 删除完全连接的隐藏层以获得更深的架构。
  • 在生成器中对除输出之外的所有层使用 ReLU 激活,输出使用 Tanh。
  • 在所有层的判别器中使用 LeakyReLU 激活

我无法理解这是否是模式崩溃、梯度消失或收敛失败问题。生成的输出都是相同的,因此看起来像是模式崩溃。如果是,我该如何解决这个问题?我尝试过尝试学习率、架构、标签平滑以及分别训练假批次和真实批次,而不是堆叠它们(我应该补充一下,当我看到 d_loss 或 g_loss 时,我多次停止训练并且没有让它完成变成0或波动很大)

这些是数据集中的一些图像:

Real (training) images

这些是生成的图像:

Generated Images

这是 d_real 损失、d_fake 损失和 gan 损失与时期数的关系图。

Loss Plot

这是代码:

import matplotlib.pyplot as plt
import numpy as np
import os

from tensorflow.keras.layers import Conv2D, Conv2DTranspose, Dense, Dropout, Flatten, BatchNormalization, Input, Reshape, LeakyReLU, ReLU
from tensorflow.keras.models import Sequential
from tensorflow.keras.optimizers import Adam
from tensorflow.keras.utils import img_to_array, load_img

def discriminator(input_shape=(128, 128, 3)):
    model = Sequential([
        Conv2D(64, (5, 5), strides=(2, 2), padding='same', input_shape=input_shape, kernel_initializer='glorot_uniform'), # kernel initializer was removed
        LeakyReLU(alpha=0.2),

        Conv2D(128, (5, 5), strides=(2, 2), padding='same', kernel_initializer='glorot_uniform'),
        BatchNormalization(momentum=0.5),
        LeakyReLU(alpha=0.2),

        Conv2D(256, (5, 5), strides=(2, 2), padding='same', kernel_initializer='glorot_uniform'),
        BatchNormalization(momentum=0.5),
        LeakyReLU(alpha=0.2),

        Conv2D(512, (5, 5), strides=(2, 2), padding='same', kernel_initializer='glorot_uniform'),
        BatchNormalization(momentum=0.5),
        LeakyReLU(alpha=0.2),

        # Output => 8 * 8 * 512
        Flatten(),
        Dense(1, activation='sigmoid')
    ])

    opt = Adam(learning_rate=0.0002, beta_1=0.5)
    model.compile(loss='binary_crossentropy', optimizer=opt, metrics=None)

    return model

def generator():
    model = Sequential([
        Dense(8*8*512, input_shape=(100,), kernel_initializer='glorot_uniform'),
        Reshape((8, 8, 512)),
        BatchNormalization(momentum=0.5),
        ReLU(),

        Conv2DTranspose(256, (5, 5), strides=(2, 2), padding='same', kernel_initializer='glorot_uniform'),
        BatchNormalization(momentum=0.5),
        ReLU(),

        Conv2DTranspose(128, (5, 5), strides=(2, 2), padding='same', kernel_initializer='glorot_uniform'),
        BatchNormalization(momentum=0.5),
        ReLU(),

        Conv2DTranspose(64, (5, 5), strides=(2, 2), padding='same', kernel_initializer='glorot_uniform'),
        BatchNormalization(momentum=0.5),
        ReLU(),

        Conv2DTranspose(3, (5, 5), strides=(2, 2), padding='same', activation='tanh', kernel_initializer='glorot_uniform'),
    ])

    return model

def gan(gen_model, disc_model):
    disc_model.trainable = False

    model = Sequential([
        gen_model,
        disc_model
    ])

    opt = Adam(learning_rate=0.0002, beta_1=0.5)
    model.compile(loss='binary_crossentropy', optimizer=opt)

    return model

def load_dataset(directory="/content/tshirt-resized", target_size=(128, 128)):
    images = []
    for filename in os.listdir(directory):
        img = load_img(os.path.join(directory, filename), target_size=target_size)
        images.append(img_to_array(img))

    dataset = np.array(images)
    dataset = dataset.astype('float32')
    dataset /= 255.0

    return dataset

def generate_real_samples(dataset, num_samples):
    ix = np.random.randint(0, dataset.shape[0], num_samples)

    X = dataset[ix]
    y = np.ones((num_samples, 1)) - 0.1  # Label smoothing


    return X, y

def generate_latent_points(num_samples): # gen model input
    x_input = np.random.randn(100 * num_samples)
    x_input = x_input.reshape(num_samples, 100)

    return x_input

def generate_fake_samples(gen_model, num_samples): # gen model output
    x_input = generate_latent_points(num_samples)

    X = gen_model.predict(x_input)
    y = np.zeros((num_samples, 1)) + 0.1  # Label smoothing


    return X, y

def train(gen_model, disc_model, gan_model, dataset, epochs=200, batch_size=128):
    num_batches_per_epoch = int(dataset.shape[0] / batch_size)
    d1_loss_hist = []
    d2_loss_hist = []
    gan_loss_hist = []
    for i in range(epochs):
        for j in range(num_batches_per_epoch):
            X_real, y_real = generate_real_samples(dataset, batch_size // 2)
            d1_loss = disc_model.train_on_batch(X_real, y_real)

            X_fake, y_fake = generate_fake_samples(gen_model, batch_size // 2)
            d2_loss = disc_model.train_on_batch(X_fake, y_fake)

            X_gan = generate_latent_points(batch_size)
            y_gan = np.ones((batch_size, 1))
            gan_loss = gan_model.train_on_batch(X_gan, y_gan)

            print('>%d, %d/%d, d1=%.3f, d2=%.3f, g=%.3f' % (i+1, j+1, num_batches_per_epoch, d1_loss, d2_loss, gan_loss))

        d1_loss_hist.append(d1_loss)
        d2_loss_hist.append(d2_loss)
        gan_loss_hist.append(gan_loss)
        if (i+1) % 50 == 0:
            filename = 'generator_model_%03d.keras' % (i + 1)
            gen_model.save(filename)

    plt.plot(d1_loss_hist, label='d-real')
    plt.plot(d2_loss_hist, label='d-fake')
    plt.plot(gan_loss_hist, label='gan')
    plt.legend()
    plt.savefig("Loss Plot.png")

disc_model = discriminator()
gen_model = generator()
gan_model = gan(gen_model, disc_model)
dataset = load_dataset()

train(gen_model, disc_model, gan_model, dataset)
deep-learning computer-vision conv-neural-network generative-adversarial-network dcgan
1个回答
0
投票

gan_model
函数中,您禁用了
disc_model
的训练,这意味着您的鉴别器实际上从未接受过训练。

您需要修改

train
函数以在第一个循环期间启用鉴别器训练,并在优化生成器时禁用它。

for i in range(epochs):
    for j in range(num_batches_per_epoch):
        # enable discriminator training
        disc_model.trainable = True
        X_real, y_real = generate_real_samples(dataset, batch_size // 2)
        d1_loss = disc_model.train_on_batch(X_real, y_real)

        X_fake, y_fake = generate_fake_samples(gen_model, batch_size // 2)
        d2_loss = disc_model.train_on_batch(X_fake, y_fake)

        # disable discriminator training
        disc_model.trainable = False
        X_gan = generate_latent_points(batch_size)
        y_gan = np.ones((batch_size, 1))
        gan_loss = gan_model.train_on_batch(X_gan, y_gan)
© www.soinside.com 2019 - 2024. All rights reserved.