生成对抗网络(GAN)入门实战:从理论到MNIST手写数字生成

1次阅读
没有评论

共计 1858 个字符,预计需要花费 5 分钟才能阅读完成。

image.webp

概率分布视角下的 GAN 原理

生成对抗网络 (GAN) 的核心思想可以理解为两个神经网络在玩 minimax 游戏。生成器 $G$ 试图学习真实数据的分布 $p_{data}(x)$,而判别器 $D$ 则像警察一样判断样本来自真实数据还是生成器。它们的对抗目标可以用公式表达为:

生成对抗网络 (GAN) 入门实战:从理论到 MNIST 手写数字生成

$$
\min_G\max_D V(D,G) = \mathbb{E}{x\sim p[\log(1-D(G(z)))]
$$}}[\log D(x)] + \mathbb{E}_{z\sim p_z

  • 生成器:输入随机噪声 $z$,输出伪造数据 $G(z)$
  • 判别器:输入数据 $x$,输出该数据为真实数据的概率 $D(x)$

GAN vs 传统生成模型

与传统生成模型(如 VAE)相比,GAN 有显著优势:

  1. 生成质量更高,图像更清晰(VAE 往往生成模糊图像)
  2. 不需要明确的概率密度函数
  3. 可以学习到更复杂的数据分布

但 GAN 也存在挑战:

  • 训练不稳定,容易模式崩溃
  • 难以评估生成质量
  • 需要精心调参

DCGAN 实现 MNIST 手写数字生成

以下是使用 PyTorch 实现 DCGAN 的关键代码部分:

生成器定义

class Generator(nn.Module):
    def __init__(self, latent_dim):
        super().__init__()
        self.main = nn.Sequential(nn.Linear(latent_dim, 128*7*7),
            nn.BatchNorm1d(128*7*7),
            nn.LeakyReLU(0.2),
            nn.Unflatten(1, (128, 7, 7)),
            nn.ConvTranspose2d(128, 64, 4, stride=2, padding=1),
            nn.BatchNorm2d(64),
            nn.LeakyReLU(0.2),
            nn.ConvTranspose2d(64, 1, 4, stride=2, padding=1),
            nn.Tanh())

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

判别器定义

class Discriminator(nn.Module):
    def __init__(self):
        super().__init__()
        self.main = nn.Sequential(nn.Conv2d(1, 64, 4, stride=2, padding=1),
            nn.LeakyReLU(0.2),
            nn.Conv2d(64, 128, 4, stride=2, padding=1),
            nn.BatchNorm2d(128),
            nn.LeakyReLU(0.2),
            nn.Flatten(),
            nn.Linear(128*7*7, 1),
            nn.Sigmoid())

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

训练循环关键步骤

  1. 初始化模型和优化器
  2. 对每个 epoch:
  3. 训练判别器:
    • 用真实数据计算损失
    • 用生成数据计算损失
    • 反向传播更新判别器
  4. 训练生成器:
    • 用生成数据计算损失
    • 反向传播更新生成器

常见问题与解决方案

模式崩溃的 3 种应对方法

  1. Mini-batch 判别:让判别器能够看到 batch 内的多个样本
  2. 特征匹配:让生成器匹配真实数据的统计特征
  3. 历史平均:保持参数的移动平均

学习率与优化器选择

  • Adam 优化器通常效果较好
  • 学习率建议从 1e- 4 开始尝试
  • 判别器和生成器的学习率可以不同

判别器不能过强

如果判别器太强,生成器将无法获得有效的梯度信号。理想状态是两者保持动态平衡。

评估生成质量

我们可以使用 FID(Fréchet Inception Distance)分数来评估生成图像的质量。FID 分数越低,生成质量越好。

# 计算 FID 分数的示例代码
from torchmetrics.image.fid import FrechetInceptionDistance

fid = FrechetInceptionDistance()
# 真实数据
fid.update(real_images, real=True)
# 生成数据
fid.update(fake_images, real=False)
print(f'FID score: {fid.compute()}')

总结与扩展

通过这个 DCGAN 实现,我们成功生成了 MNIST 手写数字。GAN 是一个非常强大的生成模型,但也需要耐心调参。建议在 Colab 上运行完整代码:Colab 链接

扩展学习方向:

  • 条件 GAN(CGAN)
  • StyleGAN 系列
  • GAN 在图像超分辨率中的应用

希望这篇入门指南能帮助你理解 GAN 的基本原理和实现方法。在实践中遇到问题时,记住调参是 GAN 训练的重要部分,保持耐心!

正文完
 0
评论(没有评论)