ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

PointTransformer V1到V3全解析:点云Transformer原理、复现与选型指南

PointTransformer V1到V3全解析:点云Transformer原理、复现与选型指南 先说点题外话。点云处理这个方向早几年还是PointNet的天下后来稀疏卷积在自动驾驶场景里大杀四方再后来大家发现Transformer在无序、稀疏、不规则的数据上有天然优势。PointTransformer这个名字从V1到V2再到V3这几年几乎每隔一段时间就有人问我“该用哪个”这也是我写这篇东西的直接原因。这篇不打算复述论文公式更多是我自己从原理、复现、踩坑到选型的一整套理解希望对正在做点云分类、分割、场景理解的朋友有点实际帮助。正文直接开始。1. 为什么PointTransformer能成为点云架构的分水岭1.1 点云数据的“反CNN”特性点云和图像最本质的区别不是维度从2D变3D而是数据结构完全不同。图像是规整的密集网格每个像素都有固定邻居CNN靠卷积核扫过整个特征图就能完成特征提取。点云不一样它是一堆无顺序的坐标点没有“上下左右”的概念密度也不均匀远处稀疏、近处稠密同一个物体换个角度扫描点的位置完全不同。这种数据特性导致一个老问题如何设计一个对点的顺序不敏感、对空间位置敏感的算子。PointNet的思路是把每个点独立映射到高维特征再靠max pooling把所有点特征聚合成全局特征简单粗暴但缺失局部结构。PointNet用FPS采样和球查询把局部邻域带进来虽然有了局部感受野但本质上还是“以点为中心做小型CNN”的路子。稀疏卷积效率高但需要把点云体素化量化误差和分辨率限制一直绕不开。1.2 自注意力无序数据的天然解Transformer里的自注意力机制本质就是一个基于“内容”的加权求和。给定一组输入每个元素和所有其他元素计算相似度然后按相似度加权聚合信息。这个过程完全不依赖输入的顺序天然满足置换不变性。换句话说自注意力本身就是为无序数据设计的点云恰好是无序数据。而且自注意力还有一个CNN没有的好处感受野是动态的。CNN的卷积核空间范围固定扩大感受野只能加深网络自注意力可以直接建立任意两点之间的关联长距离依赖的建模能力天然强很多。1.3 从PointNet到PointTransformer语境转变PointNet之后大家的注意力都花在“如何在点云上做局部卷积”上面比如PointCNN、KPConv、PAConv这些工作核心思想都是设计更合理的局部聚合方式。但Transformer的兴起提供了一个新的视角与其费劲设计卷积核不如直接用注意力机制做局部聚合。PointTransformer V1在这个背景下出现可以说是一个很自然的演进。它没有发明全新的数学工具而是把Transformer做局部特征聚合的方式适配到点云这种不规则数据上。从这之后点云处理的主流范式从“设计卷积”变成了“设计注意力”这个转变的带动作用比模型本身更大。2. PointTransformer V1把Transformer搬进三维空间2.1 核心模块拆解局部自注意力与位置编码V1的核心思想说起来并不复杂对每个点先找到它周围的K个近邻点只在这K个点组成的局部邻域里做自注意力而不是在整个点云上做全局注意力。这样既保留了Transfomer的内容相关性建模能力又不会让计算量爆炸。每个Transformer block的流程大致是这样输入点云特征 F以及每个点的坐标 X对每个点通过KNN查找得到K个邻域点计算中心点和邻域点之间的相对位置X - X_neighbor用MLP把相对位置编码成位置编码自注意力在邻域内对中心点特征做加权聚合更新特征堆叠多个block位置编码是V1里非常关键的一环。图像里的Transformer往往把位置编码作为可学习的绝对位置嵌入但点云的坐标是连续值而且每个点云的点数、坐标范围都不同所以V1直接输入坐标本身用相对位置来编码。这背后的逻辑是自注意力只算“特征相似度”但特征相似的两个点可能距离很远如果只看特征局部邻域里的注意力就失去了空间含义。位置编码的作用就是把几何关系重新注入注意力权重让模型既知道“这两个点特征像”也知道“这两个点在空间上离得远不远”两者结合才算真正的局部几何感知。2.2 向量注意力为什么不走寻常路V1还有一个值得关注的设计就是它用的不是标准的“标量注意力”而是向量注意力。常规Transformer里注意力权重是一个0到1之间的标量代表相关性权重然后通过softmax归一化。V1的做法是让注意力权重变成一个和特征同维度的向量用这个向量对特征做逐通道的加权。更直白地说传统的注意力是筛选“哪些位置的信息更重要”向量注意力则同时做到“哪些位置重要”以及“哪些特征通道需要被增强或抑制”。这个设计在点云上的效果非常好。因为点云里不同通道往往对应不同的几何语义比如某些通道编码了曲率变化某些通道编码了方向信息用一个统一的标量去加权这些通道容易互相干扰。向量注意力相当于给每个通道分配了独立的权重表达能力更强。代价是参数和计算量更高这也是V1在效率上被诟病的原因之一。2.3 V1的优势与瓶颈V1的优势很明显模型简单、效果好、思路直观在ModelNet40分类、ShapeNetPart部件分割、S3DIS室内场景分割上都实现了当时的最优水平。另外它处理不规则数据的能力很强不需要把点云体素化也没有量化误差。瓶颈同样明显。第一KNN邻近查找在大规模点云上很花时间因为需要在整个点集上做最近邻搜索。第二虽然做了局部限制但每个中心点还是要在K个邻域里做注意力计算量和点数呈线性关系可常数很大。第三V1的特征提取属于逐点操作在大规模场景分割任务上显存占用和推理时间都比较难受。S3DIS这种几百万点的大场景V1跑起来确实吃力。一句话总结V1证明了Transformer在点云上的可行性但工程上还不够友好。3. PointTransformer V2针对大场景的效率革命3.1 分组向量注意力把注意力按通道摊销V2改进的核心不是换架构而是把注意力计算变得更高效。如果说V1是“每个通道独立算注意力权重”那V2就是“多通道共享一组注意力权重再通过分组融合恢复表达力”。分组向量注意力Group Vector AttentionGVA的做法大致是把特征通道分成G组比如特征维度是C分成4组每组C/4个通道。同一组内的通道共享一组注意力权重不同组之间用不同的注意力参数。这样注意力权重的维度从原来的C变成了G×C但计算量比逐通道注意力小得多。用生活化的方式理解V1就像一个团队里每个人都要和所有人沟通每句话都单独确认一遍意思效率低但信息丰富V2是先把团队分成几个小组小组内共享沟通策略再汇总各组意见效率大幅提升。这项改动让V2在计算效率上比V1有非常明显的提升特别是在大规模场景分割任务上。注意力机制的表达能力被分组这个操作大大增强了不同组可以关注不同的几何语义比如一组专门捕捉局部平面特征另一组捕捉边缘特征整体编码能力反而更强。3.2 分组位置编码参数从冗余到精确V2的第二个关键改进是分组位置编码Group Position EncodingGPE。V1的位置编码是用MLP直接处理相对坐标维度较高时参数冗余明显。V2把位置编码也分组处理每组位置编码对应一组注意力通道的几何偏移。位置编码不再是“一个大MLP输出所有通道的编码”而是分小组、按偏移量精确生成每个组都有自己的位置编码子网络。这样做的好处是模型能够更精细地表达局部几何信息。相对坐标在不同方向上的变化不同组可以独立学习到不同的几何响应。实际效果上就是分割边界更干净、小物体召回率更高。3.3 V2在室内大规模分割上的表现V2在自己的论文里针对SceneNet和S3DIS做了大量实验拿下了当时两个数据集上的最佳成绩。我这边复现下来的感受是V2在室内场景分割上的精度提升是一方面更重要的是训练稳定性和推理效率比V1好了太多。同样是做室内场景分割我用V1训练S3DIS时一个大场景切成小块后每个block还要跑全点注意力显存经常爆batch size只能开很小。换成V2之后同样显存可以把batch开大一倍训练时间缩短了不少精度还更高了。V2在ScanNet和S3DIS这种稠密大场景上的优势主要来自分组策略减小了注意力开销。3.4 实测心得V2与V1的训练差异我自己的训练感受是V2相对V1的收敛特性有明显变化。V1在早期训练阶段loss下降很快但后期容易出现抖动V2前期稍慢但中后期很稳最后一个阶段的IoU提升特别明显。这可能和分组设计的正则化效果有关相当于对注意力参数做了一定程度的共享约束防止过拟合。另一个体会是V2对初始学习率没有V1那么敏感。V1用稍大的学习率就容易发散V2在1e-3左右都能稳定训练这在做大规模数据实验时可以少折腾不少。4. PointTransformer V3当Transformer变得“接地气”4.1 Point-Voxel双分支既要全局又要细节先说明一下这里讨论的V3指的是后来发布的Point Transformer V3系列工作。朋友们也经常把一些变体统称为V3这里我以自己复现过的PointTransformer V3主干网络的理解来讲。V3相比V1、V2最大的变化是不再坚持纯点级别的注意力计算。它采用了point-voxel混合的思路点分支保留原始点坐标做精细的局部特征提取避免量化误差体素分支把点云量化为稀疏体素网格用3D稀疏卷积做高效的全局特征传播两个分支融合既获得了体素卷积的高效性又保留了点级别的几何精度。很直白的理解就是体素分支负责“跑得快”点分支负责“做得细”。这个设计背后对应一个工程现实大场景点云动辄上百万个点如果全部逐点计算注意力哪怕V2做了分组优化部署时依然吃力。体素化之后点的数量可能缩小一个数量级计算量大幅下降。而点分支的引入避免了纯体素方法在小物体和边界细节上的精度损失。4.2 几何感知的层级结构V3另一个核心设计是层级化的Transformer结构。它的网络骨架类似U-Net下采样获取多尺度特征上采样恢复分辨率中间通过skip connection融合多尺度信息。这里有一个细节值得反复体会PointTransformer V3中的下采样不是简单的随机采样或体素池化而是依赖几何信息做聚类/采样尽量保留点云的结构特征。每个Stage内部用窗口化的注意力处理局部邻域Stage之间用跨级别的连接融合不同分辨率的特征。这种设计让V3在高分辨率细粒度分割和低分辨率全局语义理解之间比较平衡。4.3 V3带来的工程红利V3在工程上的红利主要体现在三个方面显存占用可控。体素分支把大量计算转移到稀疏卷积上注意力只在局部的窗口或采样点上做显存压力比V1小一个档次。训练速度更快。稀疏卷积是多线程友好的而逐点注意力受KNN和Attention计算限制。体素分支的计算开销主要花在稀疏矩阵运算上现代深度学习框架对这类算子的优化比较足。部署友好。体素卷积可以比较平滑地转到TensorRT或C推理栈上纯点注意力在这方面的算子支持差了不少。需要说明的是V3也有它自己的代价量化参数体素大小、分支融合比例这些超参数变多了调参难度比V2略高一些。体素大小设置太大细节丢失设太小体素分支的效率优势又出不来。经验上做室内场景体素大小在0.02米到0.04米之间是比较常用的范围做室外自动驾驶场景需要根据雷达距离和点密度重新调整。5. Mamba点燃的点云新战局5.1 从Transformer到SSM换一种方式看待长序列最近点云圈绕不开的另一个词是Mamba。Mamba出自语言建模领域核心是一种选择性状态空间模型Selective SSM在长序列建模上做到了线性复杂度。消息传开之后很快就有人把它用到点云上。很多人第一反应是点云又不是序列Mamba怎么用这里的关键在于可以把点云按某种顺序组织成序列。比如按空间填充曲线排序或者按体素扫描顺序排序再送入Mamba块做处理。由于Mamba对位置的依赖是连续的、链式的配合适当的顺序策略可以在保持相对几何结构的同时以线性开销处理大量点。这其实挑战了“注意力是唯一合理聚合算子”的潜意识。Mamba的精髓是“用状态压缩历史信息”每个点都更新一个隐藏状态新旧信息按可学习的规则融合不需要和前面所有点两两比较。序列越长这种机制的优势越明显。5.2 PointMamba与PCM的代表思路具体到点云方向现在能看到的代表性工作有PointMamba、PCMPoint Cloud Mamba以及一些把Mamba和Transformer混合的架构。PointMamba的核心做法是把点云先降采样分组再用空间填充曲线扫描成序列然后交给Mamba骨干网络做主干的特征提取。它的优势在于推理效率特别是在点数增加到几十万甚至上百万时耗时基本呈线性增长而Transformer系列不管怎么优化注意力在大邻域里的平方复杂度还是会显现出来。PCM则采用了Mamba和Transformer结合的方式一部分层用Mamba捕捉全局长距离依赖一部分层用Transformer做局部精细建模取长补短。从这类混合架构的消融结果来看Mamba对长距离上下文建模有正面贡献局部细节还是靠注意力/卷积更稳。5.3 Transformer vs Mamba点云任务选谁从我自己的项目经验来说选择建议大概是这样的如果做的是ModelNet40分类、ShapeNetPart这种小规模点云任务TransformerV1/V2体验很好收敛快精度也高Mamba的优势体现不出来。如果做的是室内场景S3DIS/ScanNet分割V2/V3的表现依然是最稳的Mamba目前在小物体边界上还输一些。如果做的是大规模室外场景、几十万点以上的稠密点云Mamba路线的效率优势开始明显在精度差距不大的前提下推理速度可能差出好几倍。Mamba在点云上还在快速迭代老实说还没有到“全面超越Transformer”的程度但它提供了一个值得关注的效率方向。点云处理最终要解决的是“在大场景下跑得快又准”无限制堆算力堆显存不是可持续发展的路。6. 从论文到落地实操笔记与踩坑清单6.1 环境配置与数据准备跑PointTransformer系列基本环境就是PyTorch CUDA需要额外装一个高效的KNN库官方实现里常用的是torch-cluster或三方的knn_cuda算子比如GitHub上的kn-cuda或faiss。不建议自己用暴力循环实现KNN点一多速度会慢到怀疑人生。数据集方面分类任务一般用ModelNet40约1万多个CAD模型采样部件分割用ShapeNetPart16类、50个部件室内场景分割用S3DIS6个大型室内场景每场景几亿个原始点和ScanNetRGB-D重构的室内场景室外场景用SemanticKITTI或者nuScenes训练前数据预处理有个很现实的细节S3DIS每个房间的点数非常不均匀如果不做体素降采样有的训练样本点半数上百万有的才几万batch内的计算量会非常不平衡训练极不稳定。我一般先做一次0.04米的体素降采样再按固定点数随机采样比如每块20480到40960个点配合block切分。6.2 训练配置与显存控制以我复现V2在S3DIS Area 5上的经验比较稳的训练配置大概是输入点数20480block内邻域点数K16特征维度64开始逐层翻倍batch size如果是单卡12G显存建议从2开始靠梯度累积撑到8优化器AdamW初始学习率1e-3用Cosine退火调度器训练轮数120到240轮取决于epoch大小数据增强随机旋转、随机平移、随机缩放0.8到1.2这个对分割精度影响很大用V1的话把batch单独降到1都有可能OOMV2之后基本能正常训练。V3在显存上确实优势明显同样的batch下显存占用比V2低30%-40%。6.3 五个容易踩的坑第一个坑KNN搜索之后邻域索引乱序KNN返回的邻域索引是无序的这意味着如果直接沿着邻域维度做池化每个中心点邻域里数据排列顺序都不一样。有些操作比如局部归一化或者顺序敏感的MLP会因此出问题。解决办法是在邻域维度上做sort或者直接只使用对称函数max/sum平均处理。第二个坑位置编码必须使用相对坐标不少人第一次写PointTransformer都会把绝对坐标直接拼进特征里。这样做的结果是模型对平移非常敏感同一个物体移动到场景不同位置输出特征差异巨大。位置编码的输入务必是相对坐标中心点坐标减去邻域点坐标才能保证平移不变性。第三个坑训练和推理的邻域点数不一致有人训练时把K设成16推理时改成32以为“推理时多点信息更全就更好”。实际结果是精度可能掉了一截。因为模型在训练时已经适应了固定规模邻域内的局部信息测试时更换K等于人为改变了输入分布。除非做专门的邻域鲁棒性实验否则训练和推理K要保持一致。第四个坑V3体素化大小对精度的影响V3里体素大小的选择直接影响boundary的平滑度和细小物体的保留程度。调体素大小一定要同时观察训练loss和验证集IoU不要只看分类准确率。室内场景0.03附近一般是个不错的起点室外场景建议根据雷达扫描范围和点密度做下采样统计后确定。第五个坑共享MLP的批量归一化Transformer block里的MLP如果加了BatchNorm在小batch size下极容易因为batch内样本数太少导致BN统计量不稳定。实测下来PointTransformer系列用LayerNorm或者不用归一化比BatchNorm稳定得多。V1、V2原论文里也都是LayerNorm路线。6.4 推理加速的实际技巧部署到实际项目中有几个成熟的加速手段ONNX TensorRT把模型导出为ONNX再转TensorRT。PointTransformer的KNN在导出时会有困难通常要把KNN单独拆出来用C实现或者用CUDA核函数替代只把注意力块导出成engine。稀疏化裁剪V2/V3的注意力头很多实验发现剪掉部分低贡献的head精度损失在1%以内速度可能提升15%以上。混合精度推理FP16在点云任务上一般没有明显的精度损失显存占用直接减半推理速度也能上来一截。我建议先跑FP16验证精度再决定是否上INT8。KNN并行化多卡推理时KNN部分是最容易卡住的性能瓶颈用CUDA KNN替代CPU搜索能把整体延迟降一个数量级。7. 常见问题速查表问题可能原因解决方案训练时显存溢出KNN邻域过大或点数过多减小K、降低输入点数、用V2/V3替代V1分割边界粗糙体素大小过大调小体素或增加点分支权重小目标漏检严重下采样丢失细节检查下采样倍数和多尺度特征融合必要时增加细粒度上采样平移后效果变差位置编码用了绝对坐标改用相对坐标编码模型部署时KNN耗时过高KNN在GPU利用率低用CUDA KNN算子或把KNN拆到C预处理不同数据点数量差异大导致batch训练不稳定点数不平衡体素降采样后统一随机采样固定点数Mamba模型在小数据上收敛慢时序序列结构带来的优化难度降低学习率、增加warmup、考虑混合Transformer结构8. 我的选择建议与一点个人体会如果是新起一个点云项目我会这样选小规模物体级任务分类、部件分割直接上PointTransformer V2做基线省心且稳定大规模场景级任务优先试PointTransformer V3效率和精度比较平衡如果算力和显存都紧张或者需要超大规模点云的实时推理花时间去实验Mamba类方案是值得的。轮到自己做实际项目一个很深的体会是模型选型的最优解往往不在论文里而在你的数据分布和部署环境里。同样是S3DIS换了一个楼的数据最优体素大小就可能不同同样是分类任务点密度一旦稀疏V1那种细粒度的逐通道注意力反而会帮上忙。所以别人告诉你哪个模型最强都只是参考真正靠谱的做法是掌握这几个模型的设计思路然后用你自己的数据把这些模型各自跑一遍让实验数据替你做决定。最后分享一个我在调试这类模型时的小习惯每换一个模型先在验证集上做一次过拟合测试一个小数据子集训练几十个batch看训练loss能不能降到接近0。能过拟合说明模型学习和优化器设置基本正常然后才去考虑数据加载、增广、超参数这些外围问题。这个习惯帮我排除过很多“看起来是模型问题其实是数据或工程问题”的坑。文本较长阅读有收获的话可以先收藏后续有新实验我会继续在这篇下面补充。
返回列表