FEATURED · 精选文章

RandLA-Net复现指南:大规模点云语义分割的工程实践与优化

发布时间 / 2026/9/15 21:41:50
来源 / 创域科博编辑部
栏目 / 资讯中心
RandLA-Net复现指南:大规模点云语义分割的工程实践与优化 1. 复现背后的核心思路RandLA-Net到底解决了什么问题先说个实际的感受三维点云语义分割这个方向RandLA-Net是绕不开的一个名字。我见过不少做自动驾驶、室内建图、机器人感知的朋友入门第一个要跑的模型基本都是它。原因很简单这个模型在效率和精度之间拿捏得很到位尤其擅长处理大规模场景。你直接拿PointNet去跑一帧64线激光雷达的数据大概率会被显存和耗时折磨到怀疑人生但RandLA-Net可以比较轻松地吃掉几十万甚至上百万个点还保持不错的精度。这次复现主要踩了两个数据集SemanticKITTI室外自动驾驶场景和S3DIS室内建筑场景。前者是64线激光雷达扫出来的道路环境包含车辆、行人、建筑物、植被等类别后者是室内RGB-D扫描重建的彩色点云包含天花板、地板、墙壁、椅子、桌子等类别。两者都属于点云语义分割的标杆数据集在论文里几乎必提。复现的目的不只是把官方代码跑通而是要把数据怎么组织、模型怎么训练、指标怎么评估这些链路全部吃透。为什么说RandLA-Net“高效”核心在于它的采样策略。传统方法常用最远点采样FPS或者体素下采样来减少点数但FPS在大点云上很慢。RandLA-Net换成了随机采样Random Sampling采样速度跟点数无关一下就把计算瓶颈打开了。但随机采样会丢失信息所以模型又设计了局部特征聚合模块Local Feature Aggregation来补。这个思路在工程上很有启发性既然下采样跑得快那就在特征层面把丢掉的信息想办法捞回来。这个设计理念是我觉得整个模型最值得学习的点。它不是单纯堆网络深度而是从数据流的效率出发把每一步的算力开销都做了考量。实际复现的时候你会发现每个模块的参数量和运算量都是经过设计的这让它在嵌入式设备和移动平台上也有落地的可能。复现这件事我建议分三条线来推进第一条线是环境与数据第二条线是模型与训练第三条线是评估与可视化。环境与数据是最容易卡住人的因为官方代码基于TensorFlow 1.x光装环境就能劝退一批人数据准备涉及编译、路径匹配、标签映射一步错步步错。模型与训练相对线性但超参数和训练策略的细节需要耐心调。评估与可视化是收尾也是检验复现是否成功的最终标准。本文会按照这个顺序把每一步的关键细节和踩过的坑都摊开来讲。2. 环境准备与依赖安装老代码的新环境适配2.1 TensorFlow 1.x环境的搭建技巧RandLA-Net官方实现是用TensorFlow 1.x写的这在今天是个不小的门槛。现在大多数人装的是TensorFlow 2.x如果你直接用TF 2.x去跑官方代码会遇到大量兼容性问题tf.Session没了、tf.contrib被删除、placeholder的用法也变了。所以最省心的方式是老老实实创建一个Python 3.6TF 1.14的环境。我试过TF 1.15也能跑但个别op的兼容性不如1.14稳。推荐的环境组合是这样的Python 3.6conda创建虚拟环境最方便CUDA 10.0 cuDNN 7.6这个组合对TF 1.14支持最好TensorFlow-GPU 1.14.0CPU版本也可以跑小数据集但训练SemanticKITTI会很痛苦pybind11用于编译C加速的knn计算模块装完TF之后有一个小细节需要确认import tensorflow as tf之后运行tf.test.is_gpu_available()看是否输出True。很多人忽略这一步结果训练的时候才发现跑的是CPU几十分钟才走一个step心态直接崩掉。2.2 编译C扩展模块的流程RandLA-Net的代码里tf_custom_ops目录下有三个自定义算子需要编译tf_neighborKNN邻居搜索、tf_subsamplinggrid subsampling、tf_batch_normbatch normalization的定制版。这三个都是通过pybind11绑定C实现的性能比纯Python实现快很多。编译方式不难但容易出问题。我遇到过的典型报错是Python.h: No such file or directory原因是系统缺少Python开发头文件。在Ubuntu上需要先装python3.6-dev然后重新编译。还有一次是pybind11版本过新和Python 3.6不兼容后来固定到pybind11 2.4.3才解决。编译完成后会生成一堆.so文件用的时候直接从tf_custom_ops目录导入即可路径不能写错。2.3 数据集加载路径的组织方式官方代码对数据路径有固定要求建议提前规划好目录结构。我的习惯是这样的Data/ ├── SemanticKITTI/ │ ├── dataset/ │ │ ├── sequences/ │ │ ├── poses/ │ │ └── grid_sub_sampling/ │ ├── pkl/ │ └── ... ├── S3DIS/ │ ├── train/ │ ├── val/ │ └── ... └── ...第一次跑的时候我把数据集放在中文路径下导致shutil复制文件时直接崩溃。后来全部改成英文绝对路径问题消失。这个坑大家提前避开省得浪费时间。3. 数据准备的完整流程与标签映射关系3.1 SemanticKITTI从原始激光雷达到训练样本SemanticKITTI数据集的原始组织方式是按序列sequence存储的每个序列对应一条行驶路线一帧点云是一个.bin文件里面存的是x, y, z, intensity四维数据没有颜色信息。标签则是另一个.label文件每个点对应一个标签值。这里有个关键.label文件里的原始标签值是KITTI自己的编号系统比如10代表car、40代表road并不是直接用于训练的类别索引需要通过官方提供的learning_map映射关系转换。我在准备数据时用官方脚本prepare_data.py它会依次做几件事读取每一帧点云将点云数据与标签合并然后通过体素下采样grid subsampling把点数降下来最后存成npy文件。同时生成一个pkl文件记录所有样本的文件路径和标签路径。训练的时候按照pkl里的索引逐样本读取而不是一次性加载全部数据避免内存爆炸。SemanticKITTI全部序列加起来有好几百GB的原始数据如果不做下采样训练时数据加载会成为瓶颈。SemanticKITTI的体素尺寸论文和代码里默认是0.06即6cm。考虑到一帧点云动辄几十万点6cm体素下采样之后点数会降到几万到十几万这个量级对于随机采样加注意力池化来说比较合适。如果显存不够可以考虑用0.08或0.1但精度会有所下降。我自己试过0.1的配置mIoU大概掉了2到3个百分点。3.2 S3DIS室内点云的预处理要点S3DIS数据集的原始格式是PLY文件每个房间一个PLY点云包含x, y, z, r, g, b六维信息其中RGB来自RGB-D相机重建后的颜色贴图。相对于SemanticKITTIS3DIS的类别数更少但室内场景的几何结构更复杂尤其是墙壁、柱子、桌子这些物体之间的遮挡关系明显对模型的上下文感知能力要求更高。预处理时我没有用官方的Python脚本而是直接用官方仓库里提供的grid_subsampling函数对每个房间做0.04m4cm体素下采样再存成npy。这里有个选择要不要保留颜色RandLA-Net模型本身支持输入特征拼接在S3DIS上把RGB作为额外特征传进去有明显收益。我的做法是把xyz和rgb合起来得到N×6的输入。如果你只用xyz精度会低不少。S3DIS的标准评测协议是Area 5作为测试集其余Area 1-4作为训练集。但官方代码里也提供了六折交叉验证的选项每一折留一个Area做测试。普通复现建议先用Area 5的单折方式因为训练速度快结果容易和别人报告的数字对比。六折交叉验证的完整结果会更接近论文数字但对算力和时间的要求高得多。3.3 标签映射与类别权重的细节SemanticKITTI训练时用的是19类还是20类这是第一次复现最容易懵的地方。官方的19类是指排除了unlabeled即原始标签0之后的有效类别实际训练时还会把一些样本数量极少的类别忽略掉。代码里专门有一个k_valid_labels字典用来记录真正参与训练的类别编号。我建议仔细读一遍semantic-kitti.yaml配置文件它定义了所有原始标签和训练标签的映射关系以及每个类别的颜色。理解这份配置后面做可视化的时候会省很多事。类别权重方面SemanticKITTI因为类别极不平衡行人、自行车等类别样本很少训练时用了中位频率平衡的交叉熵损失。官方提供了一个权重数组在train.py里直接使用。如果你自己从头训练建议保留这个权重否则模型会严重偏向样本多的类别如道路、建筑导致罕见类的IoU很低。S3DIS的类别数固定是13类12个语义类别clutter类别分布相对均匀不设置权重也能收敛但加上权重会略微提升桌子、白板这类中等样本量类别的精度。4. 模型训练的关键环节超参数、资源管理与实验记录4.1 RandLA-Net网络结构速览RandLA-Net的整体结构是编码器-解码器架构编码器有4层每层先做随机采样将点数减半或减少到1/4然后通过局部特征聚合模块提取特征。解码器做特征传播nearest neighbor插值把高层特征逐步上采样回原始分辨率。每个尺度上还有跳跃连接把编码器对应层的特征拼接到解码器上这个操作对保留细节非常关键。核心模块LocalFeatureAggregation内部又分三条支路第一条通过一个SharedMLP对输入特征做变换第二条做KNN邻居搜索K16对邻居特征做相对位置编码然后过一个注意力池化把邻居信息聚合回来第三条是一个扩张残差块Dilated Residual Block用不同扩张率的卷积扩大感受野。这三个分支的输出在通道维度上拼接再接一个残差结构。整个模块的目标是虽然随机采样丢了点但通过局部邻域的特征聚合和注意力加权把点的局部几何信息尽可能保留下来。模型所有卷积都是MLP形式即1x1卷积没有用到真正的3D卷积所以计算效率很高。参数量主要集中在SharedMLP的卷积核上整个模型大约几百万参数比很多2D图像模型小得多。4.2 超参数配置与训练策略推荐训练参数方面官方代码的默认配置已经调得比较均衡我复现时主要改动了以下几个地方学习率初始0.01使用指数衰减decay_rate为0.95decay_step按每个epoch的step数设置。对于S3DIS这种几千个样本的数据集训练100个epoch通常够用Batch sizeSemanticKITTI默认4S3DIS默认6。如果你显存只有11GB建议把batch_size降到2或3同时可以配合梯度累积来保持等效batch size输入点数每个样本随机选取40960个点作为输入。这个值不是硬性规定可以按数据集调整。点太多会影响训练速度点太少会影响对结构的感知优化器Adambetas默认(0.9, 0.999)。我在复现时试过SGDmomentum收敛慢不少建议还是用Adam。训练过程中需要重点观察两点一是loss是否稳定下降二是偶尔在验证集上算一次mIoU看趋势。RandLA-Net的loss曲线不像图像分类那样平滑会有一定的噪声但不是发散就没事。如果loss震荡剧烈优先检查学习率是否过大。4.3 资源开销与训练时间实测我用的是一张RTX 308010GB显存训练S3DIS Area 1-4做训练集的时候batch_size设为4每epoch约几百步耗时大概几分钟。100个epoch跑下来约10小时以内。训练SemanticKITTI会更慢因为数据量大且每帧点数多同一个显卡下batch_size只能开2100个epoch可能要一天以上。如果等不了长时间训练你想快速验收流程建议用S3DIS先跑通完整链路再用官方提供的预训练权重去跑SemanticKITTI的验证集确认数据和模型都正确。官方代码里有下载预训练checkpoint的脚本下载后放到train/SemanticKITTI/对应目录直接跑验证即可。这一步能帮你快速拥有一个可用的基准结果。5. 训练常见问题排查与可视化验证5.1 我在复现中踩过的典型坑第一个坑来自KNN邻居搜索模块。编译虽然成功但运行时偶尔会报错Segmentation fault排查后发现是输入点云的维度不是float32导致C函数内部访问越界。强制把输入特征转为float32后问题消失。这个细节不建议忽略尤其是从npy直接读数据时默认可能是float64喂给模型前一定要检查dtype。第二个坑是SemanticKITTI中某些帧的点数过少。数据里有少数帧因为传感器遮挡等原因点数不足采样阈值导致batch内维度不一致训练直接中断。官方代码实际上会做drop last处理但我自己写数据加载器时忘了处理排查了很久。建议在数据预处理阶段就把点数低于阈值比如20000的样本过滤掉。第三个坑是S3DIS训练时验证集mIoU一直上不去查看预测结果后发现所有类别都预测成了天花板和墙壁。这是因为S3DIS的室内场景中天花板和墙壁占了绝大面积模型被类别不均衡推向了高频类。解决办法是计算每个类别的权重在loss里做reweight或者对低频类做简单的过采样。我用了权重之后椅子和桌子这类中期出现频率的类别mIoU立刻提升了不少。5.2 常见问题速查表问题现象可能原因解决方法pybind11编译报Python.h缺失系统缺少Python开发包安装python3.6-devtf.Session不存在使用了TF 2.x创建TF 1.14环境训练时loss为NaN输入数据包含NaN或Inf预处理时过滤非法点验证时所有类别预测为背景类别权重缺失或学习率过大启用类别权重降低学习率显存不足batch size过大调小batch size、减输入点数模型输出全部一样KNN邻居搜索维度错误检查输入维度是否N×3或N×6数据加载极慢没有预先生成pkl索引用prepare_data.py生成索引文件验证结果和论文差距大标签映射错误核对learning_map映射表5.3 可视化验证模型的真实效果训练结束后可以用官方提供的visualize.py脚本对验证集数据进行预测并渲染。SemanticKITTI的可视化结果直接叠加在原始点云上类别用官方配置里的颜色渲染看起来非常直观。你会看到道路是灰色、车是红色、行人是蓝色边缘细节越清晰说明模型学到了更好的局部几何特征。S3DIS的可视化更有意思因为室内场景有清晰的语义边界比如墙和地板之间的分界线、桌子和椅子之间的细小缝隙。如果模型在边界处产生了模糊或错误的预测说明下采样或者注意力模块还有优化空间。我通常会把预测结果和Ground Truth放在同一视角下做对比来回切换看差异这样比单纯看mIoU数字更能定位问题。验证指标以mIoU为主但建议同时记录每个类别的IoU而不是只看平均值。很多情况下平均值看起来还行实际上模型可能把某个小众类别完全忽略了。我复现的S3DIS结果里clutter类别的IoU显著低于其他类别因为这类包含太多杂散物体标注本身也比较模糊。SemanticKITTI里行人和骑行者因为样本少、尺度小IoU通常比其他类别低10到20个百分点这是数据分布决定的模型本身还有优化空间。5.4 从复现到改进后续可以扩展的方向复现成功之后可以做的事情还有很多。比如把训练好的模型导出为TensorRT或者ONNX格式在机器人上做实时推理再比如把随机采样替换成其他下采样策略看它对精度和速度的影响又或者把SemanticKITTI上训练好的模型做少量微调迁移到自己的激光雷达数据上。我自己做完这次复现后最大的收获不是跑通了两个数据集而是理解了大规模点云处理的关键矛盾点太多算不过来点太少信息不够。RandLA-Net给了“随机采样特征聚合”这个工程解法但这个问题本身还有很多探索空间。后面我在做自己的项目时也一直在借鉴这种“局部注意力聚合”的写法把它用到体素特征合并和时序点云融合上效果都不错。6. 写在最后的实操建议如果你看完这篇准备自己动手复现我给你三个实操建议都是拿时间换来的经验第一先跑通S3DIS再碰SemanticKITTI。S3DIS数据量小、类别固定、训练时间短调试成本低很多。等S3DIS全流程没有问题了再上SemanticKITTI你会顺手很多。第二充分利用官方预训练权重做快速验证。不要一上来就训练先用预训练权重跑一遍验证和可视化确认数据路径、模型加载、评估代码都正确再开始训练自己的模型。这能帮你节省大量排查时间。第三做好实验记录。复现过程中你会调整很多参数我建议用表格记录每次实验的输入点数、体素尺寸、batch size、学习率、epoch数、mIoU结果这样后面做消融实验或者写论文时数据整理会轻松很多。复现模型这件事本质是对工程细节的全面检验。RandLA-Net值得你投入时间它不只是一个算法更是一套完整的大规模点云处理方案。希望这篇文章能帮你少走弯路顺利把这条链路跑通。
RELATED — 相关阅读

相关资讯

LATEST — 最新资讯

最新发布

TODAY — 本日精选

新闻

WEEKLY — 本周精选

新闻

MONTHLY — 本月精选

新闻