7 从零开始的生成对抗网络(GAN)教程 - 生成器与判别器的设计

7 从零开始的生成对抗网络(GAN)教程 - 生成器与判别器的设计

在本节中,我们将详细讨论生成对抗网络(GAN)的核心组件:生成器判别器。我们将分析它们的结构,并提供代码示例。在开始之前,请确保您了解 GAN 的基本概念。

1. GAN 简介

生成对抗网络 (GAN) 是一种由两部分组成的深度学习模型:生成器 (G) 和判别器 (D)。生成器旨在生成与真实数据相似的假数据,而判别器则试图区分真实数据和生成的数据。两者通过对抗训练相互竞争,从而使生成器生成的假数据逐渐逼近真实数据的分布。

2. 生成器(Generator)

2.1 生成器的定义

生成器的目的是接受一个随机噪声向量 z(通常从标准正态分布中抽取)并生成一组假数据 G(z)。生成器希望通过训练使其生成的数据尽可能真实。

2.2 生成器的结构

生成器通常由一系列的全连接层(Fully Connected Layers)、卷积层(Convolutional Layers)、批量归一化(Batch Normalization)和激活函数(如ReLULeaky ReLU)构成。

2.2.1 实现示例

下面是一个生成器的实现示例,使用 TensorFlow 和 Keras:

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
import tensorflow as tf
from tensorflow.keras import layers

def create_generator(latent_dim):
model = tf.keras.Sequential()

# 通过全连接层将噪声映射到更高维度
model.add(layers.Dense(256, activation='relu', input_dim=latent_dim))
model.add(layers.BatchNormalization())

model.add(layers.Dense(512, activation='relu'))
model.add(layers.BatchNormalization())

model.add(layers.Dense(1024, activation='relu'))
model.add(layers.BatchNormalization())

# 输出层生成图像数据(假设生成28x28的图像)
model.add(layers.Dense(28 * 28 * 1, activation='tanh'))
model.add(layers.Reshape((28, 28, 1))) # 将向量重塑成图像

return model

latent_dim = 100
generator = create_generator(latent_dim)
generator.summary()

2.3 生成器的激活函数

在生成器的最后一层,我们通常使用 tanh 激活函数,以将生成的像素值范围限制在 -11 之间,这对于图像数据十分常见。

3. 判别器(Discriminator)

3.1 判别器的定义

判别器的任务是接受一个输入(真实数据或生成的数据)并输出一个概率值,表示输入数据为真实数据的可能性。判别器的目标是区分真实数据和假数据。

3.2 判别器的结构

判别器通常由卷积层全连接层和激活函数(如Leaky ReLU)组成。它将输入图像缩小并收集特征,最终输出一个单一的概率值。

3.2.1 实现示例

下面是一个判别器的实现示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
def create_discriminator(img_shape):
model = tf.keras.Sequential()

model.add(layers.Conv2D(32, kernel_size=3, strides=2, input_shape=img_shape, padding='same'))
model.add(layers.LeakyReLU(alpha=0.2))

model.add(layers.Conv2D(64, kernel_size=3, strides=2, padding='same'))
model.add(layers.LeakyReLU(alpha=0.2))
model.add(layers.BatchNormalization())

model.add(layers.Conv2D(128, kernel_size=3, strides=2, padding='same'))
model.add(layers.LeakyReLU(alpha=0.2))
model.add(layers.BatchNormalization())

model.add(layers.Flatten())
model.add(layers.Dense(1, activation='sigmoid')) # 输出概率值

return model

img_shape = (28, 28, 1)
discriminator = create_discriminator(img_shape)
discriminator.summary()

3.3 判别器的激活函数

在判别器的最后一层,我们使用 sigmoid 激活函数,这使得输出在 01 之间,表示输入数据为真实数据的概率。

4. 小结

在本节中,我们详细介绍了生成对抗网络中生成器与判别器的设计与实现。生成器和判别器的结构均由多个层组成,采用合适的激活函数来实现其目标。接下来,您可以通过训练这两个组件(在接下来的教程中)来实现数据生成。

请确保您了解整个 GAN 的训练过程,包括损失函数及其优化等内容。这将是下一步的关键部分。

8 生成对抗网络 (GAN) 经典模型介绍

8 生成对抗网络 (GAN) 经典模型介绍

生成对抗网络(GAN,Generative Adversarial Network)是一种深度学习框架,用于生成与真实数据具有相似分布的新数据。这一模型由 Ian Goodfellow 等人于 2014 年提出,已经在图像生成、图像修复、超分辨率等多个领域取得了显著成效。以下是对经典 GAN 模型的详细介绍。

1. GAN 的基本概念

在 GAN 中,有两个主要的组件:生成器(Generator)和判别器(Discriminator)。

1.1 生成器

生成器的任务是从一组随机噪声中生成逼真的数据样本。其目标是生成尽可能接近真实样本的“假”数据,通常使用随机噪声(如高斯分布或均匀分布)作为输入。

1.2 判别器

判别器的任务是区分输入样本是真实样本还是生成样本。其目标是准确地判断每个输入是来自真实数据分布还是生成模型中的生成数据。

2. GAN 的工作原理

GAN 是通过一个“对抗”的过程进行训练。生成器和判别器相互竞争:

  1. 生成器试图生成尽可能“真实”的样本,以欺骗判别器。
  2. 判别器则试图提高其识别虚假样本的能力,以更好地判断输入。

对抗损失

GAN 通过最小化生成器的损失和最大化判别器的损失来进行训练。其损失函数可以用以下公式表示:

  • 生成器的目标:
    [
    L_G = -\mathbb{E}_{z \sim p_z(z)}[\log(D(G(z)))]
    ]

  • 判别器的目标:
    [
    L_D = -\mathbb{E}{x \sim p{data}(x)}[\log(D(x))] - \mathbb{E}_{z \sim p_z(z)}[\log(1 - D(G(z)))]
    ]

其中,( G(z) ) 是生成器生成的样本,( D(x) ) 是判别器对真实样本的输出,( p_z(z) ) 是生成器的输入噪声分布,( p_{data}(x) ) 是真实数据的分布。

3. GAN 的训练过程

GAN 的训练过程通常包括以下步骤:

  1. 初始化生成器和判别器的权重。

  2. 训练判别器

    • 从真实数据中抽取一批样本。
    • 从生成器生成一批样本。
    • 计算判别器的损失,并更新判别器的权重。
  3. 训练生成器

    • 通过判别器的输出来计算生成器的损失。
    • 更新生成器的权重。
  4. 反复进行上述步骤,直到生成样本的质量达到满意的程度。

4. 经典 GAN 示例

以下是一个简单的 GAN 实现示例,使用 TensorFlow 和 Keras 库来生成手写数字(如 MNIST 数据集)。

4.1 导入库

1
2
3
4
5
6
import numpy as np
import matplotlib.pyplot as plt
from keras.datasets import mnist
from keras.models import Sequential
from keras.layers import Dense, LeakyReLU
from keras.optimizers import Adam

4.2 构建生成器和判别器

1
2
3
4
5
6
7
8
9
10
11
12
13
def build_generator(latent_dim):
model = Sequential()
model.add(Dense(128, input_dim=latent_dim))
model.add(LeakyReLU(alpha=0.2))
model.add(Dense(784, activation='tanh'))
return model

def build_discriminator(input_shape):
model = Sequential()
model.add(Dense(128, input_shape=input_shape))
model.add(LeakyReLU(alpha=0.2))
model.add(Dense(1, activation='sigmoid'))
return model

4.3 训练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
32
33
34
def train_gan(epochs, batch_size, latent_dim):
(X_train, _), (_, _) = mnist.load_data()
X_train = X_train / 127.5 - 1.0 # 归一化到[-1, 1]
X_train = X_train.reshape(X_train.shape[0], 784)

generator = build_generator(latent_dim)
discriminator = build_discriminator((784,))

discriminator.compile(loss='binary_crossentropy', optimizer=Adam(0.0002, 0.5))

# 建立GAN模型
discriminator.trainable = False
gan_input = Sequential([generator])
gan_output = discriminator(gan_input.output)
gan = keras.models.Model(gan_input.input, gan_output)
gan.compile(loss='binary_crossentropy', optimizer=Adam(0.0002, 0.5))

for epoch in range(epochs):
# 训练判别器
idx = np.random.randint(0, X_train.shape[0], batch_size)
real_imgs = X_train[idx]
noise = np.random.normal(0, 1, (batch_size, latent_dim))
fake_imgs = generator.predict(noise)

d_loss_real = discriminator.train_on_batch(real_imgs, np.ones((batch_size, 1)))
d_loss_fake = discriminator.train_on_batch(fake_imgs, np.zeros((batch_size, 1)))

# 训练生成器
noise = np.random.normal(0, 1, (batch_size, latent_dim))
g_loss = gan.train_on_batch(noise, np.ones((batch_size, 1)))

# 输出训练过程的信息
if epoch % 100 == 0:
print(f"Epoch: {epoch}, D Loss: {d_loss_real + d_loss_fake}, G Loss: {g_loss}")

4.4 运行训练

在最后调用 train_gan() 函数,设置训练的轮数和每次训练的批量大小:

1
train_gan(epochs=30000, batch_size=64, latent_dim=100)

5. 总结

GAN 是一个强大的模型,能够生成与真实数据分布相似的新数据。通过生成器与判别器的对抗训练,GAN 可以学习到复杂的数据分布。尽管 GAN 具有很强的生成能力,仍然面临着一些挑战,例如模式崩溃(mode collapse)和不稳定的训练过程。因此,针对 GAN 的研究仍在不断深入,许多变种和改进算法也被提出以克服这些问题。

9 从零学生成式对抗网络 (GAN) - DCGAN 章节

9 从零学生成式对抗网络 (GAN) - DCGAN 章节

什么是 DCGAN?

DCGAN(深度卷积生成对抗网络)是一种特殊类型的生成对抗网络,它结合了经典的 GAN 结构与卷积网络的优势,使得生成的图像质量得到了显著的提升。DCGAN 主要应用于图像生成任务,尤其适合于生成具有空间结构的高维数据(如图像)。

DCGAN 的架构

DCGAN 的架构由两个主要组成部分构成:生成器 G 和判别器 D。这两部分通过对抗训练的方式相互竞争。

  1. 生成器(Generator)

    • 负责生成假图像,输入是随机噪声(通常是服从正态分布的向量)。
    • 通过多个反卷积层(Transposed Convolution)和激活函数 ReLU,逐步上采样生成图像。
  2. 判别器(Discriminator)

    • 负责判断输入的图像是真实的(来自训练数据)还是生成的。
    • 由多个卷积层(Convolution)和激活函数 Leaky ReLU 组成,逐渐下采样图像得到二元分类结果(真实或假)。

DCGAN 的关键特性

  • 使用卷积层
    DCGAN 采用卷积和反卷积层替代全连接层,在图像生成和判别上更加高效。

  • 批归一化(Batch Normalization)
    在生成器和判别器的每个卷积层之后加入批归一化,有助于稳定训练过程。

  • 使用 ReLULeaky ReLU 激活函数
    生成器采用 ReLU 激活函数,而判别器采用 Leaky ReLU,这样可以改善模型的学习能力。

  • 去掉全连接层
    DCGAN 强调使用卷积结构而非全连接层,以更好地处理高维数据。

DCGAN 的基本代码实现

以下将给出一个简单的 DCGAN 实现的示例代码,其中使用 PyTorch 库来构建模型。

1. 导入必要的库

1
2
3
4
5
import torch
import torch.nn as nn
import torch.optim as optim
from torchvision import datasets, transforms
from torchvision.utils import save_image

2. 定义生成器(Generator)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Generator(nn.Module):
def __init__(self, z_dim=100):
super(Generator, self).__init__()
self.model = nn.Sequential(
nn.ConvTranspose2d(z_dim, 128, 4, 1, 0, bias=False),
nn.BatchNorm2d(128),
nn.ReLU(True),
nn.ConvTranspose2d(128, 64, 4, 2, 1, bias=False),
nn.BatchNorm2d(64),
nn.ReLU(True),
nn.ConvTranspose2d(64, 1, 4, 2, 1, bias=False),
nn.Tanh()
)

def forward(self, z):
return self.model(z)

3. 定义判别器(Discriminator)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Discriminator(nn.Module):
def __init__(self):
super(Discriminator, self).__init__()
self.model = nn.Sequential(
nn.Conv2d(1, 64, 4, 2, 1, bias=False),
nn.LeakyReLU(0.2, inplace=True),
nn.Conv2d(64, 128, 4, 2, 1, bias=False),
nn.BatchNorm2d(128),
nn.LeakyReLU(0.2, inplace=True),
nn.Conv2d(128, 1, 4, 1, 0, bias=False),
nn.Sigmoid() # 输出 0 到 1 的概率
)

def forward(self, img):
return self.model(img)

4. 初始化相关变量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 超参数
z_dim = 100
num_epochs = 50
batch_size = 64
lr = 0.0002

# 数据集和数据加载器
transform = transforms.Compose([
transforms.Resize(64),
transforms.ToTensor(),
transforms.Normalize([0.5], [0.5])
])
dataset = datasets.MNIST(root='./data', train=True, download=True, transform=transform)
data_loader = torch.utils.data.DataLoader(dataset, batch_size=batch_size, shuffle=True)

# 初始化生成器和判别器
G = Generator(z_dim=z_dim).cuda()
D = Discriminator().cuda()

# 初始化优化器
optimizer_G = optim.Adam(G.parameters(), lr=lr)
optimizer_D = optim.Adam(D.parameters(), lr=lr)

5. 训练过程

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
32
33
# 训练 DCGAN
for epoch in range(num_epochs):
for i, (real_images, _) in enumerate(data_loader):
batch_size = real_images.size(0)

# 将真实图像放入 CUDA
real_images = real_images.cuda()

# 训练判别器
D.zero_grad()
z = torch.randn(batch_size, z_dim, 1, 1).cuda()
fake_images = G(z)

real_loss = nn.functional.binary_cross_entropy(D(real_images), torch.ones(batch_size, 1).cuda())
fake_loss = nn.functional.binary_cross_entropy(D(fake_images.detach()), torch.zeros(batch_size, 1).cuda())
d_loss = real_loss + fake_loss
d_loss.backward()
optimizer_D.step()

# 训练生成器
G.zero_grad()
g_loss = nn.functional.binary_cross_entropy(D(fake_images), torch.ones(batch_size, 1).cuda())
g_loss.backward()
optimizer_G.step()

if i % 100 == 0:
print(f'Epoch [{epoch}/{num_epochs}], Step [{i}/{len(data_loader)}], D Loss: {d_loss.item()}, G Loss: {g_loss.item()}')

# 保存生成的图像
with torch.no_grad():
sample_noise = torch.randn(64, z_dim, 1, 1).cuda()
fake_samples = G(sample_noise)
save_image(fake_samples, f'fake_images_epoch_{epoch}.png', normalize=True)

总结

通过以上步骤,我们建立了一个基本的 DCGAN 模型,该模型能够从随机噪声中生成 MNIST 手写数字图像。训练过程中的损失值(D LossG Loss)可以帮助我们监测模型的训练情况。DCGAN 是理解生成对抗网络的重要基础之一,通过对抗训练,生成器与