条件生成对抗网络(Conditional GAN,简称CGAN)是一种GAN的变种,它允许我们通过提供条件信息来生成特定类型的数据。这是通过在生成器和判别器中添加条件标签实现的。
1. 理解条件 GAN 与传统的GAN不同,CGAN在生成数据时引入了额外的信息,例如类别标签。这使得模型能够生成特定类别的样本。例如,在图像生成任务中,我们可以输入特定的数字标签(如 0-9),模型则会生成相应的数字图像。
1.1 结构概述 CGAN模型包含两个主要的部分:
生成器(Generator) :接收随机噪声 z
和条件信息 y
(如类别标签),输出生成的数据 G(z | y)
。
判别器(Discriminator) :接收真实数据和生成数据连同条件信息 y
,输出数据为真实的概率 D(x | y)
。
2. 条件 GAN 的数学基础 令:
在CGAN中,我们的目标是最大化对抗损失,可以表示为:
$$ \min_G \max_D V(D, G) = \mathbb{E}{x,y}[ \log D(x | y)] + \mathbb{E} {z,y}[\log(1 - D(G(z | y) | y))] $$
其中,第一项是对真实样本的判别,第二项是对生成样本的判别。
3. 实现条件 GAN 我们将使用 TensorFlow
和 Keras
来实现一个简单的条件 GAN。以下是生成手写数字图像(MNIST数据集)的示例。
3.1 导入必要的库 1 2 3 4 5 import numpy as npimport matplotlib.pyplot as pltimport tensorflow as tffrom tensorflow import kerasfrom tensorflow.keras import layers
3.2 加载和预处理数据 我们使用 MNIST 数据集,其中每个样本都有一个数字标签。
1 2 3 4 5 6 7 (x_train, y_train), (_, _) = keras.datasets.mnist.load_data() x_train = x_train / 255.0 x_train = np.expand_dims(x_train, axis=-1 ) num_classes = 10
3.3 构建生成器 生成器将随机噪声和条件标签作为输入,并生成图像。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 def build_generator (): noise_shape = (100 ,) label_shape = (num_classes,) noise_input = layers.Input(shape=noise_shape) label_input = layers.Input(shape=label_shape) model_input = layers.Concatenate()([noise_input, label_input]) x = layers.Dense(256 , activation='relu' )(model_input) x = layers.Dense(512 , activation='relu' )(x) x = layers.Dense(1024 , activation='relu' )(x) output = layers.Dense(28 * 28 * 1 , activation='tanh' )(x) output = layers.Reshape((28 , 28 , 1 ))(output) generator = keras.models.Model([noise_input, label_input], output) return generator generator = build_generator() generator.summary()
3.4 构建判别器 判别器接收图像和标签,预测图像的真实性。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 def build_discriminator (): image_shape = (28 , 28 , 1 ) label_shape = (num_classes,) image_input = layers.Input(shape=image_shape) label_input = layers.Input(shape=label_shape) flat_image = layers.Flatten()(image_input) model_input = layers.Concatenate()([flat_image, label_input]) x = layers.Dense(512 , activation='relu' )(model_input) x = layers.Dense(256 , activation='relu' )(x) output = layers.Dense(1 , activation='sigmoid' )(x) discriminator = keras.models.Model([image_input, label_input], output) discriminator.compile (optimizer='adam' , loss='binary_crossentropy' , metrics=['accuracy' ]) return discriminator discriminator = build_discriminator() discriminator.summary()
3.5 训练条件 GAN 训练过程中,我们需要交替训练生成器和判别器。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 def train_cgan (epochs, batch_size ): for epoch in range (epochs): for _ in range (x_train.shape[0 ] // batch_size): idx = np.random.randint(0 , x_train.shape[0 ], batch_size) real_images = x_train[idx] real_labels = y_train[idx] noise = np.random.normal(0 , 1 , (batch_size, 100 )) random_labels = np.random.randint(0 , num_classes, batch_size) random_labels_one_hot = keras.utils.to_categorical(random_labels, num_classes) generated_images = generator.predict([noise, random_labels_one_hot]) d_loss_real = discriminator.train_on_batch([real_images, keras.utils.to_categorical(real_labels, num_classes)], np.ones((batch_size, 1 ))) d_loss_fake = discriminator.train_on_batch([generated_images, random_labels_one_hot], np.zeros((batch_size, 1 ))) d_loss = 0.5 * np.add(d_loss_real, d_loss_fake) noise = np.random.normal(0 , 1 , (batch_size, 100 )) random_labels = np.random.randint(0 , num_classes, batch_size) random_labels_one_hot = keras.utils.to_categorical(random_labels, num_classes) g_loss = combined.train_on_batch([noise, random_labels_one_hot], np.ones((batch_size, 1 ))) print (f"{epoch} /{epochs} [D loss: {d_loss[0 ]:.4 f} , acc.: {100 * d_loss[1 ]:.2 f} ] [G loss: {g_loss:.4 f} ]" ) train_cgan(epochs=10000 , batch_size=64 )
3.6 生成图像 最后,我们可以使用生成器生成与指定标签相对应的图像。
def generate_images(num_images):
noise = np.random.normal(0, 1, (num_images, 100))
random_labels = np.random.randint(0, num_classes, num_images)
random_labels_one_hot