确保数值稳定性
在上一篇文章中,我们已经成功将协方差矩阵投影到了屏幕的二维空间(Screen Space),得到了
在理想的数学世界里,一切都很完美:这个二维协方差矩阵
在这篇文章中,我们就来聊聊如何通过几步“数值稳定性技巧”,把偏离轨道的矩阵拉回正轨,并过滤掉那些异常的数据。
强制对称
当我们对一个矩阵进行多次乘法操作后,微小的误差累积可能会导致它不再严格对称(即矩阵的转置不再等于它本身)。为了修复这个问题,我们可以使用一个非常经典且简单优雅的代数技巧:强制对称。
对于任意一个方阵
- sigma_camera_v = (sigma_camera_v + sigma_camera_v.transpose(1, 2)) * 0.5
确保半正定
虽然矩阵对称了,但我们还必须保证它是半正定的(通俗来说,高斯分布的方差不能是负数,且不能无限趋近于零导致奇异)。为此,我们需要深入矩阵的内部,对其进行特征值分解(Eigen Decomposition)。
其核心操作步骤为:
1. 分解矩阵:计算出矩阵的特征值(Eigenvalues)和特征向量(Eigenvectors)。
2. 截断特征值(Clamping):将过小的特征值拉上来,将过大的特征值压下去。
3. 重构矩阵:用修改后的特征值和原来的特征向量重新拼装出协方差矩阵。
- evals, evex = torch.linalg.eigh(sigma_camera_v)
- evals = torch.clamp(evals, min=1e-6, max=1e4)
- sigma_camera_v = evex @ torch.diag_embed(evals) @ evex.transpose(1, 2)
异常数据过滤
经过上述两步,我们的数学模型已经很稳定了。但在极少数情况下,如果初始数据极其离谱,甚至出现了无穷大(Inf)或非数字(NaN),我们必须在把它们送入下一步之前将其彻底剔除。
我们需要创建一个名为 keep 的布尔掩码(Boolean Mask),用来记录哪些高斯点是健康、有限的。
- # 异常数据过滤 (Guardrail Masking)
- flat_sigma = sigma_camera_v.reshape(sigma_camera_v.shape[0], -1)
- keep = torch.isfinite(flat_sigma).all(dim=-1)
此处 torch.isfinite 会返回一个形状为 [N, 4] 的布尔张量(全是 True 或 False)。
但我们需要的是一个形状为 [N] 的一维掩码,用来决定每个高斯点是去是留。.all(dim=-1) 沿着最后一个维度(即包含 4 个数值的维度)进行逻辑“与”运算。