3DGS 的训练机制与工程实现

A. 本篇主题

本篇聚焦 3D Gaussian Splatting 的训练优化机制。笔记 03 建立了 3DGS 的表示框架(高斯集合)和渲染方程(splatting),本篇则回答:这些高斯如何从无到有地被创建、调整、分裂、修剪?哪些参数在端到端优化中被更新?为什么这些操作能改善重建质量与收敛?

本篇内容原属于 3DGS 论文的同一部分,因篇幅较长且涉及独立的工程实现细节,单独成篇。

B. 本篇在整条路线中的位置

本篇是笔记 03 的直接延续。笔记 03 建立了”高斯如何表示”和”高斯如何渲染”的静态数学框架;本篇则阐明这个框架如何通过梯度下降动态优化,以及高斯数量如何自适应调整以匹配场景复杂度。

本篇的结尾将指出 3DGS 训练机制的一个根本局限:缺乏时间维度的表示能力。Densification/Split/Prune 都只在 3D 空间操作,无法自然扩展到动态场景。这为笔记 05(时空分解方法)和笔记 06(4DGS)做了铺垫——如果要在时间维度上做类似的自适应调整,需要全新的表示框架。

C. 数学建模

C.1 优化目标

3DGS 的训练目标是图像重建损失

其中:

  • 是训练视角数量
  • 是笔记 03 定义的 splatting 渲染颜色
  • 是第 个视角的真实像素颜色

可学习参数

注意:高斯数量 在训练过程中也是动态变化的(Densification 增加,Prune 减少)。

C.2 优化器设置

3DGS 使用 Adam 优化器配合参数级学习率:

参数学习率备注
位置 较小,保证稳定性
缩放 与位置相同
旋转(四元数 归一化后更新
不透明度 较大学习率,鼓励透明→不透明转变
球谐系数 较小,避免颜色震荡

学习率调度:位置和缩放学习率在前 3000 次迭代线性warmup到目标值。

D. 详细推导

D.1 Densification 的梯度推导

问题:初始高斯数量不足以覆盖场景细节,部分区域渲染模糊。

解决方案:通过梯度积累识别高贡献区域,增加高斯密度。

第一步:计算空间梯度

对每个像素的损失 ,沿光线反向传播到每个高斯的梯度:

Extra close brace or missing open brace\frac{\partial \mathcal{L}}{\partial \mu_i}, \quad \frac{\partial \mathcal{L}}}{\partial \Sigma_i}

由于 splatting 的 alpha 合成形式,这些梯度可精确计算。

第二步:识别需分裂的高斯

对每个高斯,累积其在所有视角、所有像素上的位置梯度:

直觉:梯度大意味着该高斯的位置对损失有重要影响——它可能位于高纹理区域或几何边缘,需要更多高斯来精细表示。

第三步:分裂操作(Split)

对梯度大的高斯,复制一份并进行小幅扰动:

同时缩小其缩放参数:

分裂的数学效果:一个大的高斯被两个小的高斯替代。由于 ,缩放缩小会使高斯变得更紧凑,在局部区域提供更高的表达能力。

D.2 Clone 和 Split 的区分

Clone(克隆):当高斯太大但梯度方向一致时,克隆一份放在相同位置但稍作偏移。

Split(分裂):当高斯沿着某个主轴方向梯度不对称时,沿着该方向分裂成两个。

区分标准:

  • 各向异性程度:计算 的特征值比
  • 比值大 → 各向异性强 → 沿长轴分裂
  • 比值小 → 各向同性 → 克隆

D.3 Prune 的不透明度推导

问题:某些高斯对重建贡献小(透明度太低或太高),应移除以减少冗余。

解决方案:基于不透明度的修剪。

第一步:计算不透明度的有效性

对每个高斯,计算其有效不透明度

这衡量了该高斯对图像最大可能贡献。

第二步:修剪阈值

设定阈值 ,移除 的高斯。

实践中 设为

第三步:不透明度的梯度更新倾向

不透明度 的梯度:

  • 当高斯在重建中作用不大(落在边缘或空旷区),梯度倾向于降低
  • 当高斯对图像有重要贡献,梯度倾向于维持或增加

这形成了一种隐式的”软修剪”机制——贡献小的高斯会逐渐变得完全透明(),贡献大的高斯维持不透明。

D.4 协方差参数化的梯度推导

协方差矩阵参数化为 ,其中:

  • 由单位四元数 参数化

四元数到旋转矩阵的转换

为保证 (行列式 +1 的正交矩阵),从单位四元数转换:

梯度传播:四元数梯度在更新后需重新归一化以保证单位性:

缩放参数的梯度:缩放参数 通过 间接影响损失。梯度计算利用矩阵微分:

E. 算法与训练流程

E.1 完整训练循环

输入:初始化高斯集合 {G_i},训练图像 {I_l} 及相机参数 {π_l}
输出:优化后的高斯集合

1.  for iteration = 1 to N do
2.      // 1. 渲染当前视角子集
3.      for l in sample_batch(π) do
4.          Ĉ ← Render(G, π_l)
5.          L ← ‖Ĉ - I_l‖²
6.      end for

7.      // 2. 梯度反传
8.      for each G_i do
9.          g_μ ← ∂L/∂μ_i
10.         g_Σ ← ∂L/∂Σ_i
11.         g_α ← ∂L/∂α_i
12.         g_c ← ∂L/∂c_i
13.         AccumulateGradient(G_i, g_μ, g_Σ, g_α, g_c)
14.     end for

15.     // 3. 参数更新(Adam)
16.     UpdateParameters(Adam, θ)

17.     // 4. Densification(每 100 次迭代)
18.     if iteration % 100 == 0 then
19.         for each G_i with large gradient norm do
20.             if G_i is anisotropic then
21.                 Split(G_i)                 // 沿主轴分裂
22.             else
23.                 Clone(G_i)                 // 克隆
24.             end if
25.         end for
26.     end if

27.     // 5. Prune(每 100 次迭代)
28.     if iteration % 100 == 0 then
29.         for each G_i with low opacity do
30.             Remove(G_i)
31.         end for
32.     end if

33.     // 6. 不透明度复位(防止高斯过于不透明)
34.     if iteration % 3000 == 0 then
35.         α_i ← α_i * 0.3 for all G_i  // 重置为较低值
36.     end if
37. end for

关键设计点

  • Densification 和 Prune 每 100 次迭代执行一次,而非每步(太频繁会影响稳定收敛)
  • 不透明度复位()防止某些高斯过早变得完全不透明,阻断梯度传播

E.2 初始化策略

基于 SfM 的初始化(推荐):

  1. 对训练场景运行 Structure-from-Motion(如 COLMAP)
  2. 得到稀疏点云
  3. 每个点转换为一个小高斯:

随机初始化(备选):

  • 在训练图像的可见空间内随机采样位置
  • 缩放初始化为较大值(如
  • 不透明度初始化为接近零(如

为什么初始化重要:SfM 初始化提供了良好的几何起点,减少训练迭代次数并提高最终质量。

E.3 渲染加速的实现

Tile-Based 光栅化

将图像划分为 的不重叠 tiles。对每个 tile:

  1. 粗筛:找出与 tile 相交的投影高斯(用 AABB 包围盒快速排除)
  2. 深度排序:按 排序
  3. Splatting:按排序顺序 alpha 合成到 tile 内的每个像素

并行化

  • 不同 tiles 可并行处理(无依赖)
  • 每个 tile 内的排序是独立的
  • GPU shader 批量执行 splatting

内存优化

  • 投影高斯值 不显式存储,按需计算
  • 仅对与 tile 相交的高斯计算投影

F. 关键直觉

  1. Densification 的本质是”梯度驱动的自适应的分辨率”:高梯度区域需要更多高斯来精细表示,这与图像处理中”边缘处需更多像素”或体素方法中”表面处需更高分辨率”的直觉完全一致。

  2. Split vs Clone 的区别是几何自适应:各向异性高斯(特征值比大)分裂成两个拉长的高斯;各向同性高斯克隆成两个相似的球形高斯。这比统一分裂更高效。

  3. 不透明度是训练的隐式开关 趋近于 0 的高斯实际上被”禁用”,但保留在集合中(可能后续通过 densification 重新激活)。

  4. 不透明度复位防止”局部最优”:当某些高斯过早变得完全不透明,它们无法接收梯度更新,复位 重新激活这些区域的学习。

  5. 训练是”重建损失驱动的高斯集合进化”:整个训练过程中高斯数量、位置、形状、颜色都在变化,目标是让最终的高斯集合能精确重建训练图像。

G. 局限性

  1. Densification 策略依赖手工设计的启发式规则:何时分裂、分裂成几个、如何区分 split vs clone,这些都需要人工调参,缺乏理论最优性。

  2. 训练不稳定且收敛依赖初始化:随机初始化时训练可能发散,需要良好的初始化(SfM)才能稳定收敛。

  3. 内存随高斯数量线性增长:复杂场景需要数百万高斯,存储和渲染的内存压力显著。

  4. 无法处理动态场景的时间维度:所有 densification/split/clone/prune 操作都是 3D 空间操作,时间维度被完全忽略。

  5. 不透明度阈值需要人工设定 是经验值,对不同场景可能需要不同设置。

H. 与前后篇的衔接

本篇承接:笔记 03 的 3DGS 表示和渲染方程。本篇说明了如何从随机/SfM 初始化的稀疏高斯集合,通过梯度驱动的 densification/prune 操作,进化到能精确重建场景的密集高斯集合。

本篇引出:3DGS 的训练优化机制虽然高效,但它是为静态场景设计的——所有操作都在 3D 空间进行,时间维度完全被忽略。当需要表示动态场景(如运动的人体、变化的物体)时,3DGS 的框架不再适用。

笔记 05 将介绍 K-Planes / HexPlane 等时空分解方法,它们将空间和时间分别表示,为动态场景提供了一条不同于 3DGS 的路径。笔记 06 的 4DGS 则将 3DGS 的高斯表示扩展到时间维度,形成完整的”显式时空高斯”框架。


本篇必须记住的结论

  1. 优化目标是图像重建损失 ,所有参数()通过 Adam 端到端优化。

  2. Densification 通过梯度积累识别高贡献区域,梯度大的高斯需要分裂以增加局部表达能力。

  3. Split 沿各向异性主轴分裂,Clone 复制到相近位置:通过 的特征值比判断是各向异性(分裂)还是各向同性(克隆)。

  4. Prune 基于有效不透明度 移除低贡献高斯 时移除。

  5. 不透明度复位()防止高斯过早完全不透明而阻断梯度传播,是训练稳定的重要技巧。

  6. 所有训练操作都是 3D 空间操作,时间维度被完全忽略,这限制了 3DGS 处理动态场景的能力。


参考文献

  1. Kerbl et al. “3D Gaussian Scattering for Real-Time Rendering of Radiance Fields” ACM TOG 2023
  2. Kingma and Ba. “Adam: A Method for Stochastic Optimization” ICLR 2015(优化器基础)
  3. Szeliski. “Computer Vision: Algorithms and Applications” 2nd Ed.(COLMAP/SfM 参考)