LiDAR点云跨域分割:从64线到16线的UDA与结构改进实战
跨域部署的翻车现场64线模型遇到16线点云先说一次让我印象很深的实测模型是在64线LiDAR点云上训练的源域验证mIoU做到68.2换到一辆装了16线激光雷达的采集车上没做任何适配直接推理目标域mIoU掉到31.5。道路、建筑这些大目标还算完整但行人、骑车人基本碎成噪点护栏和低矮路沿几乎全丢。那一刻我意识到Road-Object Segmentation的模型结构再花哨跨传感器、跨场景部署时Unsupervised Domain Adaptation不是可选项而是刚需。这篇文章想把我在这个方向上的完整思路记录下来主要包括三件事为什么模型结构要专门为UDA做改进无监督域适应在LiDAR点云分割里的可用流水线长什么样以及我在调参、复现、实测过程中踩过的一堆坑。内容偏工程实践适合做自动驾驶感知、点云分割算法落地或者正在调研UDA方案的同行参考。1. 跨域部署的翻车现场从68.2到31.5的差距是怎么拉开的1.1 一次习以为常的跨设备测试事情是这样的项目组里同一套代码同一个训练配置在公开基准数据集A上训出来的模型放到自采工业园数据集B上测试。两个数据集都是LiDAR道路场景类别也都是道路、车辆、行人、骑车人、建筑那一套。我当时想的是模型泛化再差也不至于差到没法看吧。结果一跑验证直接傻眼。更让人头疼的不是整体指标而是可视化结果。远距离行人被漏检金属护栏被错分卡车侧面被切成好几块。后来我把点云叠加到真值上一帧一帧看发现模型在密集的近处点云上表现还行一旦点云变稀疏比如15米以外的行人特征提取基本失效。这个现象不是单个类别的问题而是所有小物体都中招。后来我把64线采集车上的数据和16线采集车的同场景数据放在一起比才意识到所谓跨域最直观的表现就是点云密度和分布的巨大差异。64线在50米处的地面点间距可能只有几厘米16线到了30米就稀疏得跟筛子一样。模型训练时没见过的这种稀疏模式直接推理当然扛不住。1.2 三类域差距密度、统计分布与标注风格很多文章把域差距笼统地说成数据分布不同但落到LiDAR点云分割上我总结下来主要有三类密度与距离衰减模式不同线束LiDAR的垂直角分辨率不同导致各距离区间的点密度差异很大。64线在近距离非常密集16线在中远距离就已经稀疏到难以支撑局部几何特征。坐标统计与反射强度不同设备的扫描范围、安装高度、旋转方式不同点云的空间坐标统计特征差异明显。更隐蔽的是强度值不同设备对同一材质物体的反射强度标定差异可能达到几十甚至上百直接把模型搞懵。类别定义与标注边界两个数据集即使类别名相同标注规则也可能不同。比如骑车人里包不包含自行车本身行人在遮挡时标注边界画在哪里这些都能让同一模型在跨数据集时出现系统性偏差。理解这三类差距才能对症下药。我见过不少人一上来就套UDA方法结果只解决了统计分布对齐密度差异没管效果自然上不去。1.3 为什么不能靠暴力重新标注解决问题有人会问既然目标域效果差那就重新标注一批目标域数据不就行了吗道理是这个道理但实际工程里行不通。首先是成本。一帧64线LiDAR点云的语义标注熟练标注员要花十几分钟到半小时遇到密集场景甚至更久。一个工业园园区测试集就算只有2000帧也是几百个工时做完一次还能忍做两次三次就完全扛不住。其次是迭代周期。算法每改一版如果都要重新标注才能验证效果那开发节奏基本废了。最后是数据获取的实时性。传感器升级、采集车换装、新场景测试这些都是持续发生的事靠标注去追永远追不上。所以我当时的判断是要么用无监督域适应让模型自己适应目标域要么就接受每次换传感器都重训一遍的糟糕体验。既然目标是做能落地的系统UDA这条路必须打通。2. 模型结构改进让网络在点云稀疏区与稠密区都能看得准2.1 主干选择单一结构在密度剧烈变化下不可靠先交代一下背景。我最初用的是业界非常成熟的单分支点云分割网络靠3D稀疏卷积在体素化后的点云上做特征提取然后反投影到每个点得到语义类别。这套方案在源域测试集上表现稳定因为源域数据集中近处远处、密集稀疏的样本都相对均衡。但它有个致命弱点体素化会丢失点级高频几何信息。什么意思体素大小比如设成0.1m一个行人的点云被塞进几个体素里如果密度不够体素内的点可能只有一两个稀疏卷积提取出来的特征就变成了即兴发挥。16线点云在中远距离恰恰就是这样。单靠稀疏卷积主干去扛等于在密集和稀疏两个极端之间走钢丝。我在对比实验里发现把输入点云人为抽稀到目标域密度水平后单分支模型的mIoU直接从66.1掉到48.7而双分支结构只掉了9个点。这个差距说明面对密度变化网络结构必须先稳下来UDA后续才能接得住。2.2 双分支方案的选型逻辑与关键超参数我最终采用的方案可以概括为体素分支管结构点分支管细节体素分支用稀疏卷积在体素空间提取局部结构和上下文语义负责看懂建筑物轮廓、道路走向、车辆姿态这些宏观信息。这个分支对密度有一定容忍度因为就算体素内点数少只要局部几何形状还在卷积核还是能学到模式。点分支用MLP直接处理原始点坐标和邻近特征保留每个点的精确空间信息。远距离稀疏点不会被池化稀释点分支依然可以基于局部的少量点拟合几何。两个分支在编码器中间层和解码器输出层各做一次融合。中间层融合用的是通道拼接加轻量注意力输出层融合用的加权求和。这样低层的高频几何信息和高层的语义信息都能保留。关键超参数我实测下来是这样体素尺寸0.15m比较均衡。0.1m体素在近距离表现好但远距离体素空置率太高浪费算力0.2m体素对细长物体比如路沿、护栏形状表达不够。前后对比下来0.15m是性价比最高的。点分支的采样范围也很重要我限制在半径1.5米的球邻域内。太大会把远距离点的特征稀释掉太小则局部上下文信息不足。这个数值不是玄学我是以行人点云的平均空间尺度为基准调的。融合权重我采用了一种简单的自适应策略让网络自己学每层两个分支的权重初始值各为0.5。收敛后观察近处点往往更依赖点分支远处点反而更依赖体素分支符合直觉。2.3 损失函数交叉熵只是基础不能只有它结构改了损失函数也不能太随意。点云分割的类别分布天然不平衡道路和建筑占了大多数行人、骑车人只有一点点普通交叉熵会被大类别把梯度淹没。我用了加权交叉熵加Lovász-Softmax的组合。加权交叉熵负责把少量类别拉起来Lovász-Softmax直接优化IoU相关的代理损失对整体mIoU的提升比较友好。权重方面我按类别频率的倒数做了截断最小权重不低于0.1最大不超过3.0。为什么不直接把稀有类别权重拉到10因为太高的权重会让模型在小类别上过拟合在源域验证集上漂亮跨域时反而更快崩掉。提示做UDA任务时损失函数选择不要只看源域mIoU。一个在源域上过拟合到完美的模型目标域上往往更弱因为特征容易被源域特有模式绑架。2.4 为什么先改结构再谈域适应是对的我最初也走错过方向先不管结构直接套了一个当时很火的对抗式域适应模块结果目标域mIoU只从31.5涨到34.2非常有限。后来仔细分析才发现模型在稀疏区域连基本几何特征都提取不出来你让它做域对齐它对齐的其实是一堆噪声特征。换个顺序做实验先把双分支结构加上不引入任何域适应目标域mIoU直接从31.5涨到43.8。这时候再做域对齐才能再往上走。这个经验让我确信结构是地基UDA是上层建筑地基不稳上层再花哨都白搭。3. UDA流水线先用保守伪标签把学生模型扶起来3.1 整体流程源域预训练、目标域伪标签、交替微调模型结构确定之后UDA流水线本身我也走了好几轮迭代最后稳定下来的是一个偏传统的自训练框架外加轻量化的特征约束。流程分四步源域预训练用标注数据训练一个初始模型不追求极致精度但要保证基本的类别区分能力。生成伪标签用预训练模型推理目标域点云每个点得到各类别置信度按阈值和规则生成伪标签。联合微调把源域标注数据和带伪标签的目标域数据混合一起训练一个学生模型一般迭代两到三轮。可选特征约束在最后几轮加入特征统计对齐约束抑制目标域逗留的分布偏移。这个流程的关键是保守。伪标签只保留高置信度的点宁可漏标也不引入噪声。UDA最大的风险不是伪标签太少而是伪标签里的系统性错误会被模型当作真理学进去越学越偏。3.2 伪标签的获取不是置信度大于某值这么简单很多人写UDA代码伪标签就是confidence 0.95全部mask保留。但LiDAR点云分割跟2D图像不一样类别之间天然有几何混淆关系。我举几个典型的例子行人跟骑车人在点云里行人和骑车人的几何外形很接近尤其是当骑车人身体部位遮挡严重时模型几乎分不清。置信度0.9以上的伪标签也可能错。护栏跟墙体如果点云密度低护栏的稀疏点在体素化后表现成一片平面非常容易被当成墙体。地面跟低矮植被地面点的局部特征和低矮灌木很像尤其在点云稀疏时。所以我最终放弃统一阈值方案改成类别自适应阈值加几何先验约束车辆、建筑、地面这些大类置信度阈值拉到0.95以上行人、骑车人、摩托车这些易混小类阈值放宽到0.85给模型更多机会学到目标域的形态变化。然后加一层几何约束地面点的z值必须在局部邻域内连续行人点的高度范围必须在合理区间内否则即使置信度达标也丢弃。3.3 伪标签不是越自信越好把标错的点识别出来还有一类问题容易被忽视空间分布。目标域点云不同区域模型置信度分布差异很大。近距离点云特征丰富伪标签置信度高远距离点云特征稀疏置信度普遍低。如果按全局置信度阈值直接过滤远距离物体几乎没有伪标签学生模型在远距离上又变成睁眼瞎。我的做法是分距离区间设置阈值。0到20米用0.920到40米用0.840米以上用0.7。虽然远距离的伪标签噪声更大但不给样本模型对远距离就完全没有学习信号。测试下来远距离类别IoU的提升比“一刀切”方案多出约5个点。3.4 用EMA模型当伪标签生成器比在线模型更稳自训练框架里一个很容易踩的坑是学生模型如果直接从当前轮次模型生成伪标签很容易陷入模型偏误自我强化的恶性循环。这个轮次模型把某个错分的类别当作正常下一轮它继续用这个错误伪标签训练自己越错越深。我的解决方案是用指数滑动平均模型EMA。每当学生模型更新一步EMA模型就按0.99的衰减因子更新。伪标签始终由EMA模型生成学生模型只负责学习。这样即使学生模型偶尔走偏EMA模型还保留着更接近源域分布的记忆伪标签不会跟着一起崩。3.5 特征域对齐把它放在最后别一开始就加很多对抗式UDA方法强调从一开始就加域判别器让特征域无关。我的实测结论是在语义分割任务里初期就强推域对齐会伤语义表达。原因很简单分割需要的是语义判别性特征而域判别器要求特征无法区分数据来源这两个目标早期是冲突的。打个稍微生活化的比方你让一个刚学会区分猫狗的孩子同时要求他别去听动物声音来自哪个录音设备如果两个任务同时学他会连猫狗都有些分不清。先学会区分再让特征对设备不敏感顺序很重要。我在实验里试过两种方案第一种从第一轮就加对抗域判别器第二种等第三轮才加最终目标域mIoU相差了3.4个点。所以我把域对齐模块的启用时机放在了自训练已经收敛之后并且梯度反转层的权重设在0.01这个很小的量级。4. 调参日志与踩坑记录从42.3到57.1的完整链路4.1 一个反向下降案例域判别器加太强反而掉点有一轮实验特别值得复盘。我给流程加上了对抗域判别器梯度反转权重开到0.1目标域mIoU不升反降从52.8掉到50.1。一开始我以为是随机性重跑两次还是差不多。后来把特征可视化出来才发现域判别器太强的时候模型把某些本可以用来区分类别的方向性特征也对齐掉了。最典型的是路沿与低矮墙体这类由空间朝向区分的物体。域判别器把两个域的这些特征强行拉到一起反而把类间差异给磨平了。后面我把梯度反转权重降到0.01并且只在网络后三分之一层级施加约束效果才稳住最终反而比不加判别器时高出2.3个点。提示域对齐不是越彻底越好。分割任务的标签空间是语义域对齐操纵的是特征空间两者必须找一个平衡点而不是非黑即白地追求特征完全不可分。4.2 置信度阈值与类别不平衡的拉锯战伪标签的置信度阈值我做了几组对比阈值策略目标域mIoU有效伪标签点数相对现象全局0.9551.268%行人骑车人几乎没伪标签全局0.849.892%噪声太多模型被带偏类别自适应0.85/0.9555.781%大类别稳小类别有收益类别自适应距离分段57.179%远距离小物体终于有提升注意第三和第四行差了1.4个点这个提升主要来自远距离伪标签的加入。代价是噪声也更多但对分割任务来说有噪声的监督信号远好过没有监督信号前提是噪声占比不超过一定上限。4.3 四个反复踩的工程坑第一个坑是强度归一化。不同LiDAR的反射强度标定差异极大我的源域模型几乎完全依赖强度值来区分金属栏杆和树木。目标域强度分布一变这个线索直接失效。我后来强制把源域和目标域的强度值分别做分位数归一化再作为输入特征效果立刻改善。这件事必须在数据加载层面解决不要在模型里靠学习补救。第二个坑是地面点处理。有人喜欢先用地面分割算法把地面点去掉再送入分割网络。这种做法在密集点云上效果好但16线点云地面分割本身就不稳一旦把地面点误删道路区域就会变成空洞。我是反过来保留所有点输入网络让模型自己学地面模式反而更稳。第三个坑是评估指标虚高。自训练微调后目标域mIoU涨了不少但是我单独抽查了200帧目标域数据用人工标注真值去算IoU发现比伪标签评估低大概3到4个点。原因很简单伪标签生成的评估集带有模型自身的偏误。如果模型在行人这个类别上误判为骑车人而伪标签也这么标那评估时这两个类别都恰好正确了实际却是错的。所以UDA实验里必须留一部分人工标注的目标域数据做最终评估。第四个坑是时序数据必须打乱。我一开始直接用连续帧序列做伪标签自训练结果模型mIoU看着很高换到验证集直接崩。原因很直观相邻帧点云高度相似伪标签也高度相似模型学到了复读机模式根本没有泛化到帧间变化。把序列数据充分打乱混合后性能才回归正常。4.4 从42.3到57.1我是靠哪些决策一步步走到的我把整个优化过程拆成里程碑方便大家对照参考阶段操作目标域mIoU起点单分支模型无UDA31.5结构改进双分支模型无UDA43.8伪标签两轮类别自适应阈值距离分段55.7域对齐模块梯度反转0.01最后两轮启用57.1注意从43.8到55.7这11.9个点的提升主要来自自训练。再加域对齐只贡献了1.4个点。这不是说域对齐没用而是说明在自训练已经效果很好的情况下域对齐的边际收益在变小。如果你算力或时间有限优先做结构和伪标签自训练性价比最高。5. 实测效果与理性判断哪些涨点是真实的哪些只是数字游戏5.1 分类别涨跌表现大物体大涨小物体原地踏步看整体mIoU容易产生错觉好像UDA让所有类别都变好了。实际上分类别看差异非常明显类别初始结构改进后完整UDA后道路62.371.878.5建筑54.666.372.0车辆60.169.475.2行人18.728.531.4骑车人21.327.229.8护栏25.135.038.9道路、建筑、车辆这些类别UDA带来的提升非常可观因为它们的伪标签置信度高可学习样本多。行人、骑车人这种小目标结构改进带来的提升比UDA更大而UDA只贡献了2到3个点。护栏这类细长物体居中。结论是UDA解决的是目标域可学习样本不足的问题但解决不了模型本身对稀疏小目标捕捉能力弱的问题。后者必须靠结构改进、数据增强、时序融合这些手段去补。5.2 纯UDA的上限不要幻想零标注追平全监督我在实验中还做了一个对照把目标域所有数据全部人工标注用完整监督训练同结构模型目标域mIoU可以到69.5。纯UDA最好成绩是57.1差距还有12.4个点。所以说句实话在LiDAR道路物体分割里纯无监督域适应可以让一个新场景的模型从基本不可用变成能跑起来但要追平完全重新标注是不现实的。那些宣称UDA逼近全监督的工作多半是在特定类别和特定场景下取得的放到长尾类别上照样失真。最理性的定位是UDA用于冷启动让模型先有一个可用的底子再配合少量关键帧人工标注做修正才是性价比最高的路线。5.3 后续可以扩展的三个方向如果时间充裕我会在三个方向接着做一是多帧时序信息。LiDAR单帧点云对行人和骑车人的几何表达先天不足多帧叠加可以显著提升小型物体的几何密度。如果UDA配合时序特征一致性约束伪标签稳定性会进一步改善。二是物理层面增强。比如模拟雨雾噪点、模拟低线束LiDAR的稀疏模式在源域直接把目标域可能遇到的物理变化提前引入。这个思路可以降低域差距让UDA更轻松。三是半监督与UDA结合。我已经在私下实验里验证过只标注目标域5%的关键帧加上无监督域适应目标域mIoU能从57.1直接拉到63.8。相比纯UDA的提升这个收益几乎是免费的也很贴近真实工程。未来如果条件允许我会把这条路线继续推下去。经历了这些实验我最大的体会是无论是结构改进还是域适应本质上都是在跟信息量不足作斗争。源域模型掌握的规律到了目标域变得不可靠不是模型笨而是它训练时没见过这些情况的变体。解决路径也很朴素先把网络结构做得更耐受稀疏变化再用保守的策略从目标域本身一点点收集可学习的信号。看起来没有特别惊艳的trick但每一步踩实了最后的效果反而很扎实。