📜  使用 Keras 的深度卷积 GAN(1)

📅  最后修改于: 2023-12-03 14:49:42.619000             🧑  作者: Mango

使用 Keras 的深度卷积 GAN

深度卷积 GAN (DCGAN)是一种生成对抗网络 (GAN) 的变体,它使用深度卷积神经网络来生成真实的图像。Keras 是一个高级神经网络 API,它能够以清晰、简单的方式创建深度学习模型。在本文中,我们将介绍如何使用 Keras 实现深度卷积 GAN。

程序示例

首先,我们需要导入 Keras 和必要的 Python 库。

import numpy as np
from keras.layers import Input, Dense, Reshape, Flatten, Dropout
from keras.layers import BatchNormalization, Activation, ZeroPadding2D
from keras.layers.advanced_activations import LeakyReLU
from keras.layers.convolutional import UpSampling2D, Conv2D
from keras.models import Sequential, Model
from keras.optimizers import Adam
from keras.datasets import mnist
import matplotlib.pyplot as plt

接下来,我们需要加载 MNIST 数据,并将像素值归一化到 [-1, 1]。

(X_train, _), (_, _) = mnist.load_data()
X_train = X_train / 127.5 - 1.
X_train = np.expand_dims(X_train, axis=3)

接下来,我们将定义生成器。

def build_generator():

    model = Sequential()

    model.add(Dense(256 * 7 * 7, activation="relu", input_dim=100))
    model.add(Reshape((7, 7, 256)))
    model.add(UpSampling2D())
    model.add(Conv2D(128, kernel_size=3, padding="same"))
    model.add(BatchNormalization(momentum=0.8))
    model.add(Activation("relu"))
    model.add(UpSampling2D())
    model.add(Conv2D(64, kernel_size=3, padding="same"))
    model.add(BatchNormalization(momentum=0.8))
    model.add(Activation("relu"))
    model.add(Conv2D(1, kernel_size=3, padding="same"))
    model.add(Activation("tanh"))

    noise = Input(shape=(100,))
    img = model(noise)

    return Model(noise, img)

然后我们将定义判别器。

def build_discriminator():

    model = Sequential()

    model.add(Conv2D(32, kernel_size=3, strides=2, input_shape=(28, 28, 1), padding="same"))
    model.add(LeakyReLU(alpha=0.2))
    model.add(Dropout(0.25))
    model.add(Conv2D(64, kernel_size=3, strides=2, padding="same"))
    model.add(BatchNormalization(momentum=0.8))
    model.add(LeakyReLU(alpha=0.2))
    model.add(Dropout(0.25))
    model.add(Conv2D(128, kernel_size=3, strides=2, padding="same"))
    model.add(BatchNormalization(momentum=0.8))
    model.add(LeakyReLU(alpha=0.2))
    model.add(Dropout(0.25))
    model.add(Conv2D(256, kernel_size=3, strides=1, padding="same"))
    model.add(BatchNormalization(momentum=0.8))
    model.add(LeakyReLU(alpha=0.2))
    model.add(Dropout(0.25))
    model.add(Flatten())
    model.add(Dense(1, activation='sigmoid'))

    img = Input(shape=(28, 28, 1))
    validity = model(img)

    return Model(img, validity)

接下来,我们将构建 GAN 模型。

def build_gan(generator, discriminator):

    discriminator.trainable = False

    gan_input = Input(shape=(100,))
    x = generator(gan_input)
    gan_output = discriminator(x)

    gan = Model(gan_input, gan_output)
    gan.compile(loss='binary_crossentropy', optimizer=Adam(0.0002, 0.5))

    return gan

现在,我们可以训练 GAN 模型了。

def train():

    # Load the dataset
    (X_train, _), (_, _) = mnist.load_data()

    # Rescale -1 to 1
    X_train = X_train / 127.5 - 1.
    X_train = np.expand_dims(X_train, axis=3)

    batch_size = 32
    half_batch = 16
    iterations = 10000

    generator = build_generator()
    discriminator = build_discriminator()
    gan = build_gan(generator, discriminator)

    for iteration in range(iterations):

        # ---------------------
        #  Train Discriminator
        # ---------------------

        # Select a random half batch of images
        idx = np.random.randint(0, X_train.shape[0], half_batch)
        imgs = X_train[idx]

        # Sample noise and generate a half batch of new images
        noise = np.random.normal(0, 1, (half_batch, 100))
        gen_imgs = generator.predict(noise)

        # Train the discriminator (real classified as ones and generated as zeros)
        d_loss_real = discriminator.train_on_batch(imgs, np.ones((half_batch, 1)))
        d_loss_fake = discriminator.train_on_batch(gen_imgs, np.zeros((half_batch, 1)))
        d_loss = 0.5 * np.add(d_loss_real, d_loss_fake)

        # ---------------------
        #  Train Generator
        # ---------------------

        # Sample full batch of noise and generate a batch of new images
        noise = np.random.normal(0, 1, (batch_size, 100))
        valid_y = np.array([1] * batch_size)
        g_loss = gan.train_on_batch(noise, valid_y)

        # Plot losses and generated images
        if iteration % 1000 == 0:
            print("%d [D loss: %f] [G loss: %f]" % (iteration, d_loss, g_loss))
            save_generated_images(generator)

最后,我们定义一个函数用于保存生成的图像。

def save_generated_images(generator):

    # Generate sample noise
    noise = np.random.normal(0, 1, (25, 100))

    # Generate images from noise
    gen_imgs = generator.predict(noise)

    # Rescale images 0 - 1
    gen_imgs = 0.5 * gen_imgs + 0.5

    # Plot images
    fig, axs = plt.subplots(5, 5)
    fig.suptitle("Generated Images")
    cnt = 0
    for i in range(5):
        for j in range(5):
            axs[i, j].imshow(gen_imgs[cnt, :, :, 0], cmap='gray')
            axs[i, j].axis('off')
            cnt += 1
    plt.show()

现在,我们可以启动训练:

train()

这个程序将训练一个深度卷积 GAN,并生成手写数字图像。每 1000 个迭代周期,它将输出判别器和生成器的损失,并生成 25 个手写数字图像。