生成模型伪影实战解决:我彻底放弃转置卷积,用双线性插值根治棋盘格噪声

3 阅读5分钟

生成模型伪影实战解决:我彻底放弃转置卷积,用双线性插值根治棋盘格噪声

在我做时空生成模型的前期训练中,有一个问题困扰了我特别久:

模型整体收敛没问题、损失也在稳步下降,但是生成出来的结果一直有网格纹路、棋盘格伪影、细碎雪花噪声,画面割裂、不细腻、看着非常假。

我最开始以为是我的网络深度不够、训练迭代不够、学习率没调好,折腾了很久调参,效果几乎没有改善。

直到我自己逐模块排查、替换上采样结构,才终于定位根源:问题根本不在训练超参,而是转置卷积天生的缺陷。

这篇依旧只记录我自己完整的踩坑、排错、替换、优化全过程,全是我亲手试出来的经验,不讲空话、不套模板。

一、我最开始的搭建习惯:生成器上采样,直接用转置卷积

我最刚开始搭建生成模型的上采样模块,完全是跟着常规开源写法走的。

生成器需要放大特征图、恢复分辨率,我当时图省事、照着传统GAN结构,全部直接使用 ConvTranspose2d 转置卷积做上采样。

几乎所有入门生成模型教程都是这么写的,我自然以为这是标准、最优的方案。

训练初期我就发现不对劲:

  • 生成图有明显规律网格,一格一格的棋盘纹路
  • 画面有细碎雪花噪点,整体不干净
  • 局部细节割裂、断层,过渡不自然
  • 整体质感很生硬,完全达不到平滑真实的效果

我当时完全没怀疑上采样层,一直在损失、学习率、迭代次数、权重初始化上面死磕,白白浪费了很多调参时间。

二、我排查后才明白:转置卷积本身就会产生棋盘格伪影

我后来单独拆开每一层输出、可视化特征图,终于确认问题根源。

转置卷积的运算机制,有一个无法规避的天生缺陷: 不均匀重叠采样。

尤其是在步长为2、卷积核为偶数的配置下,像素重叠不均匀,模型训练后会规律性生成网格状棋盘伪影。

关键点是: 这不是我训练的问题,是结构本身的问题,再怎么调参都根除不了。

只要生成器堆叠多层转置卷积上采样,伪影会逐层叠加,越深层越明显。 我之前训练出来的割裂感、格子纹、细碎噪点,全部源头在这里。

想通这点之后,我不再盲目调参,直接开始替换结构。

三、我的最终根治方案:放弃转置卷积,改用插值+普通卷积

为了彻底解决伪影,我直接换掉了生成器所有的转置卷积上采样模块。

现在我固定使用一套非常稳、零棋盘格、特别适合时空生成的组合方案: 双线性插值上采样 + 普通卷积 Conv2d

我的完整改造逻辑很简单:

1. 用双线性插值完成分辨率放大,插值自带平滑过渡,不会产生网格重叠问题; 2. 紧跟一层普通二维卷积,用来重新提取融合特征、修正插值带来的柔和模糊; 3. 全程没有转置卷积,从根源杜绝不均匀采样伪影。

我替换完结构第一时间跑训练,效果是肉眼级提升:

  • 之前顽固的棋盘格网格纹路直接消失
  • 细碎雪花噪声大幅减少
  • 画面过渡自然、平滑连贯
  • 整体细腻度、真实感直接上了一个档次

那一刻我才真正意识到:很多生成效果不好,不是模型学不会,是模块选错了。

四、顺带解决我前期疑惑:训练初期雪花噪声的真正原因

除了棋盘格,我前期还经常遇到训练初期雪花噪点很重的问题。

这次排查模块的过程中,我也终于理清了我自己的问题来源:

1. 转置卷积自带不稳定采样,容易生成高频噪点 2. 前期归一化正反参数偶尔不对齐 3. 学习率前期偏大,模型对高频噪声过度敏感

之前我一直以为是单一原因,现在彻底串起来了。 换掉转置卷积之后,我连前期噪点问题一并改善了,训练初态干净稳定很多。

五、我个人实战总结(全部是自己试错后的真实感悟)

这一轮伪影排查和结构替换,给我的触动特别大:

1. 生成模型出现规律网格、棋盘格,优先查上采样,不要盲目调参; 2. 转置卷积看似经典,实际在高精度生成任务里非常不友好,缺陷很大; 3. 插值+普通卷积虽然看着朴素,但是更稳、更干净、更适合时空连续数据; 4. 有时候效果瓶颈不在网络深度、不在损失函数,在基础模块选型; 5. 做实验一定要逐层排查,不要被“开源常规写法”绑架思维。

六、最后小结

这是我做时空生成模型踩的非常典型的“结构性大坑”。

之前一直跟风用转置卷积,以为是标准方案,结果一直被伪影拖累效果。 自己一步步替换、对比、复现之后,才彻底根治问题。

现在我的生成器上采样,一律优先插值+卷积组合,不再无脑使用转置卷积。

做算法科研真的是这样: 很多经典结构不一定最优,别人的默认写法不一定适合自己的任务。 只有自己亲自拆模块、做对比、跑实验,才能真正避开这些隐形坑。

 

本文正在参加「金石计划」