神经辐射场(NeRF)通过多层感知机拟合场景的密度与颜色分布,参数量动辄几十万起步,而训练数据往往只有几十张照片,这种模型容量与数据规模的极端不对等,注定了过拟合是NeRF绕不开的问题。Nerfies这篇工作专门针对可变形场景提出了系统的解决方案,其中正则化与数据增强两大板块的思路具有普遍参考价值,不仅适用于人脸、宠物这类动态场景,对静态场景的少视角重建同样适用。本文围绕这两个方向展开,先分析NeRF过拟合的成因与症状,再逐一拆解各类正则项的设计动机和实现细节,最后给出数据增强的具体做法与组合建议。

NeRF过拟合的成因与典型症状
要解决问题,先得看懂问题。NeRF的过拟合本质上是一个欠约束的逆问题:一张训练图像的每个像素只约束了一条射线上沿途的密度与颜色分布,而这条射线内部如何分配密度,存在无数种解。当模型容量足够大时,网络会选择记住训练图像的精确外观,而不是学习符合物理规律的几何结构。
典型症状有几个:第一,训练PSNR持续攀升甚至超过40dB,但验证集PSNR停滞不前甚至下降;第二,从新视角渲染时出现漂浮的雾状伪影(floater),或者几何表面凹凸不平;第三,在可变形场景中,变形场会把训练视角的误差吸收进形变里,导致新视角下形状崩塌。观察训练曲线时,如果发现验证指标在训练早期达到峰值后开始回落,基本可以断定过拟合已经发生。
另一个容易被忽视的信号是密度场的弥散。健康的NeRF密度应该集中在物体表面附近形成薄壳,过拟合的模型则常常在相机与物体之间的空白区域也堆积了密度,这些密度在训练视角下被视角相关的颜色"伪装"掉了,换一个视角就原形毕露。
正则化:给神经辐射场加上物理先验
弹性正则化与变形场平滑约束
Nerfies针对可变形场景引入了基于单调弹性形变的正则化。核心思想是:把每个采样点的变形限制为一个单射(injective)的位移场,并用弹性势能惩罚剧烈形变。具体实现上,通过雅可比矩阵的奇异值分解约束形变的奇异值落在合理区间,避免网络用夸张的形变去"硬凑"训练图像。
def elastic_loss(jacobian):
# jacobian: 形变场对采样坐标的雅可比矩阵,形状 [N, 3, 3]
s_vals = torch.linalg.svdvals(jacobian) # 奇异值
# 限制奇异值在 [1 - sigma, 1 + sigma_pp] 区间
sigma, sigma_pp = 0.2, 0.2
penalty = torch.relu(s_vals - (1.0 + sigma_pp)) ** 2
penalty += torch.relu((1.0 - sigma) - s_vals) ** 2
return penalty.sum(dim=-1).mean()</code>这个损失项的意义在于:均匀网格经过形变后不允许局部翻转或过度拉伸,天然保证了形变的可逆性。对于静态场景,虽然不需要变形场,但同样的思想可以迁移到坐标网络的平滑性约束上,比如对MLP输入坐标加上随机扰动,惩罚网络输出的剧烈变化。
背景正则与近远平面密度约束
针对漂浮物问题,一个实用技巧是背景正则化:假设场景背景是均匀的,用一张模糊的低分辨率背景图作为监督,只在射线没有命中前景物体时激活背景损失。Sparsity正则则更直接:对每个采样点施加先验,鼓励处于相机与场景边界之间的点密度趋近于零。
def sparsity_loss(weights, z_vals, near, far):
# weights: 体渲染权重; z_vals: 采样深度
# 场景边界假设在 [near, far] 内,边界外的密度应被抑制
scene_b = 0.9 * (far - near) + near
mask = (z_vals < scene_b).float().detach()
loss = -torch.log(1.0 - weights + 1e-6) * mask
return loss.mean()这段代码的含义是:在场景包围盒之前的区域,体渲染权重越接近零越好,取负对数会让任何非零权重产生显著惩罚。这个正则项实现简单、几乎零开销,却能大幅减少新视角渲染中的雾状伪影,是性价比极高的选择。
颜色与视角相关性约束
NeRF的视角相关颜色(view-dependent color)是一把双刃剑:它能建模镜面反射,也给了网络"作弊"的空间——用颜色变化掩盖几何错误。限制的做法包括降低视角方向的编码阶数、对粗糙网络与精细网络的颜色输出施加一致性约束,或者干脆在数据侧做白化处理,降低网络依赖视角信息的动机。
数据增强:用扰动制造等效多样性
射线级别的增强策略
与图像分类不同,NeRF的训练是基于射线的,因此数据增强也应在射线层面进行。常用的做法有三种:射线丢弃(随机屏蔽部分射线)、射线颜色抖动(对采样到的RGB值加随机偏移或缩放)、以及半分辨率训练(随机用低分辨率版本的射线参与训练)。这些操作等价于向训练过程注入噪声,迫使网络学习更平滑的函数。
def color_jitter(target_rgb, brightness=0.1, contrast=0.1):
# target_rgb: 训练射线对应的真值颜色 [N, 3]
b = 1.0 + (torch.rand(1, 3) * 2 - 1) * brightness
c = 1.0 + (torch.rand(1, 3) * 2 - 1) * contrast
mean = target_rgb.mean(dim=0, keepdim=True)
return (target_rgb - mean) * c + mean * b需要注意的是,颜色抖动必须对同一条射线内的所有采样点保持一致,否则会破坏体渲染的一致性。另外抖动幅度不宜过大,0.05到0.15之间是比较安全的区间,过大会导致渲染结果整体偏色。
姿态扰动与多分辨率策略
Nerfies中使用了按进度递增的批大小与分辨率调度:训练初期用低分辨率射线快速收敛粗略结构,后期逐步提高分辨率并减小姿态噪声。姿态扰动是指对相机位姿施加微小随机旋转平移再渲染,配合出现正则可以提升对位姿误差的鲁棒性。这个策略对采用COLBA估计位姿的场景尤其有效,因为SFM得到的位姿本身就有误差,训练时见过类似的扰动,推理时反而更稳。
还有一种容易被低估的增强是随机背景色。训练时随机将图像背景替换为不同颜色(黑、白、随机色),网络就无法依赖固定的背景先验,对后续做前景抠图或背景替换也有帮助。
调参建议与组合方案
正则项不是越多越好。实践中建议按问题对症下药:漂浮物多优先加稀疏正则与背景正则;形变场崩塌优先调弹性正则的sigma参数;整体泛化差再考虑降低模型容量(减少MLP宽度或位置编码阶数),配合射线颜色抖动。各项损失的权重建议从较小的值开始(如1e-3量级),观察验证集指标再逐步调整。
一个经过验证的组合是:弹性正则加稀疏正则加颜色抖动加随机背景色,配合余弦退火学习率和指数移动平均的模型权重。在少视角(20到50张)的人头场景上,这套组合通常能比朴素NeRF在验证视角上提升2到4dB的PSNR,且新视角的几何伪影明显减少。此外,早停是最后的保险丝,务必保留一份验证集并定期渲染可视化,光看数值指标有时会漏掉几何层面的退化。
最后强调一点:数据增强与正则化解决的是"在有限数据下学得更稳",而不是"凭空创造信息"。如果视角覆盖严重不足(比如环绕一圈只拍了90度),任何正则都救不了被遮挡区域,此时应该考虑补充拍摄数据,或引入深度先验、几何监督等更强的外部约束。理解这一点,才能把这些工具用在刀刃上。