4 GAN 的基本概念

4 GAN 的基本概念

什么是生成式对抗网络 (GAN)

生成式对抗网络(Generative Adversarial Network,简称 GAN)是一种深度学习模型,由两个神经网络组成:一个是生成器(Generator),一个是判别器(Discriminator)。这两个网络相互对抗,进行训练,从而能够生成与真实数据相似的假数据。

GAN 的主要组成部分

  1. 生成器 (Generator)

    • 生成器的目标是从一个随机噪声(通常是服从均匀分布或正态分布的随机向量)生成与真实样本类似的数据。它的输入是一个随机噪声向量,输出是生成的数据样本。
  2. 判别器 (Discriminator)

    • 判别器的目标是区分输入的数据是来自真实分布(真实样本)还是来自生成器(生成样本)。它接收一个数据样本并输出一个概率值,表示该样本为真实的概率。

GAN 的训练过程

  1. 初始化:随机初始化生成器和判别器的参数。

  2. 样本选择

    • 从真实数据集中选择一小批样本 (real samples)。
    • 从生成器中生成一小批假样本 (fake samples)。
  3. 训练判别器

使用真实样本和假样本训练判别器。判别器的损失函数通常为交叉熵损失,目标是最大化正确分类真实样本和假样本的概率。

$$
r = \mathbb{E}_{z \sim p_z} [\log(1 - D(G(z)))]
$$

$$
L_D = -\mathbb{E}_{x \sim p_\text{data}} [\log D(x)] - r
$$

  1. 训练生成器

生成器的目标是最大化判别器对生成样本的误判率。即,生成器希望判别器尽可能将其生成的假样本视为真实的。

$$ L_G = -\mathbb{E}_{z \sim p_z} [\log D(G(z))] $$

  1. 迭代
    • 重复以上步骤,直到生成器生成的样本质量足够高或达到预设的训练轮数。

GAN 的优缺点

优点

  • 高效生成:GAN 能够生成高质量的图像、视频等数据。
  • 灵活性强:可以在多种应用中使用,如图像生成、图像修复等。

缺点

  • 训练不稳定:GAN 的两种网络相互对抗,可能导致训练不稳定,甚至出现模式崩溃(Mode Collapse)。
  • 超参数敏感:需要仔细调整网络结构和超参数,否则可能无法收敛。

示例代码

以下是使用 PyTorch 实现一个简单的 GAN 的示例代码,用于生成手写数字(MNIST 数据集)。

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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
import torch
import torch.nn as nn
import torch.optim as optim
from torchvision import datasets, transforms
from torch.utils.data import DataLoader

# 超参数
latent_size = 100
learning_rate = 0.0002
batch_size = 64
num_epochs = 100

# 数据集
transform = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize((0.5,), (0.5,)) # 数据归一化
])

dataset = datasets.MNIST(root='data', train=True, transform=transform, download=True)
dataloader = DataLoader(dataset, batch_size=batch_size, shuffle=True)

# 生成器模型
class Generator(nn.Module):
def __init__(self):
super(Generator, self).__init__()
self.model = nn.Sequential(
nn.Linear(latent_size, 256),
nn.ReLU(),
nn.Linear(256, 512),
nn.ReLU(),
nn.Linear(512, 1024),
nn.ReLU(),
nn.Linear(1024, 28 * 28), # MNIST 图像为 28x28
nn.Tanh(), # 输出范围 [-1, 1]
)

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

# 判别器模型
class Discriminator(nn.Module):
def __init__(self):
super(Discriminator, self).__init__()
self.model = nn.Sequential(
nn.Linear(28 * 28, 512),
nn.LeakyReLU(0.2),
nn.Linear(512, 256),
nn.LeakyReLU(0.2),
nn.Linear(256, 1),
nn.Sigmoid() # 输出范围 [0, 1]
)

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

# 实例化模型
generator = Generator()
discriminator = Discriminator()

# 优化器
optim_G = optim.Adam(generator.parameters(), lr=learning_rate)
optim_D = optim.Adam(discriminator.parameters(), lr=learning_rate)

# 训练过程
for epoch in range(num_epochs):
for i, (imgs, _) in enumerate(dataloader):
# 将图像转化为向量
real_imgs = imgs.view(-1, 28 * 28)

# 训练判别器
z = torch.randn(imgs.size(0), latent_size) # 随机噪声
fake_imgs = generator(z)

# 判别器的标签
real_labels = torch.ones(imgs.size(0), 1)
fake_labels = torch.zeros(imgs.size(0), 1)

# 计算损失
loss_D = nn.BCELoss()(discriminator(real_imgs), real_labels) + \
nn.BCELoss()(discriminator(fake_imgs.detach()), fake_labels)

# 更新判别器
optim_D.zero_grad()
loss_D.backward()
optim_D.step()

# 训练生成器
loss_G = nn.BCELoss()(discriminator(fake_imgs), real_labels)

# 更新生成器
optim_G.zero_grad()
loss_G.backward()
optim_G.step()

print(f'Epoch [{epoch+1}/{num_epochs}], Loss D: {loss_D.item():.4f}, Loss G: {loss_G.item():.4f}')

# 生成假图像的示例
with torch.no_grad():
z = torch.randn(16, latent_size)
generated_imgs = generator(z).view(-1, 1, 28, 28)

# 这里可以添加绘图代码以显示生成的图像

结论

生成式对抗网络(GAN)通过生成器和判别器的对抗训练,能够生成高质量的样本。虽然训练过程可能存在挑战,但其在图像生成等领域的巨大潜力使其成为深度学习中一个

5 GAN 的工作原理

5 GAN 的工作原理

生成对抗网络(GAN)是由 Ian Goodfellow 等人在 2014 年提出的一种深度学习框架,用于生成与真实数据分布相似的新数据。它包含两个主要的构成部分:生成器(Generator)和判别器(Discriminator)。这两个部分通过对抗性训练来相互竞争,以达到生成高质量样本的目的。

1. GAN 的基本结构

GAN 由两个神经网络组成:

  • 生成器(Generator): 该网络负责接收随机噪声作为输入,并生成看似真实的样本。生成器的目标是“欺骗”判别器,使其无法区分生成样本与真实样本。

  • 判别器(Discriminator): 该网络负责判断输入样本是来自真实数据集还是生成器生成的样本。判别器的目标是尽可能准确地识别输入样本的来源。

2. 对抗训练

对抗训练过程是 GAN 的核心,其目标是使生成器和判别器在零和博弈中逐渐优化。具体步骤如下:

  1. 生成器从潜在空间(通常是高维的随机噪声)中采样。

    1
    noise = np.random.normal(0, 1, size=(batch_size, noise_dim))
  2. 生成器通过它的模型生成样本。

    1
    generated_samples = generator.predict(noise)
  3. 判别器接收真实样本和生成样本,并学习去区分二者的差异。判别器输出一个概率值,表示其判断输入样本为真实样本的可能性。

  4. 计算判别器的损失,使用真实样本和生成样本的标签(真实样本标签为 1,生成样本标签为 0):

    1
    2
    d_loss_real = discriminator.train_on_batch(real_samples, labels_real)
    d_loss_fake = discriminator.train_on_batch(generated_samples, labels_fake)
  5. 更新判别器的权重,使其更加准确地分类。

  6. 生成器根据判别器的输出更新自己的权重,以提高生成样本的质量,使其更像真实数据。

    1
    g_loss = combined.train_on_batch(noise, labels_real)

3. 损失函数

GAN 的训练损失函数是生成器和判别器的对抗损失。公式为:

  • 判别器的损失函数:

    1
    L_D = - (E[log(D(x))] + E[log(1 - D(G(z)))])
  • 生成器的损失函数:

    1
    L_G = - E[log(D(G(z)))]

其中,D(x) 表示判别器对真实样本 x 的输出,G(z) 表示生成器对噪声 z 的输出。

4. 训练流程示例

以下是一个简单的 MNIST 数据集上训练 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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
import numpy as np
import tensorflow as tf
from tensorflow.keras import layers

# 定义生成器
def build_generator():
model = tf.keras.Sequential()
model.add(layers.Dense(128, activation='relu', input_dim=100))
model.add(layers.Dense(784, activation='sigmoid')) # 28x28
return model

# 定义判别器
def build_discriminator():
model = tf.keras.Sequential()
model.add(layers.Dense(128, activation='relu', input_shape=(784,)))
model.add(layers.Dense(1, activation='sigmoid'))
return model

# 生成器和判别器实例化
generator = build_generator()
discriminator = build_discriminator()

# 构建我们 GAN 模型
discriminator.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
discriminator.trainable = False # 在训练生成器时,固定判别器

# GAN 模型
model_gan = tf.keras.Sequential([generator, discriminator])
model_gan.compile(loss='binary_crossentropy', optimizer='adam')

# 训练 GAN
for epoch in range(num_epochs):
# 随机选择真实样本
real_samples = get_real_samples()
noise = np.random.normal(0, 1, size=(batch_size, 100))
generated_samples = generator.predict(noise)

# 训练判别器
labels_real = np.ones((batch_size, 1))
labels_fake = np.zeros((batch_size, 1))
d_loss_real = discriminator.train_on_batch(real_samples, labels_real)
d_loss_fake = discriminator.train_on_batch(generated_samples, labels_fake)

# 训练生成器
noise = np.random.normal(0, 1, size=(batch_size, 100))
g_loss = model_gan.train_on_batch(noise, labels_real)

print(f'Epoch: {epoch + 1}, D Loss: {d_loss_real[0]}, G Loss: {g_loss}')

5. 总结

生成对抗网络通过生成器和判别器之间的对抗训练,能够生成出极具真实感的样本。GAN 的工作原理是一种独特的无监督学习方法,通过优化损失函数实现生成模型的训练。这类模型的应用在图像生成、图像翻译以及增强学习等领域具有广泛的前景。

6 GAN 的训练过程详细教程

6 GAN 的训练过程详细教程

生成对抗网络(GAN,Generative Adversarial Networks)是一种深度学习模型,通过两个互相对抗的网络进行训练:生成器(Generator)和判别器(Discriminator)。在这一小节中,我们将详细探讨 GAN 的训练过程。

1. 初始化网络

在开始训练之前,我们需要定义和初始化生成器和判别器。

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
35
36
37
import torch
import torch.nn as nn
import torch.optim as optim

# 生成器 (Generator)
class Generator(nn.Module):
def __init__(self, input_dim, output_dim):
super(Generator, self).__init__()
self.model = nn.Sequential(
nn.Linear(input_dim, 128),
nn.ReLU(),
nn.Linear(128, output_dim),
nn.Tanh()
)

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

# 判别器 (Discriminator)
class Discriminator(nn.Module):
def __init__(self, input_dim):
super(Discriminator, self).__init__()
self.model = nn.Sequential(
nn.Linear(input_dim, 128),
nn.ReLU(),
nn.Linear(128, 1),
nn.Sigmoid()
)

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

# 参数定义
latent_dim = 100 # 噪声维度
data_dim = 784 # 例如,28x28 的图像展平后为 784
G = Generator(latent_dim, data_dim)
D = Discriminator(data_dim)

2. 定义损失函数和优化器

GAN 的训练涉及到两个损失函数,分别用于生成器和判别器。通常使用的损失函数是二元交叉熵损失。

1
2
3
4
5
6
criterion = nn.BCELoss()
lr = 0.0002 # 学习率

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

3. 训练过程

3.1 准备数据

在开始训练前,确保有一个数据集。例如,训练 MNIST 数据集。

1
2
3
4
5
6
7
8
9
10
from torchvision import datasets, transforms

# 数据加载和预处理
transform = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize((0.5,), (0.5,))
])

train_dataset = datasets.MNIST(root='./data', train=True, download=True, transform=transform)
train_loader = torch.utils.data.DataLoader(dataset=train_dataset, batch_size=128, shuffle=True)

3.2 训练循环

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
35
36
37
38
39
40
41
42
43
44
45
46
47
num_epochs = 200  # 总共训练的轮数

for epoch in range(num_epochs):
for i, (real_images, _) in enumerate(train_loader):
batch_size = real_images.size(0)

# 将图像展平
real_images = real_images.view(batch_size, -1)

# 真实标签和假标签
real_labels = torch.ones(batch_size, 1)
fake_labels = torch.zeros(batch_size, 1)

# 训练判别器
optimizer_D.zero_grad()

# 计算真实图像的损失
outputs = D(real_images)
d_loss_real = criterion(outputs, real_labels)

# 生成假图像
noise = torch.randn(batch_size, latent_dim)
fake_images = G(noise)

# 计算假图像的损失
outputs = D(fake_images.detach())
d_loss_fake = criterion(outputs, fake_labels)

# 组合损失并反向传播
d_loss = d_loss_real + d_loss_fake
d_loss.backward()
optimizer_D.step()

# 训练生成器
optimizer_G.zero_grad()

# 计算生成器的损失
outputs = D(fake_images)
g_loss = criterion(outputs, real_labels)

# 反向传播
g_loss.backward()
optimizer_G.step()

# 每轮打印损失
if (epoch + 1) % 10 == 0:
print(f'Epoch [{epoch + 1}/{num_epochs}], d_loss: {d_loss.item():.4f}, g_loss: {g_loss.item():.4f}')

3.3 生成样本

在训练完成后,我们可以利用生成器生成样本:

1
2
3
4
5
6
7
8
9
10
11
12
13
import matplotlib.pyplot as plt

# 生成样本
G.eval() # 设置为评估模式
with torch.no_grad():
noise = torch.randn(16, latent_dim)
generated_images = G(noise).view(-1, 1, 28, 28).cpu()

# 可视化生成的样本
grid_img = torchvision.utils.make_grid(generated_images, nrow=4, normalize=True)
plt.imshow(grid_img.permute(1, 2, 0).numpy())
plt.axis('off')
plt.show()

4. 训练过程中的注意事项

  • 模式崩溃(Mode Collapse):GAN 训练中常见的问题,当生成器仅生成少量样本时,可以通过调整模型或引入更多样本进行缓解。

  • 调整超参数:学习率、批量大小和网络结构都可能影响训练效果,尝试不同的值。

  • 监控训练:经常监控损失值和生成样本,以观察是否正常。

5. 总结

在这一小节中,我们详细探讨了 GAN 的训练过程,包括网络的初始化、损失函数的定义、训练循环、生成样本以及注意事项。通过理解这些步骤,你可以很好地训练一个 GAN 模型并生成新样本。