pytorch中gan最小可运行结构包含生成器(输入噪声→图像,末层tanh)、判别器(输入图像→真假概率,末层不加sigmoid)、两个adam优化器、bcewithlogitsloss损失函数,数据需归一化至[-1,1]并统一送入gpu,噪声每轮重采样,训练时交替更新且判别器先于生成器。

PyTorch里GAN的最小可运行结构长什么样
GAN在PyTorch中没有现成的torch.nn.GAN模块,必须手动组合Generator和Discriminator两个子网络,并分别定义各自的损失与优化逻辑。最简结构就是:一个生成器(输入噪声→输出图像),一个判别器(输入图像→输出真假概率),外加两套optim.Adam优化器和nn.BCELoss或nn.BCEWithLogitsLoss——后者更稳定,推荐直接用。
常见错误是把生成器和判别器共用同一个优化器,或者误用nn.CrossEntropyLoss(它要求整数标签,而GAN输出的是标量概率)。
-
Generator最后一层通常用nn.Tanh()(输出范围[-1,1]),配合transforms.Normalize((0.5,), (0.5,))归一化输入 -
Discriminator最后一层**不要**加sigmoid——用nn.BCEWithLogitsLoss自动处理logits更数值稳定 - 训练时先固定
Discriminator更新一次Generator,再固定Generator更新一次Discriminator,顺序不能反
为什么生成器loss突然变成nan或爆炸
这几乎总是梯度问题:判别器太强导致生成器收到的梯度方向剧烈震荡,尤其当判别器已接近“完美分类”(loss≈0)时,log(1 - D(G(z)))项会趋向log(0)引发数值溢出。
解决方式不是调小学习率,而是换损失形式:
- 用
nn.BCEWithLogitsLoss替代手写log(1 - D_fake),它内部做了log-sum-exp稳定化 - 判别器loss用真实样本标签
ones_like、假样本标签zeros_like;生成器loss则统一用ones_like(即“骗过判别器”) - 加梯度裁剪:
torch.nn.utils.clip_grad_norm_(netG.parameters(), max_norm=1.0)
如何让MNIST上GAN快速出图(不跑CIFAR-10)
MNIST维度低、结构简单,适合验证GAN流程是否走通。关键不是堆深度,而是对齐数据流和设备:
- 加载数据必须用
transforms.Normalize((0.5,), (0.5,)),否则生成器输出全黑或全白 - 所有tensor要统一进GPU:
real_imgs = real_imgs.to(device),漏掉任何一处都会报Expected all tensors to be on the same device - 噪声
z每次迭代必须重新采样:z = torch.randn(batch_size, nz, 1, 1).to(device),复用旧z会导致生成结果卡死 - 生成器建议用转置卷积
nn.ConvTranspose2d,通道数从100→256→128→1,kernel_size=4,stride=2,padding=1
保存和复现生成结果时容易忽略什么
训练中途保存模型只存state_dict()不够,必须同时保存随机种子和噪声固定值。否则即使load了相同权重,每次torch.randn出来的图也完全不同。
调试阶段务必做两件事:
- 训练前固定:
torch.manual_seed(42); np.random.seed(42) - 生成样本时用固定噪声:
fixed_noise = torch.randn(64, nz, 1, 1).to(device),后续每轮都用它,才能观察生成质量是否提升 - 保存图片别用
plt.imshow直接显示——它默认插值,改用torchvision.utils.save_image保证像素级准确
GAN收敛慢、模式崩塌常见,但第一步能用MNIST跑通并稳定生成数字,就说明骨架没搭错。后面换数据集,只是调整网络宽度和归一化参数的事。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











