老梁聊IT头像
深度学习:生成对抗网络 GAN 原理与图像生成应用封面图

深度学习:生成对抗网络 GAN 原理与图像生成应用

2014 年,Ian Goodfellow 在酒桌上想出了一个点子:让两个神经网络互相博弈——一个负责"造假",一个负责"打假",在对抗中共同进步。这便是 GAN。它能从噪声里"无中生有"出逼真人脸、画作、甚至药物分子。但 GAN 也是出了名地难训。本文推导它的目标函数,讲清为什么难训,以及工程师们是怎么把它"驯服"的。


一、极小极大博弈目标推导

GAN 同时训练两个网络:

  • 生成器 G:输入噪声 z ~ p_z,输出假样本 G(z),目标是骗过判别器。

  • 判别器 D:输入真样本 x ~ p_data 或假样本 G(z),输出"这是真的"的概率。

二者玩一个零和博弈,目标函数:

min_G max_D  V(D, G) = E_{x~p_data}[log D(x)] + E_{z~p_z}[log(1 - D(G(z)))]
  • 对 D:希望 D(x) 接近 1(真),D(G(z)) 接近 0(假),所以最大化 V。

  • 对 G:希望 D(G(z)) 接近 1,即最小化 V(等价于最大化 log D(G(z)))。

理论最优:当 G 完美拟合真实分布(p_g = p_data)时,最优判别器 D* = 1/2,此时 V 取到最小值 -log 4。也就是说,博弈的纳什均衡就是"生成分布 = 真实分布"——这正是 GAN 优雅的地方。


二、训练不稳定与模式崩溃

理想很丰满,现实三大坑:

  1. 模式崩溃(Mode Collapse):G 发现某几个样本能稳定骗过 D,于是只生成这几类,丢失多样性。比如人脸生成全是同一张脸。

  2. 梯度消失:当 D 太强,真假判别接近完美,log(1 - D(G(z))) 的梯度趋于 0,G 学不动。

  3. 超参敏感 + 振荡:G 和 D 必须"势均力敌"地同步提升,一方过强就训崩,对学习率、架构极其挑剔。

训练循环(交替更新):

for epoch in range(epochs):
    for real_imgs in dataloader:
        # ---- 训练判别器 D ----
        z = torch.randn(batch, z_dim, 1, 1)
        fake = generator(z).detach()
        d_loss = -torch.log(D(real_imgs)).mean() - torch.log(1 - D(fake)).mean()
        d_loss.backward(); d_opt.step()
​
        # ---- 训练生成器 G ----
        fake = generator(z)
        g_loss = -torch.log(D(fake)).mean()   # 希望 D(fake)->1
        g_loss.backward(); g_opt.step()

三、WGAN 等改进方案

WGAN(Wasserstein GAN) 用 Earth-Mover(推土机)距离替换原始 JS 散度,核心改动两点:

  1. 判别器改为"批评家"(Critic),去掉最后的 sigmoid,输出打分而非概率。

  2. 对 Critic 参数做** Lipschitz 约束**(原始 WGAN 用权重截断,后续 WGAN-GP 用梯度惩罚,更稳)。

好处:哪怕真假分布不重叠,梯度也不会消失,训练曲线更平滑、可监控。

# WGAN-GP 判别器损失(示意)
def critic_loss(real, fake, critic, lambda_gp=10):
    gp = gradient_penalty(critic, real, fake)   # 梯度惩罚项
    return (fake.mean() - real.mean()) + lambda_gp * gp

其他稳定技巧:

  • 谱归一化(Spectral Norm):约束每层权重的谱范数,天然满足 Lipschitz。

  • 标签平滑 / 历史缓存(Buffer):缓解 D 过拟合 recent fake、导致的振荡。

  • TTUR / 不同学习率:让 D 和 G 用不同步长。


四、DCGAN / StyleGAN 实战

4.1 DCGAN(入门标配)

用卷积反卷积构建 G/D,首次让 GAN 在卧室、人脸等数据集上稳定出图:

import torch.nn as nn
class Generator(nn.Module):
    def __init__(self, z_dim=100, fdim=64):
        super().__init__()
        self.net = nn.Sequential(
            nn.ConvTranspose2d(z_dim, fdim*8, 4, 1, 0), nn.BatchNorm2d(fdim*8), nn.ReLU(),
            nn.ConvTranspose2d(fdim*8, fdim*4, 4, 2, 1), nn.BatchNorm2d(fdim*4), nn.ReLU(),
            nn.ConvTranspose2d(fdim*4, fdim*2, 4, 2, 1), nn.BatchNorm2d(fdim*2), nn.ReLU(),
            nn.ConvTranspose2d(fdim*2, 3, 4, 2, 1), nn.Tanh(),
        )
    def forward(self, z): return self.net(z.view(z.size(0), z.size(1), 1, 1))

4.2 StyleGAN(可控生成)

StyleGAN 把隐码解耦成"风格向量",通过 AdaIN 注入各层,实现发型、年龄、姿态的解耦控制,是当代人脸生成的事实标准。其核心思想(映射网络 + 风格调制)已成为生成模型的通用范式。


五、FID 评估与扩散模型对比

生成质量怎么量化?FID(Frechet Inception Distance) 用 Inception 特征分布的距离衡量"真假样本有多像",越低越好(< 10 通常算好)。IS(Inception Score)则衡量多样性和清晰度,但 FID 更受认可。

GAN vs Diffusion 此消彼长:2020 年后,扩散模型(DDPM、Stable Diffusion)在稳定性和可控性上压过 GAN,尤其文生图领域几乎被扩散占领。但 GAN 在实时、低算力、可控编辑场景(如 StyleGAN 的人脸属性编辑、GAN-based 超分)仍有不可替代的地位。


六、总结

GAN 用"对抗"这一极简思想打开了生成式深度学习的大门,其极小极大博弈、模式崩溃、WGAN 改进是理解所有生成模型的基石。尽管扩散模型来势汹汹,GAN 在可控生成和实时性上的积累依然厚实。学 GAN,不为追新,而为理解"让两个网络互相教对方变强"这一深刻范式。

参考资料

  1. Goodfellow, I., et al. (2014). Generative Adversarial Networks.

  2. Arjovsky, M., et al. (2017). Wasserstein GAN (WGAN).

  3. Gulrajani, I., et al. (2017). Improved Training of WGAN (WGAN-GP).

  4. Karras, T., et al. (2019). A Style-Based Generator Architecture for GANs (StyleGAN).

往期回顾


关注作者,继续《深度学习工程化》专栏:下一篇讲"模型训好了怎么塞进手机"——量化、剪枝与 ONNX 部署。


📚 本篇出自专栏《深学之路:从感知机到智能体》 —— 从感知机到大模型智能体的完整深度学习连载(基础+工程化 +扩散模型 / RAG / Agent 等)。每篇附可运行代码与原创实验,收藏专栏不迷路。

转载自 CSDN-专业IT技术社区

原文链接:https://blog.csdn.net/liangjinhu/article/details/169630792

文章来源转载

评论

评论列表

微信小程序
QQ小程序

关于作者

点赞数:0
关注数:0
粉丝:0
文章:0
关注标签:0
加入于:--