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 优雅的地方。
二、训练不稳定与模式崩溃
理想很丰满,现实三大坑:
-
模式崩溃(Mode Collapse):G 发现某几个样本能稳定骗过 D,于是只生成这几类,丢失多样性。比如人脸生成全是同一张脸。
-
梯度消失 :当 D 太强,真假判别接近完美,
log(1 - D(G(z)))的梯度趋于 0,G 学不动。 -
超参敏感 + 振荡: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 散度,核心改动两点:
-
判别器改为"批评家"(Critic),去掉最后的 sigmoid,输出打分而非概率。
-
对 Critic 参数做** Lipschitz 约束**(原始 WGAN 用权重截断,后续 WGAN-GP 用梯度惩罚,更稳)。
好处:哪怕真假分布不重叠,梯度也不会消失,训练曲线更平滑、可监控。
python
# 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 在卧室、人脸等数据集上稳定出图:
python
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,不为追新,而为理解"让两个网络互相教对方变强"这一深刻范式。
参考资料
-
Goodfellow, I., et al. (2014). Generative Adversarial Networks.
-
Arjovsky, M., et al. (2017). Wasserstein GAN (WGAN).
-
Gulrajani, I., et al. (2017). Improved Training of WGAN (WGAN-GP).
-
Karras, T., et al. (2019). A Style-Based Generator Architecture for GANs (StyleGAN).
往期回顾
关注作者,继续《深度学习工程化》专栏:下一篇讲"模型训好了怎么塞进手机"------量化、剪枝与 ONNX 部署。
📚 本篇出自专栏《深学之路:从感知机到智能体》 ------ 从感知机到大模型智能体的完整深度学习连载(基础+工程化 +扩散模型 / RAG / Agent 等)。每篇附可运行代码与原创实验,收藏专栏不迷路。