灾难性遗忘在连续学习任务中并不陌生,但在3D视觉领域,它的破坏力被空间表征的高耦合性进一步放大。当开发者在已收敛的NeRF或3D高斯场景上继续微调时,优化器只看到新任务损失,所有可训练参数都会朝着降低新损失的方向移动,旧场景的密度、颜色、几何细节随即被覆盖。对于点云分割模型,新增类别训练会重新划分特征空间,导致旧类别边界混淆。为了不让模型每次学习新数据都从头开始,工业界和学术界通常会引入弹性权重巩固与渐进式学习两类思路。

一、3D模型微调为什么特别容易发生灾难性遗忘
3D模型的高耦合性来自连续空间表达方式。以NeRF为例,场景中的每个采样点通过MLP同时预测颜色和体积密度,训练好的权重隐式编码了整个场景的几何与光照。微调时,哪怕只更新少数几层,也会改变输出函数在空间中的分布,导致旧视角渲染出现细节丢失甚至几何错乱。类似地,3D高斯泼溅场景中每个高斯包含位置、协方差、颜色和不透明度,梯度更新可能移动或删除旧高斯,造成旧场景结构永久丢失。点云分割模型共享全局特征提取器,类别增量学习时特征空间被重新划分,旧类的决策边界容易漂移。
与2D图像模型相比,3D表征通常不是规则网格,输入坐标与输出结果之间的非线性更强,参数对损失曲面的影响更复杂。下面这段无约束微调代码直接展示了遗忘过程:模型只在新数据上最小化损失,没有任何旧知识保护机制,训练结束后旧任务性能通常大幅下滑。
import torch
import torch.nn as nn
model = load_pretrained_3d_model()
optimizer = torch.optim.Adam(model.parameters(), lr=1e-4)
criterion = nn.MSELoss()
for epoch in range(50):
for batch in new_3d_loader:
inputs, targets = batch
optimizer.zero_grad()
outputs = model(inputs)
loss = criterion(outputs, targets)
loss.backward()
optimizer.step()
这段代码里,所有参数都对模型参数的旧状态没有任何约束。随着新场景或新类别数据不断输入,权重会沿着新任务的梯度方向持续移动,旧任务对应的参数配置被覆盖。若没有保存旧数据或旧约束,恢复旧场景能力几乎不可能。
二、弹性权重巩固 EWC 的原理与3D实现
弹性权重巩固的核心思想是在新任务损失上加一个参数重要度惩罚项。惩罚项根据旧任务中每个参数的敏感程度加权,避免重要参数被大幅更新。通常使用 Fisher 信息矩阵的对角线来近似参数重要性,损失函数可以写成 L_total = L_new + (λ/2) Σ_i F_i (θ_i - θ_old_i)^2。其中 F_i 是旧任务损失对第 i 个参数的二阶梯度近似,θ_old_i 是旧任务的收敛参数,λ 控制约束强度。Fisher 值越大的参数对旧任务越重要,训练时会被限制在旧值附近。
下面代码给出了在3D模型上估计 Fisher 信息和计算 EWC 损失的实现。估计 Fisher 时需要在旧数据上计算梯度平方的均值,常用少量旧样本就能得到稳定近似。
def estimate_fisher(model, old_loader):
fisher = {}
for name, param in model.named_parameters():
fisher[name] = torch.zeros_like(param)
model.eval()
for batch in old_loader:
inputs, targets = batch
model.zero_grad()
outputs = model(inputs)
loss = nn.MSELoss()(outputs, targets)
loss.backward()
for name, param in model.named_parameters():
fisher[name] += (param.grad ** 2) / len(old_loader)
return fisher
def ewc_loss(model, fisher, old_params, lam=0.5):
loss = 0.0
for name, param in model.named_parameters():
loss += (fisher[name] * (param - old_params[name]) ** 2).sum()
return lam * loss
在 NeRF 场景中应用 EWC 时,通常不需要对每个采样射线都计算 Fisher,可以只从旧场景的若干参考视角采样射线,对渲染损失执行反向传播并累计平方梯度。3D高斯泼溅模型的高斯参数数量很大,对全部参数施加 EWC 可能限制新场景重建,推荐对主干编码器或位置、协方差等关键参数分组施加不同强度的惩罚。通过调节 λ 可以在旧任务保持和新任务拟合之间取得平衡。
实际使用中,Fisher 矩阵可以每几个 epoch 重新估计一次,不必每次更新都计算,这样可以降低训练开销。同时需要保存旧模型参数 old_params,每个优化步之后累加 EWC 损失到主损失中。若 λ 过大,新任务会欠拟合;若过小,旧场景仍然会遗忘。建议从 0.1 到 10 之间进行扫描,观察旧视角 PSNR 和新视角损失的变化曲线。
三、渐进式学习如何通过结构扩展保留旧能力
渐进式学习的另一种思路是避免直接修改旧参数,而是为新任务增加新的可训练分支。经典渐进式网络为每个任务添加独立的侧枝,并将新侧枝特征与旧特征拼接。对于3D模型,可以冻结旧 NeRF 的 MLP 层,新增一个残差块或颜色头,专门学习新场景的差异;点云分割模型可以保留旧类别头,新增新类别头,共享编码器保持不变或仅施加轻微 EWC。
下面代码演示了一个渐进式3D模型的基本结构:旧分支被冻结,新分支负责学习新任务增量,输出为两个分支之和。
class Progressive3DModel(nn.Module):
def __init__(self, old_model, new_dim):
super().__init__()
self.old_branch = old_model
for p in self.old_branch.parameters():
p.requires_grad = False
self.new_branch = nn.Sequential(
nn.Linear(new_dim, 128),
nn.ReLU(),
nn.Linear(128, new_dim)
)
def forward(self, x):
old_feat = self.old_branch(x)
new_feat = self.new_branch(x)
return old_feat + new_feat
这种结构扩展方式可以大幅减少对旧参数的破坏,但新分支的输出能力有限,复杂的新场景可能需要更多层或额外输入条件。对于3D高斯表示,可以在不修改旧高斯的前提下,为新场景添加一批新的高斯,训练时只更新新增部分;这类似于渐进式空间分配,能很好地保留旧场景结构。
数据回放是另一类渐进式学习手段。它不改变网络结构,而是保留旧任务的代表性样本,与新数据混合训练。3D场景中可以保存旧任务的稀疏参考视图或关键帧,训练时恢复旧场景渲染监督;点云任务可以保存部分旧类别点云。生成式回放则使用3D扩散模型生成旧场景伪样本,在存储空间受限时更有优势。数据回放与渐进式结构扩展经常结合使用,前者解决旧数据丢失问题,后者减少新旧任务之间的参数竞争。
四、结合 EWC 与渐进式学习的工程实践
两种方法可以互补。渐进式结构扩展减少共享参数的冲突,EWC则保护仍然共享的部分不受破坏。例如在3D分割任务中,可以冻结旧类别头,给共享编码器施加 EWC 惩罚,并新增一个独立的新类别头训练。NeRF 场景中,主干 MLP 保留旧场景能力并添加 EWC 约束,新场景通过附加特征网格或残差分支学习。组合损失可以写成下面这种形式。
total_loss = new_task_loss + ewc_penalty optimizer.zero_grad() total_loss.backward() optimizer.step()
工程部署时,需要重点关注超参数和评估指标。下表对比了不同策略在3D模型持续学习中的典型表现。
| 方法 | 旧任务保持 | 新任务学习 | 额外成本 |
|---|---|---|---|
| 直接微调 | 差 | 好 | 低 |
| 仅EWC | 较好 | 中等 | Fisher计算 |
| 仅渐进式 | 好 | 好 | 参数与存储 |
| EWC + 渐进式 | 最好 | 好 | 中等 |
在3D任务中,评估旧任务保持率常用旧视角的 PSNR 或旧类别 mIoU,新任务性能则用新视角渲染损失或新类别分割精度。建议在每次微调后同时记录这两组指标,并计算遗忘率。Fisher 估计频率、λ 值和新增分支的宽度都可以通过网格搜索在验证集上确定。学习率预热也有助于前几个 epoch 不破坏旧参数配置,之后恢复较大学习率加快新任务收敛。
灾难性遗忘不是不可解的问题,而是持续学习场景中必须正视的优化约束。通过限制重要参数的更新幅度,并为新任务提供独立参数空间或旧数据监督,3D模型可以在不断扩展能力的同时保持旧场景和旧类别的稳定表现。实际项目中可以先用 EWC 快速验证旧任务保持效果,再逐步引入渐进式分支和数据回放,形成一套适合自身3D管线的持续学习方案。