news 2026/10/29 1:50:07

3DGS 模型保存与加载完整指南:PLY 格式扩展与断点续训实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
3DGS 模型保存与加载完整指南:PLY 格式扩展与断点续训实战

3DGS 模型保存与加载完整指南:PLY 格式扩展与断点续训实战

【免费下载链接】gaussian-splattingOriginal reference implementation of "3D Gaussian Splatting for Real-Time Radiance Field Rendering"项目地址: https://gitcode.com/gh_mirrors/ga/gaussian-splatting

跑 3D Gaussian Splatting(3DGS)训练的人大概都经历过这种时刻:迭代到 3 万步,机器断电 / 显存爆了 / 被同事的脚本抢卡。训练目录里只有一个 .ply,重新加载后发现优化器状态全丢,等于从"半成品"倒退回"刚起步"。其实 3DGS 官方仓库 gaussian-splatting 的模型持久化方案分两条线:PLY 文件负责把模型参数完整落盘,checkpoint 文件负责把优化器状态落盘。本文沿着"存了什么 → 怎么存 → 怎么加载 → 怎么续训 → 体积怎么省"这条线,把 scene/gaussian_model.py 里的保存与加载机制讲透,帮你把崩溃后的损失降到最低。

3DGS 模型文件到底存了什么:和网格模型差在哪

先说人话:网格模型(OBJ/GLB)存的是"顶点 + 面片拓扑",而一个 3DGS 模型存的是几百万个可变形椭球,每个椭球自带一套参数——位置、三个方向的缩放、朝向四元数、不透明度,再加一组球谐(SH)系数来描述"从不同角度看它是什么颜色"。

这决定了它的模型文件没法套用标准网格格式。官方在 scene/gaussian_model.py 的construct_list_of_attributes里给出了完整清单,一张表对比清楚:

参数字段(PLY 列名)个数作用
椭球中心xyz3空间坐标
法向量nxnynz3纯占位,值全为 0
球谐 DC 项f_dc_0~23基础颜色(视角无关部分)
球谐高阶项f_rest_0~443×(L²−1),L=4 时为 45随视角变化的颜色
不透明度opacity1椭球"实体感"强度
缩放scale_0~23三轴半径
旋转rot_0~34单位四元数定朝向

合计23 个属性,全部是 float32。注意后四类参数(缩放、旋转、不透明度、SH 系数)训练时会被持续优化,所以文件必须把它们的当前值原样存下来——这正是save_ply的职责。

PLY 格式怎么扩展的:23 个属性背后的一个关键取舍

PLY 本质是一张可自定义列的表格文件:element vertex声明有哪些列,后面每行一个顶点数据。3DGS 没有发明新格式,而是像给表格追加新列一样,把 23 个参数全部挂成 vertex 的自定义属性。save_ply的骨架只有四步:

xyz = self._xyz.detach().cpu().numpy() normals = np.zeros_like(xyz) # 法线列只作占位 f_dc = self._features_dc.detach().transpose(1, 2).flatten(start_dim=1).cpu().numpy() f_rest = self._features_rest.detach().transpose(1, 2).flatten(start_dim=1).cpu().numpy() scale = self._scaling.detach().cpu().numpy() rotation = self._rotation.detach().cpu().numpy() # ...把各数组沿 axis=1 拼接成 (N, 23) 后,用 PlyData 逐行写入

这里有个容易忽略的关键设计:所有参数存的都是原始优化值,不是渲染时用的激活值。缩放存的是exp之前的对数空间值,不透明度存的是sigmoid之前的值。为什么?因为模型加载后往往还要继续训练,参数必须和nn.Parameter里的值一一对应才能接上梯度;若存激活后的值,反推回去就有精度损失,续训直接"变味"。

顺带算笔账:100 万高斯的 PLY 约100MB(每个高斯平均 100 字节左右);千万级场景则轻松突破1GB——这个数字后面讲省空间技巧时会再用到。

3DGS 模型加载:load_ply 如何把文件还原成可训练的模型

加载是保存的逆过程,load_ply里有两个值得注意的细节。

第一个:SH 系数数量要动态解析。高阶球谐列数取决于阶数 L(3*(L²−1)),文件里有多少列不能靠假设,得扫描出来再核对:

extra_f_names = [p.name for p in plydata.elements[0].properties if p.name.startswith("f_rest_")] extra_f_names = sorted(extra_f_names, key=lambda x: int(x.split('_')[-1])) assert len(extra_f_names) == 3*(self.max_sh_degree + 1) ** 2 - 3

这里藏着最常见的坑:如果加载时配置的max_sh_degree和训练保存时不一致,这个assert会直接炸(或者炸之前渲染出怪颜色)。scale_、rot_两组列用同样的"前缀扫描 + 数字后缀排序"方式解析。

第二个:张量重组。解析出的 numpy 数组统一包成nn.Parameter并requires_grad_(True),直接建在 CUDA 上,比如:

self._features_rest = nn.Parameter( torch.tensor(features_extra, dtype=torch.float, device="cuda") .transpose(1, 2).contiguous().requires_grad_(True))

SH 系数在文件里是每行展平的一串数,加载时reshape回(N, 3, L²−1)再转置成(N, 1, C)的布局,和create_from_pcd初始化时的形状对齐。函数最后一行self.active_sh_degree = self.max_sh_degree也很实在:既然文件里存的是满阶系数,加载后直接拉满。

3DGS 断点续训:capture 与 restore 的双持久化机制

回到开头的痛点:训练中断后怎么接着跑?答案是两个文件分工。PLY 只存参数;而 Adam 优化器的动量exp_avg、二阶矩exp_avg_sq,以及自适应点增删用到的xyz_gradient_accum、denom这些"训练记忆",都不在 PLY 里。

train.py 的保存逻辑是:每到--checkpoint_iterations指定的迭代,就把gaussians.capture()的返回值连同迭代号一起存成.pth:

# train.py 中,iteration 命中 checkpoint_iterations 时: torch.save((gaussians.capture(), iteration), scene.model_path + "/chkpnt" + str(iteration) + ".pth")

capture()在 scene/gaussian_model.py 里返回一个 12 元组,成员按职责分三类:

类别成员用途
模型参数_xyz_features_dc_features_rest_scaling_rotation_opacity权重本体
训练记忆max_radii2D、xyz_gradient_accum、denom、active_sh_degree、spatial_lr_scale点云增删与学习率调度
优化器optimizer.state_dict()恢复 Adam 动量与二阶矩

恢复侧是restore(model_args, training_args):解包元组后先调training_setup重建优化器,再self.optimizer.load_state_dict(opt_dict)把动量灌回去。启动时加--start_checkpoint path/chkpnt30000.pth,train.py 里就会torch.load后执行gaussians.restore(model_params, opt),从对应迭代继续——动量不丢,收敛曲线能无缝接上。

高斯模型文件体积怎么优化:千万级高斯的三个方向

千万高斯的 PLY 超过 1GB,存储和加载都会疼。三个可落地的方向:

  1. 量化压缩:features_dc/features_rest默认 float32,改用numpy.astype(np.float16)落盘可省一半体积,代价是加载后转回 float32 有一丁点精度损失。
  2. 空间分区:把点云按空间位置切成多个 PLY 文件,部署时只加载视锥相关的块,加载与渲染都能减负:
# 按坐标块切分,每块独立写一个 PLY def save_partitioned_ply(xyz, params, partition_size=1e6): for i in range(0, xyz.shape[0], partition_size): save_ply(f"model_part_{i//partition_size}.ply", xyz[i:i+partition_size], params[i:i+partition_size])
  1. 增量更新:只存相对基线模型的 diff 文件,适合高频迭代的场景版本管理。

加载侧则推荐内存映射延迟读入,避免大文件一次性占满内存:

plydata = PlyData.read(path) # 先读元数据 xyz = np.memmap(path, dtype='f4', mode='r', offset=plydata.elements[0].data.offset, shape=(plydata.elements[0].count, 3))

三条策略可叠加:先 prune 瘦身,再分区,最后按需 memmap 加载,千万级场景的磁盘和内存压力都能压到可接受范围。

3DGS 加载后渲染异常 / 续训失败的常见坑速查

现象可能原因解法
加载后颜色发灰 / 发怪max_sh_degree与保存时不一致,SH 系数维度对不上统一 SH 阶数配置再加载
优化器状态加载报错中途做过点云修剪,参数数量和快照不匹配修剪走prune_points/_prune_optimizer,同步剪 optimizer 状态
PLY 体积过大大量低贡献高斯没被清掉保存前执行prune_points,按不透明度阈值 0.01 过滤
大模型加载卡内存整个文件一次读入分块 PLY +numpy.memmap延迟加载

最后一行效果直观对比一下:低质量阶段的渲染(左)和收敛后的渲染(右)差距明显——所以体积优化时别为了省空间把"有用的高斯"也剪没了。

小结

一句话收束:PLY 存参数,.pth 存记忆——save_ply落盘 23 个 float32 属性且坚持存原始优化值,capture/restore负责把 Adam 动量和训练统计量完整续上;体积问题交给 prune(阈值 0.01)、量化、分区和 memmap 组合拳。随着实时渲染需求增长,更紧凑的专用二进制格式与硬件加速的加载路径大概率会登场,但理解这套 PLY + checkpoint 的双持久化机制,永远是你玩转 3DGS 工程化的基本功。

【免费下载链接】gaussian-splattingOriginal reference implementation of "3D Gaussian Splatting for Real-Time Radiance Field Rendering"项目地址: https://gitcode.com/gh_mirrors/ga/gaussian-splatting

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/29 1:47:38

三年进化:AI编程工具从玩具到协作伙伴的跃迁

1. 三年时间,AI编程工具到底变了什么我记得三年前第一次用AI辅助写代码的时候,那种感觉就像拿到一个会说话的橡皮鸭子——它能跟你聊天,能给你一些提示,但真让它写点能跑的东西,十次里有八次得自己从头改到尾。那时候大…

作者头像 李华
网站建设 2026/10/29 1:46:37

Samba文件服务器安全(7)

完成 Samba 服务器的基础加固——关闭 NetBIOS、限制监听接口、配置防火墙、启用消息签名——并不意味着安全工作就此结束。配置写在文件里是一回事,实际运行效果是否达标则是另一回事。端口是否真的关闭了?SMB 协议版本是否符合预期?防火墙能否有效抵御 SSH 暴力破解?这些…

作者头像 李华
网站建设 2026/10/29 1:44:45

Crush AI 编码助手安装与上生产:一份实操手册

Crush AI 编码助手安装与上生产:一份实操手册 【免费下载链接】crush Glamourous agentic coding for all 💘 项目地址: https://gitcode.com/gh_mirrors/crush3/crush 这篇文章讲 Crush 部署的完整流程:从一行命令装好 AI 编码助手、…

作者头像 李华
网站建设 2026/10/29 1:38:46

neuroptica:可微分光学神经网络仿真框架

简介:本资源是面向光学计算与光子人工智能研究者的专业仿真工具包,专为光学神经网络(ONN)建模、设计与性能评估提供开源支持,适用于高校研究生、光电交叉领域工程师及AI硬件方向科研人员。包内共39个文件,以…

作者头像 李华
网站建设 2026/10/29 1:36:45

3个维度解析ECDICT:开源词典数据库的技术实现与应用价值

3个维度解析ECDICT:开源词典数据库的技术实现与应用价值 在数字化时代,词典工具已成为语言学习、应用开发和文本分析的基础设施。ECDICT作为一款完全开源的中英文词典数据库,通过本地化部署实现毫秒级离线查询响应,支持自定义扩展…

作者头像 李华