图像去噪这个方向这两年最让人头疼的不是网络结构而是“噪声本身到底是什么”。以前我们默认噪声是已知强度的高斯白噪声照着经典论文把网络搭起来在合成数据上跑得飞起一放到真实照片上就露馅——去不干净、边缘发糊、伪影频出。直到我看到VDNVariational Denoising Network变分去噪网络这篇论文才意识到把去噪问题直接升级成“盲去噪”才是正路。它最吸引我的点是不再把噪声方差当作需要预知的固定参数而是把它放进网络里一起推断靠变分推断同时解决“噪声估计”和“图像重建”。整篇论文像是一个优雅的概率模型外壳里面装的却是一个非常实用的双分支网络。这篇文章适合谁如果你正在做图像去噪、真实噪声去除或者对“盲去噪”“噪声水平估计”“置信度图估计”这几个方向感兴趣VDN值得你逐行读一遍。整篇论文的核心可以这样理解我们不直接学习带噪图到干净图的映射而是学习一个“带噪图到干净图噪声方差图”的联合概率模型训练时用变分下界把这两件事绑定在一起。这样一来训练好的网络遇到任何未知噪声水平的输入都能自己先估计出每像素的噪声强度再引导去噪这就是它叫“变分去噪网络”的原因。1. 变分去噪网络要解决的三个痛点1.1 真实图片噪声为什么不能用固定高斯噪声近似经典的CNN去噪工作比如DnCNN走的是残差学习路线输入带噪图输出预测的噪声图用干净图减掉。默认前提是噪声水平已知或者至少固定。训练时用固定的噪声标准差生成合成样本测试时输入的真实照片如果噪声水平不在训练范围内效果立刻打折扣。这就像你只练过游泳姿势却被扔进湍急的河里——那完全是另一个世界。真实噪声根本不是均匀的高斯分布。我看过某个传感器在不同ISO下抓拍的照片放大到像素级别你会发现暗部区域噪声明显更大亮部相对干净边缘过渡区域还会出现顺着梯度方向的条纹噪声。也就是说噪声方差实际上是空间变化的每块区域都有自己的强度。VDN正是抓住了这一点它把噪声方差建模成一张和原图分辨率相同的“方差图”每个像素都有自己的噪声强度而不是全图共享一个标量。这个设定直接推动了后面的盲去噪能力。1.2 已有盲去噪方案的重重限制在VDN之前怎么处理盲去噪主流做法是“估计-去噪”两阶段代表是CBDNet。这类方法先训练一个噪声水平估计子网络输出噪声方差的标量或者方差图然后把这个估计结果作为附加输入送进后面的去噪网络。听起来很合理但仔细看有个硬伤噪声估计子网络和去噪子网络通常分开训练或者只有单向的传递关系。如果估计错了去噪网络只能用错参数硬着头皮生成结果没有“两者互相修正”的机制。另一个问题是监督信号的不平衡。去噪网络输出干净图可以用和真实干净图的L1/L2损失来监督训练信号非常直接。但噪声估计网络没有同样直接的监督——你很难准备一张“带噪图对应的真实噪声方差图”。常见的做法是训练时用已知合成噪声的标准差做弱监督但真实图像哪来的这种标注。于是估计网络在真实数据上就成了“盲猜”它的误差会被下游放大。这就是“估计误差传导”的问题。1.3 VDN的破局思路把估计和重建放进同一个概率框架VDN换了个思路。它把带噪图y、干净图x、噪声方差图ν三者写进一个联合概率模型利用变分推断来同时处理。简单说它不再显式地分别训练“估计模块”和“去噪模块”而是设计一个双分支网络一条分支负责输出估计的噪声方差另一条分支负责输出去噪结果但两者的目标是同一个变分下界。这相当于把“估计噪声”和“去除噪声”两个任务打包进同一个损失函数互相反馈而不是串联流水线。尤其是网络在训练时不需要真实噪声方差图它只依赖带噪图y、干净图x以及推导出来的变分下界。这非常关键因为真实噪声方差图几乎是无法标注的VDN绕开了这个坑。它相当于告诉网络“你猜出来的方差分布要既能解释带噪图的产生过程又要能指导干净图的重建。”这样估计分支和重建分支被绑在一起谁也不能跑偏。2. VDN的核心设计把噪声方差当成隐变量2.1 从观察模型到变分下界VDN的起点是一个很朴素的观察模型带噪图y等于干净图x加上噪声n噪声服从零均值的高斯分布但方差σ²(x)是逐像素变化的记作y x n, n ~ N(0, diag(ν))这里的ν就是一张噪声方差图。注意这个写法已经做了重要的知识压缩噪声的方差是x的函数也好是局部特征也好反正我们用ν代表它。变分推断的核心思想是不需要精确计算后验分布p(x, ν|y)而是用一个近似分布q去逼近它。VDN把q设计成带噪图y作为输入的函数由一个神经网络直接输出。展开推导后目标函数变成两项之和。第一项是重建误差即q预测的干净图和真实干净图之间的L2距离第二项是KL散度用来约束预测的噪声方差分布不要偏离先验太多。有人觉得这个KL项只是正则化但实际复现时你会发现它对稳定训练非常关键。没有KL项噪声估计分支就会出现极端值因为重建损失倾向于让“方差”和“噪声残差”共同承担解释容易出现局部最优解。2.2 双分支网络一条去噪一条猜方差VDN的网络结构看着像U-Net但输出端是两条分支。主干是标准的编码器-解码器结构提取多尺度特征后在解码器最后阶段分出两个头去噪分支输出干净图估计通道数等于输入通道数灰度图就是1通道RGB就是3通道。方差分支输出噪声方差图灰度图对应1通道RGB对应3通道数值上必须严格大于零。这两个分支不是完全独立的它们在解码器内部共享了大量特征。而且有个细节容易被忽略去噪分支最终要利用方差分支的输出。VDN不是简单地输出两个结果就完了它将方差分支的结果通过某种调制方式注入到去噪分支中让去噪分支能用上“当前像素噪声多大”的信息。这种共享和调制的设计比两阶段流水线合理得多。2.3 用重参数化把期望损失变成可计算形式如果只是Maximize后验概率训练会卡在期望项没有解析解。变分自编码器领域的标准答案——重参数化技巧在这里同样适用。VDN把噪声图的采样过程写成ε ~ N(0, I), n ν^0.5 ⊙ ε也就是把随机噪声拆分成标准正态随机变量ε乘以预测方差图的逐元素平方根。这样一来对噪声的期望就可以用采样近似而梯度可以通过ε回传到方差分支。这个技巧在你复现时几乎必须使用否则方差分支的梯度会断掉。有读者可能会问为什么非得引入随机性因为VDN本身是一个生成模型。干净图像x的估计虽然是确定性的但以ν为条件的后验本质上是一个分布。随机采样让网络在训练时不再只学习“唯一正确”的干净图而是学习“在给定噪声估计下最可能的干净图”变分框架让这两条分支形成一个自洽的整体。3. 训练损失与网络结构的落地细节3.1 从ELBO到可实现的Loss把变分下界展开我们得到训练时实际使用的损失函数大致可以分成三块重建块去噪分支输出的干净图与真实干净图之间的L2距离也就是MSE损失。这一块提供最核心的监督信号让去噪分支学会把带噪图变成干净图。KL散度块约束方差分支输出的ν接近先验分布。先验一般取标准高斯或某个固定方差的高斯KL项会让ν的分布不要太极端起到正则作用。方差的自监督块在推导过程中会出现一个“噪声对数似然”项它实质上告诉方差分支你估计的ν要能解释带噪图y和预测干净图x之间的残差。这是整个模型真正做到“盲估计”的关键。如果你去看官方实现会发现代码首页的三个损失项并不难写。但难的是权重分配。重建损失主导梯度方向KL和似然项权重如果太大方差分支会变成“什么都学不到”太小方差图又会出现退化。我的经验是先用小学习率预热主干方差分支用单独的权重更新效果会好很多。3.2 训练数据怎么造从合成到真实噪声VDN训练使用的数据分两种。一是完全合成数据从干净的Dataset里取图加上零均值高斯噪声但关键在于——合成的时候每个像素的方差要不同。论文里使用了空间变化的高斯噪声让网络真正适应“每像素一个噪声强度”。二是用真实噪声数据做微调比如用两部手机在暗光下拍摄同一场景得到的短曝光/长曝光带噪图对虽然这个数据对不完全准确但从真实噪声特性里学到的方差图明显更贴近实际。这里要特别提醒如果你只用固定方差的高斯噪声训练VDN方差分支几乎没有用武之地模型会退化成一个普通去噪网络。想要体现VDN的优势数据里一定要有空间变化的噪声。论文里构造了一个噪声方差与图像内容相关的生成方式暗部区域方差大亮部区域方差小这样学出来的方差分支才真正学会“内容感知的噪声估计”。3.3 损失函数表达细节与“让方差去解释噪声”的直觉我读论文时最拍案叫绝的是它如何处理“残差归因”。一个像素点上的(带噪图-干净图)误差既可能来自噪声也可能来自模型没有拟合干净图。普通训练会把两者混在一起导致去噪结果过平滑。VDN通过变分推导把噪声部分的解释权交给了ν让重建分支专心解释“真实场景”。两个分支各干各的又互相制约从而尽量避免“为了降低MSE而拼命抹平边缘”的问题。这种分工在实际运行中表现为边缘区域虽然方差可能估计得大一些但去噪分支会利用特征做保边处理而不是狠命地平滑平坦区域方差估计得小一些去噪分支可以放心增大平滑力度。最终的主观效果是真实照片能保住纹理细节同时没有残留噪声斑点。4. 实验结果的解读视角和论文里的关键结论4.1 合成数据上的量化优势论文在常见的合成高斯噪声数据集上跑了一组对比实验和BM3D、DnCNN、CBDNet等作比较。关于PSNR/SSIMVDN不是全面碾压但有几个稳定的结论值得记住。第一个是当测试噪声强度与训练时最常用的范围接近且是空间一致噪声时DnCNN级别的专用去噪器仍然很强VDN的量化指标不会差太多。真正拉开差距的是在测试时使用空间变化噪声这时VDN的优势明显因为它能估计出逐像素方差相当于每一步去噪都用了“局部最优强度”。另一个结论是如果把测试噪声方差调得很大比如训练时没见过的强度传统方法通常会崩VDN因为方差分支能自适应调整PSNR下降的曲线要平滑得多。这说明它的盲估计能力不是泛泛而谈而是实实在在提升了模型的跨噪声强度泛化性能。我自己复现时也发现用同一个VDN权重去处理σ15和σ75的噪声不需要重新训练也能保持可接受的效果。4.2 真实照片上的方差图可视化论文最让我信服的是它在真实噪声照片上输出了噪声方差图的可视化。不看这个图你很难相信“空间变化噪声”假设有多正确。那些方差图并不是一张均匀的灰色图而是在暗部区域明显更亮、边缘和纹理附近有细节起伏这和图像传感器增益噪声的物理特性完全对得上。这说明VDN没有走捷径它确实学到了噪声的空间分布。这个可视化还有一个额外用途噪声方差图可以作为“置信度图”供下游任务使用。比如做RAW域去噪、HDR合成或深度估计时你本来就需要知道哪些像素点更可靠。VDN免费提供了一个每像素的噪声强度估计这对很多系统来说反而是比PSNR提升更值钱的副产品。4.3 消融实验透露出来的设计智慧论文的消融实验部分建议大家重点看三个设计点的取舍。去掉KL散度项方差估计会变得极不稳定训练后期出现噪声方差图剧烈震荡整体PSNR下降约0.3~0.5dB。这说明了正则约束的重要性。去掉方差分支对去噪分支的调制相当于把双分支变成两个独立任务去噪分支不再感知噪声强度真实噪声场景下的表现回落明显证明“方差信息引导去噪”这个设计不是装饰。用固定噪声方差替代空间变化噪声训练模型虽然也能收敛但输出方差图基本退化为常数失去盲去噪能力。这直接验证了训练数据设计对模型能力的决定作用。5. 复现VDN时的实践要点与避坑清单5.1 搭建网络时最容易踩的通道坑VDN的双分支设计听起来直观但自己在代码里写时很容易搞错通道数。灰度图输入是1通道主干编码器的第一层输出是32或64通道解码器最终恢复到输入尺寸时需要分出两个头去噪头的输出通道是1方差头的输出通道也是1。如果你把方差头的输出通道误写成3然后在RGB图上直接当作1通道处理模型会照常训练但方差图的语义就错了。RGB输入时更重要方差图应该是三通道逐像素方差还是单通道共享方差按论文设定三通道各自估计更好理论上R/G/B通道的噪声强度不完全相同。但实践下来因为三个通道高度相关用单通道方差换算成三通道也可以训练还更快。如果你的目标只是复现论文指标第一版可以先用RGB三通道方差以保险为主。5.2 方差分支的活化函数和数值保护方差必须严格大于0这是从概率模型里带出来的硬约束。输出层常选择Softplus或Sigmoid乘上一个大尺度。我自己复现时偏好Softplus因为它导数平滑没有Sigmoid那类饱和区训练初期方差不会卡死在0附近。还需要在KL散度计算时对方差取log时加epsilon一般取1e-6到1e-8否则log(0)会让loss直接变成NaN。这里说一个我踩过的坑方差图是模型自己估计的不代表你可以在反向传播时随意停掉它的梯度。刚开始我觉得方差头训练不稳定就在KL散度那一支用了detach()结果方差分支完全不更新了去噪分支虽然照样收敛但真实噪声测试时敏感度极差。原因是重参数化路径本来就靠噪声图采样传播梯度你再detach就把这条路切断了。5.3 训练策略的细节学习率、batch size与评估时机VDN的收敛速度并不算快我测试时用2块显卡训练512×512的patchbatch size设成4大约需要跑140个epoch才能看到稳定的效果。建议不要一开始就追求大batch size因为方差分支的稳定性对batch size非常敏感batch太小方差估计的统计噪声会干扰KL散度导致loss曲线毛刺很多。梯度累积是个折中方案但要注意BN层的统计量更新会受影响尽量使用GroupNorm或InstanceNorm。学习率方面我给两个分支设了不同的初始学习率。主干和各分支共享主干权重所以主干的学习率用1e-4方差分支额外乘一个0.5的系数因为方差分支的梯度方差比较大更大的学习率容易让方差图出现椒盐噪声般的离群值。等主干loss稳定后再把方差分支的学习率调回相同水平这样训练过程更稳。5.4 推理时的“方差图”要不要后处理训练好的VDN推理时同时输出干净图和方差图。这里有个很多人没注意的点实际应用时可以直接把方差图的低通滤波版本作为后处理置信度。因为白噪声方差图通常局部波动较大直接用于下游任务不稳定。我通常对方差图做一次均值模糊或引导滤波再将其用于加权融合或其他任务。但请注意这不应该作用于去噪分支的输出那是网络自己特征调制的你修改它反而会破坏去噪结果。5.5 官方代码之外从Torch到你自己的框架迁移很多复现者习惯把官方代码搬到自己项目里。迁移时最容易遗漏的是“训练噪声方差图”的采样过程。官方网站里的噪声图生成方法通常先随机生成一个低频的方差场再乘以均匀噪声做完缩放。迁移时一定要复制这个过程因为它决定了训练数据中空间变化噪声的分布。另外在训练过程中要对噪声水平范围做一定控制。论文里的方差图取值范围大概在[0, 50]这个量级以像素值0~255计算。如果你设置的范围过大网络会把大量精力放在估计极端噪声上过小则体现不出盲估计能力。我的建议是先用窄范围训练主力模型再在真实数据上微调时扩大范围。6. 我眼里的VDN适用场景和后续演进6.1 什么时候首选VDN什么时候不选如果你的任务是在已知噪声水平的合成数据集上追求最高PSNRVDN不是最优选择专一训练的DnCNN或Restormer会更强。但如果你面对的是真实拍摄的无序噪声不知道噪声强弱甚至希望在同一个网络里处理多种设备、多档ISOVDN的优势就体现出来了它不需要预先知道噪声强度还可以顺带输出方差图供系统使用。我实际在一个夜间视频降噪项目里用过VDN的思想。视频帧的噪声随时变固定方差模型完全扛不住我借用了VDN的“逐帧方差估计”思路把方差分支的估计结果作为时序滤波的权重效果比直接套固定阈值好非常多。这说明VDN的模型价值超出了图像去噪本身它可以嵌入任何需要置信度信息的视觉系统。6.2 VDN和Noise2Noise、AP-BSN等无监督流派的关系无监督去噪方法里Noise2Noise比较出名核心是把配对关系从“干净-带噪”变成“带噪-带噪”。VDN表面上看是有监督方法需要干净图但它的变分框架和无监督方法关系很近。如果你只想解决真实噪声问题却实在搞不到干净参考图可以考虑VDN思路的无监督变体——把重建目标从“重建干净图”改成“重建另一张同噪声分布的带噪图”方差分支同样可以工作。近两年有些工作在此基础上把VDN的方差先验换成可学习的空间先验或者引入扩散模型的迭代去噪思路本质上都是把“估计噪声场”和“重建图像”解耦再耦合。VDN算是在这个交叉点上比较早且完整的尝试。6.3 改进方向非高斯噪声、结构化噪声与多任务扩展VDN最大的局限在于高斯噪声假设。真实传感器噪声中的坏点、条纹、量化噪声都不是高斯噪声。我自己尝试把VDN中的高斯似然换成拉普拉斯分布效果有改善但KL散度推导变得复杂。另一个改进方向是把方差图推广为协方差矩阵从而处理通道间噪声相关性这会带来计算量暴涨但对RAW域去噪很有意义。还有一个很实用的扩展把VDN的方差分支单独拿出来作为图像质量评估的预测器。它输出的空间噪声方差可以聚合出一张图片的“噪度分”这个东西在无参考图像质量评估里很好用我的一个实验就是基于它做的失真类型判别准确率还不错。所以就算你不需要去噪VDN的变分结构也值得研究。6.4 复现VDN的一个心态建议我第一次跑VDN时没有细读变分推导直接用三个loss叠加结果效果和普通U-Net差不多。后来把推导逐行顺了一遍才明白KL、重建、噪声似然三者谁是主角、谁是配角。建议准备复现的人先花两个小时把ELBO从公式推导到代码接口再动手写网络。过程虽然枯燥但会让你知道哪一步该加梯度停止、哪一步该指数运算。这个准备时间绝对值得。我还有一个很实用的测试方法训练到一半时喂一张完全干净的图进网络此时理想的方差图输出应该接近于零去噪输出应该几乎等于输入。如果方差图输出有明显纹理或数值偏大说明你的方差分支没有正确学到“什么是有噪声”这时需要检查训练数据的噪声采样范围多半是因为合成噪声最小值太大了。最后再分享一个实操细节在把VDN应用到真实场景时我最喜欢用的一个技巧是先让模型输出方差图再利用方差图生成一张“带噪程度引导掩膜”把去噪分支的结果和原始输入按像素加权融合。在方差图估计值很高的区域完全相信去噪结果在方差图估计值很低的区域保留原始图像细节。这样能在主观画质上比直接全图使用去噪结果更自然尤其是面对近乎无噪声的输入时避免无谓的模糊。这个技巧并不是论文内容完全来自我多次真实测试的经验但它能解决VDN实际落地中最常见的一个抱怨明明已经去噪了为什么细节反而丢了答案往往不是去噪能力不足而是你忽略了“这块区域本来噪声就不大”这个事实。VDN的方差图恰好给了你一把尺子量完再决定动刀轻重效果自然就上来了。如果你也是被真实噪声折磨过的人一定要把VDN的“变分估计”思路吃透。哪怕最终不用它的网络结构这种“把未知量建模成隐变量再用推断求解”的思维方式也会在你会遇到的很多视觉问题里帮上大忙。