GAN 的三座工程大山:评估难(指标偏差与业务错位)、算力贵(规模化训练的显存与时间账)、超参敏(一组长长的敏感旋钮)。 本节逐山测算:FID 的种子方差实验、显存换算演算、超参排查顺序表,最后给出"大山脚下"的项目级建议。
庭审收官一案。前两案(崩溃、震荡)是发作时看得见的病,本案三座大山是慢性消耗:评估说不清好坏、预算撑不起规模、调参填不满的黑洞。逐山过堂。
4.2 节已建立 IS 与 FID 的计算与读数规则,这里补审"指标之间的坑":同尺才可比之外,还有一重随机性方差——同一模型换个随机种子重算 FID,读数会漂多少?用合成实验量化:
import numpy as np rng = np.random.default_rng(21) def sqrtm_(M): w, v = np.linalg.eigh(M); return v @ np.diag(np.sqrt(w)) @ v.T def fid(m1, c1, m2, c2): cm = sqrtm_(sqrtm_(c1) @ c2 @ sqrtm_(c1)) d = m1 - m2 return float(d @ d + np.trace(c1) + np.trace(c2) - 2*np.trace(cm)) def sample(n): # 同一分布 return rng.normal(0, 1, (n, 16)) @ np.triu(rng.normal(0, .2, (16, 16))) * 0 + \ rng.normal(0, 1, (n, 16)) + np.arange(16) * 0.1 # 固定参考集, 重复采 5 次生成集, 看 FID 漂移 ref = sample(2000) for i in range(5): gen = sample(500) # 500 样本, 同分布! print(f"第{i+1}次重算: FID = {fid(ref.mean(0), np.cov(ref.T), gen.mean(0), np.cov(gen.T)):.3f}") # 输出: # 第1次重算: FID = 0.189 # 第2次重算: FID = 0.240 # 第3次重算: FID = 0.208 # 第4次重算: FID = 0.240 # 第5次重算: FID = 0.192 # 同一分布! 仅采样随机性就带来约 0.05 的漂移—— # 论文里 0.1 量级的 FID 差距在 500 样本下没有统计意义
(注:上例 drift 幅度取决于分布与维度;正式实验建议把 4.2 节的样本量守则与这里的重复测量结合起来。)结论落成两条守则:一,报告 FID 必须附样本量与重复测量的波动范围,差距小于波动范围的两模型按"打平"处理;二,指标要配业务侧验收(4.2 节人检协议),指标测的是分布距离,业务要的是可用性,两者错位的教训在 5.3 节医疗分号已经见过。
规模化 GAN(BigGAN 一系)的账本主要记在显存上。做一个量级演算,把"批大小、分辨率、显存"的关系摊开:
# 显存量级演算: 激活值占大头(参数只占零头) def activations_gb(bs, res, ch_scale=1.0): # DCGAN 风格 D 的激活总量随分辨率下降逐层减半面积、通道翻倍 layers, r = [], res ch = 64 * ch_scale while r >= 4: layers.append(bs * r * r * ch * 4) # 每层激活字节数(浮点32) r //= 2; ch *= 2 return sum(layers) / 1024**3 for bs in (32, 128, 256): print(f"批 {bs:3d}, 分辨率 128: 判别器激活约 {activations_gb(bs, 128):.1f} GB") # 输出: # 批 32, 分辨率 128: 判别器激活约 0.2 GB # 批 128, 分辨率 128: 判别器激活约 1.0 GB # 批 256, 分辨率 128: 判别器激活约 2.0 GB # 这是"最小 DCGAN 骨架 + 64 通道起步"的基线账; 真实规模化配置再叠三笔: # 通道数放大(BigGAN 级是十几倍)、生成器与双方优化器状态、更高分辨率, # 每笔都是近似线性叠加——所以 BigGAN 用 2048 的批要靠多卡分片才能成立
三条省显存的刀,代价各不同:梯度检查点(用重算换显存,时间换空间,约慢三成);混合精度(显存减半,对抗训练下要盯损失数值稳定);渐进增长(3.6 节,低分辨率阶段天然便宜)。产业上的共识顺序:先上混合精度,再考虑检查点,最后才是加卡。
GAN 的敏感旋钮清单长得吓人:双方学习率、更新比 k、动量参数、batch 大小、噪声维度、各层通道数、损失系数(L1 权重、梯度惩罚系数)、标签平滑幅度……逐个网格搜索不可行。给一张排查顺序表——按"影响面 ÷ 调试成本"排序:
| 优先级 | 旋钮 | 为什么先调 | 推荐起点 |
|---|---|---|---|
| 一 | 双方学习率与比值 | 影响所有病灶, 一刀便宜 | 0.0002, D 减半 |
| 二 | 更新比 k | 直接管平衡 | 1, 按 D 准确率调 |
| 三 | 损失形式与系数 | 治本项 | 非饱和 / WGAN-GP 系数 10 |
| 四 | batch 大小 | 影响批归一化与梯度噪声 | 64~128 |
| 五 | 噪声维度 | 过低限制容量, 过高难训 | 100~128 |
| 六 | 架构细节 | 最后才动, 成本高 | DCGAN 守则 |
⚠️ 常见坑:一次性调三四个旋钮后看到"变好了",却不知道是哪个旋钮的功劳——下次复现不出来。规矩:一次一刀、固定种子、留对照日志(4.1 节的引入纪律在超参上的重申)。
三座大山压顶时,项目的活法是主动收缩:数据够小时用 WGAN-GP 加 DCGAN 骨架的"稳态小配置"先跑通全流程(4.3 节实战);评估指标从第一天就接入(别等模型好了再建验收);预算算清再定架构(第二山的演算放在立项阶段做)。规模化是手段不是目标——很多业务问题在 64×64 到 256×256 的档位就已经解决。
FID 相差多少才算真差距? 拿波动范围当标尺:同一配置重复测量几次取波动宽度(本节实验里约 0.05,正式大规模测量也有自己的宽度),差距小于一倍波动宽度的按打平处理。论文对比同理——没给重复测量区间的 FID 表格,读的时候自动打折。
预算有限先堆算力还是先调参? 先调参。超参山的排查表(学习率、k、损失形式)几乎零成本,且配置不当的规模化只是把错误放大得更贵。算力投入在配置验证之后,这是性价比排序不是品味问题。
多卡训练有什么坑? 批归一化的统计在卡间不同步会引入噪声(梯度同步但批统计不同步);对抗训练对这类噪声尤其敏感。用同步批归一化或梯度累积规避,后者还顺便省显存。
你只有一张 16GB 卡,想训 128 分辨率、批 128 的配置(本节基线演算约 1GB 激活,但你的通道数是基线八倍)。粗算激活显存:约 8GB,加参数与优化器状态(参数量的两到三倍)勉强放得下但很紧。三个选项:混合精度(首选,显存减半)、批降到 64(次选,注意批归一化统计质量)、梯度检查点(最后,慢三成)。这道题的解法顺序就是本节第二山的结论。