跳转到内容

StyleGAN2 — 把 StyleGAN 的水滴瑕疵和潜空间纠葛一起修掉

待复核

StyleGAN2 是 NVIDIA 2020 年的一篇论文,做的事情一句话:把前作 StyleGAN 留下的两个明显毛病——图像里到处冒”水滴状斑点”和潜空间方向变化不平滑——分别用『把 AdaIN 换成权重解调』和『路径长度正则』修掉,并在 FFHQ 人脸生成上把 FID(生成图与真图分布距离,越低越好)从 4.40 降到 2.84

日常类比:StyleGAN 像一台已经能拍 1024×1024 大头照的高级单反,但底片上总有几粒固定瑕疵——拍 100 张同样位置都有。StyleGAN2 没换镜头,是发现”瑕疵”是相机内部某个零件设计错了(AdaIN:按单张图自己的明暗统计做归一),换掉这个零件再加一个”防止画面之间过度跳变”的稳定器(path-length regularization),照片就干净了。

代价:训练时间比 StyleGAN 多约 1.4 倍,但模型改动不大,整体仍是 NVIDIA 那条”逐分辨率加 style 控制”的路线。

不理解 StyleGAN2,下面这些事说不清:

  • 为什么 2020 年之后所有人脸生成 demo(thispersondoesnotexist 那批)默认用的是 StyleGAN2 而不是初代 StyleGAN——水滴消失了
  • 为什么”潜空间编辑”(性别、年龄、表情滑块)在 StyleGAN2 上突然好用——path-length regularization 让潜空间方向变得线性可解释
  • 为什么扩散模型出现之前,GAN 的最高峰是 StyleGAN2/3 而不是 BigGAN——前者在窄分布(人脸、车、卧室)上的 FID 至今难超
  • 为什么 AdaIN 这个 2017 年的”风格迁移神器”在 2020 年被抛弃——它的 per-instance 归一化会引入信息泄漏

StyleGAN2 的修复可以拆成 三件事

  1. 诊断”水滴瑕疵”根因:StyleGAN 用 AdaIN(Adaptive Instance Normalization,按单张图自己的均值/方差做归一)注入风格——先减均值除标准差再乘风格 scale。论文发现生成器学会了偏门技巧:在某个特征图里做出一个超大值,让这张图的标准差被它支配,归一化后就能”偷偷传递”信号。这个超大值在最终图像上就是那粒水滴。

  2. 权重解调(weight demodulation)替换 AdaIN:不再对特征图做 per-instance 归一化,改成把”风格 scale”直接乘进卷积权重,再对权重做一次”理论上的输出方差归一”——不依赖单张图统计量。水滴消失;论文 Table 1 里仅换解调(config B)FFHQ FID 从 4.40 → 4.39,质量跃升要等后面架构与正则叠上。

  3. path-length regularization(路径长度正则):希望潜空间 W 里走相同长度的步,画面变化幅度也差不多(类比:油门踩一格,车速别忽快忽慢)。论文加一项 loss:约束生成器对 W 的局部拉伸幅度尽量恒定。效果:年龄等滑块更线性,训练更稳;叠到最终大网络(config F)FID 到 2.84。

附带的工程优化:

  • lazy regularization:正则项每 16 步算一次,几乎不掉指标,省约 1/3 计算
  • 去掉 progressive growing:改用 skip-G + residual-D,避免渐进训练的”特征定位偏好”
  • 大分辨率用 mixed precision:FP16 让 1024×1024 显存可控

AdaIN 的公式(伪代码):

def adain(x, style_scale, style_bias):
# x: [B, C, H, W]
mean = x.mean(dim=[2, 3], keepdim=True)
std = x.std(dim=[2, 3], keepdim=True)
x_norm = (x - mean) / (std + 1e-8)
return x_norm * style_scale + style_bias

问题:std单张图当前的标准差。如果 G 在某个位置故意放一个 1000 的尖峰,那 std 会被这个尖峰拉很大,归一化后整张图都被”压扁”,于是 G 就利用了”我能控制 std”这件事来跨层传递信号。论文反向追踪发现这粒尖峰在最终图像就是那个固定位置的水滴。

案例 2:weight demodulation 怎么消掉水滴

Section titled “案例 2:weight demodulation 怎么消掉水滴”

新的注入方式(伪代码):

def modulated_conv(x, weight, style_scale):
# weight: [out_c, in_c, k, k];style_scale: [B, in_c]
w = weight.unsqueeze(0) * style_scale.view(B, 1, in_c, 1, 1) # 调制
sigma = (w ** 2).sum(dim=[2, 3, 4], keepdim=True).sqrt() + 1e-8
w = w / sigma # 解调:方差来自权重,不看 x
# 跟做提示:把 B 折进 groups,勿直接 F.conv2d(x, w)
x = x.reshape(1, B * in_c, H, W)
w = w.reshape(B * out_c, in_c, k, k)
return F.conv2d(x, w, groups=B).reshape(B, out_c, H, W)

关键:sigma 不依赖 x,G 没法靠”放大单点”劫持归一化——水滴失去存在理由。

案例 3:path-length regularization 让潜空间编辑变可控

Section titled “案例 3:path-length regularization 让潜空间编辑变可控”

公式(简化):

def path_length_reg(G, w):
img = G(w)
y = torch.randn_like(img)
y = y / y.reshape(y.size(0), -1).norm(dim=1).view(-1, 1, 1, 1) # 单位长度随机方向
grad = autograd.grad((img * y).sum(), w)[0] # 图像方向 → 潜空间梯度长度
return (grad.norm() - moving_avg) ** 2

含义:让”在 W 里走 1 步”对应”图像里也走 ~固定长度”。训完做年龄滑块:沿方向走 5 步应是 5 个等距档,不会前 4 步不动后 1 步暴变。这是 InterFaceGAN、StyleCLIP 等编辑能 work 的基础。

  1. 去掉 progressive growing 不是无痛:直接换成 skip-G + residual-D 后,训练初期 FID 会比 StyleGAN 难看,要看到约 5M 张图后才追上。

  2. path-length 系数难调:太大易让画面变化塌成”处处差不多”,太小没效果;论文 lazy 每 16 步、weight≈2 是经验值,且扰动 y 要先单位化。

  3. fused modconv / groups 维度易写错:batched 权重必须 groups=B 折进卷积,漏 reshape 会 silent 错形状或显存暴涨。

  4. 复现成本高 + 分布要窄:FFHQ 1024² 约 8×V100×9 天;社区单卡 256² 也要一周以上。同一套直接训 ImageNet 1000 类 FID 很差——那是 BigGAN 地盘。

适用

  • 单一窄分布的高分辨率图像生成(人脸、汽车、卧室、马、教堂)
  • 需要可解释潜空间编辑(人脸属性滑块、风格混合)
  • 预训练 + 反演(GAN inversion)做图像编辑工具

不适用

  • 大规模多类别(ImageNet 1000 类)→ 用 BigGAN 或扩散模型
  • 文本到图像 → 没有语言条件,走 Stable Diffusion 这条线
  • 训练资源紧张 → 1024×1024 至少 8×V100 一周
  • 想要 SOTA 通用图像质量 → 2022 年起扩散模型已全面反超
  • 2017 年:Huang & Belongie 提出 AdaIN,做风格迁移神器
  • 2018 年:NVIDIA Karras 团队的 ProgressiveGAN 把 GAN 推到 1024×1024 人脸
  • 2019 年初:同团队 StyleGAN(CVPR 2019)把 AdaIN 引入 G,让”风格”能逐分辨率注入,FFHQ 惊艳,但所有样本都有水滴瑕疵
  • 2019 年 12 月:StyleGAN2 论文挂 arXiv,CVPR 2020 接收
  • 2021 年:StyleGAN3 修了”texture sticking”(图像旋转时纹理粘着),这条线告一段落
  • 2022 之后:扩散模型(DALL·E 2、Stable Diffusion)在通用生成接管,StyleGAN 系列退守”人脸 / 单类别 SOTA”位置
  1. 诊断比创新更重要:StyleGAN2 最大的贡献是诊断出”水滴是 AdaIN 的副作用”——这一步靠的是反向追踪激活值最大点,不是新算法
  2. per-instance 统计量是漏点:任何依赖单张图统计量的归一化(IN / LN 在某些位置)都给 G 一个”劫持归一化器”的机会,工程上要警惕
  3. 潜空间几何也要正则:不仅 loss 要管输出像不像真,还要管”潜空间走一步对应输出走多远”——这是后续编辑可控的前提
  4. Lazy regularization 是免费午餐:很多正则项每步算和每 16 步算结果差不多,训练流程里值得检查

StyleGAN 的水滴瑕疵根源是 AdaIN 的 per-instance 标准差被 G 偷偷利用——把它换成”理论方差归一的权重解调”瑕疵就消失;再加一项让潜空间 W 走相同长度对应图像走相同长度的路径长度正则,编辑就线性了。

  • biggan-2018 —— 同期另一条 GAN 路线(ImageNet 多类别 vs StyleGAN2 单类别窄分布)
  • stable-diffusion —— 2022 年后在通用生成上反超 GAN 的范式
  • attention —— StyleGAN3 后续引入更强的位置编码思想,与 attention 的等变性研究相关

(暂无反向链接)