2. 物理残差项梯度消失的排查
问题特征:残差损失在降,解却不收敛
在 PINN 训练中,物理残差损失 L_r 持续下降,但预测解与参考解的相对 L2 误差停滞甚至上升,这通常不是优化器“没在学”,而是残差项对网络参数的梯度在传播路径上被削弱。残差损失下降可能来自少数配点被拟合、或残差被网络输出层的偏置吸收,而真正决定解精度的内部层几乎没有收到有效梯度。
排查的核心是两条证据链:一是逐层梯度统计,看残差损失对每一层权重的梯度范数是否随层数迅速衰减;二是残差对输入的敏感度,即 ∂r/∂x 与 ∂r/∂t 的分布,若敏感度接近零,说明残差曲面在空间上过于平坦,网络没有学到能改变残差的特征。
逐层梯度统计:定位“断点”层
在 PyTorch 中,残差损失对每层权重的梯度可以通过 torch.autograd.grad 单独获取,避免被总损失中的其他项掩盖。下面给出一个可直接嵌入训练循环的诊断函数,它在每个记录周期计算 L_r 对各层参数的梯度范数,并输出归一化衰减比。
import torch
def residual_grad_stats(model, residual_loss_fn, collocation_pts, record=False):
"""
model: PINN 网络(nn.Module)
residual_loss_fn: 输入配点,返回物理残差损失 L_r
collocation_pts: 配点张量,形状 [N, 2],列为 (x, t)
"""
params = [p for p in model.parameters() if p.requires_grad]
L_r = residual_loss_fn(collocation_pts)
grads = torch.autograd.grad(L_r, params, retain_graph=True, allow_unused=True)
stats = []
for name, p, g in zip([n for n, _ in model.named_parameters() if _.requires_grad], params, grads):
if g is None:
stats.append((name, 0.0))
else:
stats.append((name, g.norm().item()))
if record:
for name, norm in stats:
print(f"{name:30s} ‖∂L_r/∂W‖ = {norm:.3e}")
return stats
# 使用示例:每 200 步记录一次
# stats = residual_grad_stats(model, residual_loss_fn, collocation_pts, record=True)
# 关注相邻层梯度范数比值,若连续两层比值 < 0.1,则该处为疑似断点
判读要点:若输入层梯度范数在 1e-2 量级,而输出层附近降到 1e-4 以下,且相邻层比值持续小于 0.1,说明反向传播在该段被压缩。常见原因包括激活函数饱和(如 tanh 在大输入下导数趋零)、输入未归一化导致高阶导数项量级失衡、以及残差项本身对网络输出的一阶依赖过弱。
残差敏感度分析:判断残差曲面是否“平坦”
梯度消失的另一种表现是残差对输入几乎不敏感。对配点集计算 ∂r/∂x 与 ∂r/∂t,统计其中位数与分位数。若中位数低于 1e-3,说明残差曲面在空间上接近常数,网络输出的小扰动无法有效改变残差,优化器自然难以通过残差项改善解。
def residual_sensitivity(model, residual_fn, collocation_pts):
pts = collocation_pts.clone().requires_grad_(True)
r = residual_fn(model, pts) # 形状 [N]
dr_dx = torch.autograd.grad(r.sum(), pts, create_graph=False)[0]
sens_x = dr_dx[:, 0].abs()
sens_t = dr_dx[:, 1].abs()
return {
"median_dx": sens_x.median().item(),
"median_dt": sens_t.median().item(),
"q10_dx": sens_x.quantile(0.1).item(),
"q10_dt": sens_t.quantile(0.1).item(),
}
若 median_dx 与 median_dt 均低于阈值,同时逐层梯度统计显示深层梯度衰减,则可判定为残差项梯度消失,而非数据损失主导或学习率问题。
验证实验:三类干预与通过判据
定位到断点后,用对照实验确认因果,而不是一次性改多个因素。建议按以下顺序做单变量实验,每个实验训练相同步数并记录同一组指标。
| 实验 | 改动 | 观察指标 | 通过判据 |
|---|---|---|---|
| A 梯度增强 | 残差损失权重 λ_r 提高 10 倍,或对残差梯度做归一化 |
深层 ‖∂L_r/∂W‖、相对 L2 误差 |
深层梯度回升至 ≥1e-3,误差下降 |
| B 网络结构调整 | 激活函数改为 tanh 或 sin,或加入残差连接 |
敏感度中位数、梯度衰减比 | 敏感度中位数 ≥1e-3,衰减比 >0.1 |
| C 输入归一化 | 将 x,t 归一化到 [-1,1] |
∂r/∂x 量级、训练稳定性 |
敏感度量级提升且不出现数值溢出 |