PointTransformerV3¶
PointTransformerV3 is a LiDAR encoder for LiDAR 3D semantic segmentation and
3D object detection. The shared component is the hierarchical PTv3 encoder
(PointTransformerV3Encoder); each task owns its head:
- Segmentation:
PTv3Seg3DDecoderHeadunpools the deepest encoder stage back to full resolution through the encoder skip chain and classifies each point. - Detection:
PTv3Det3DBEVNeckfuses the two coarsest encoder stages (PTv3Det3DFeatureFusion), scatters them onto a dense BEV canvas at the detection-head resolution, and feeds aTransFusionHead.
The models read single lidar frames, every point as (x, y, z, intensity). The voxel feature
encoder turns each voxel into the mean x, y, z and intensity of its points, 4 features per voxel,
and the detection heads predict no velocity. The 6 cm teacher reads the current frame and one
past sweep, every point with a time lag. Its voxel feature encoder places each voxel at its
current frame points and describes the past and future points relative to that position, 17
features per voxel, and its detection head predicts velocity. Segmentation is scored on the
current frame points only.
Because the detection branch taps the encoder only, finetuning the segmentation head with a frozen encoder cannot change detection outputs - the segmentation and detection checkpoints of a joint model stay independently finetunable and stackable at deploy time.
The training path uses flash-attn for serialized attention. The export path
automatically disables flash attention and falls back to the standard attention
implementation so ONNX export remains supported.
Summary¶
| Property | Value |
|---|---|
| Task | 3D semantic segmentation, 3D object detection |
| Modality | LiDAR |
| Input | Single point cloud of x, y, z and intensity, the 6 cm teacher adds one past sweep with a time lag |
| Output | Point-wise semantic labels or 3D boxes/scores/classes |
| Architecture | PointTransformerV3 with sparse convolution stem and task heads |
| Datasets | nuScenes, T4Dataset |
Available Configurations¶
| Config Name | Task | Dataset | Head | Range | Purpose |
|---|---|---|---|---|---|
segmentation3d/ptv3/nuscenes/voxel005_b16_50e_nuscenes_51m |
segmentation3d | nuScenes | Seg decoder | 51 m | nuScenes segmentation |
segmentation3d/ptv3/t4dataset/base_voxel012_122m |
segmentation3d | T4Dataset | Seg decoder | 122 m | T4Dataset segmentation |
detection3d/ptv3/nuscenes/voxel005_b16_30e_nuscenes_51m |
detection3d | nuScenes | TransFusion | 51 m | nuScenes detection |
detection3d/ptv3/t4dataset/base_voxel012_122m |
detection3d | T4Dataset | TransFusion | 122 m | T4Dataset detection |
multi/ptv3/nuscenes/voxel005_b16_100e_nuscenes_51m |
segmentation3d + detection3d | nuScenes | TransFusion | 51 m | Joint segmentation + detection |
multi/ptv3/t4dataset/base_voxel012_122m |
segmentation3d + detection3d | T4Dataset | TransFusion | 122 m | Joint segmentation + detection |
The T4Dataset rows are bases. They declare the classes the model trains and require the taxonomy that folds the labels of the database onto them, so a T4Dataset experiment that binds one lives in an external config root, see Configuration.
Training¶
autoware-ml train --config-name segmentation3d/ptv3/nuscenes/voxel005_b16_50e_nuscenes_51m
autoware-ml train --config-name detection3d/ptv3/nuscenes/voxel005_b16_30e_nuscenes_51m
autoware-ml train --config-name multi/ptv3/nuscenes/voxel005_b16_100e_nuscenes_51m
For a pipeline validation run:
autoware-ml train \
--config-name segmentation3d/ptv3/nuscenes/voxel005_b16_50e_nuscenes_51m \
+trainer.fast_dev_run=true
Mixed precision¶
spconv has no autocast support, so under trainer.precision=16-mixed its
convolutions run in fp32. If t4sparse is installed (see
Installation), sparse convolutions run
16-bit t4sparse kernels under autocast instead. Checkpoints are interchangeable.
The two libraries' indice_key caches are incompatible, so disable autocast
around whole stages only.
Evaluation¶
autoware-ml test \
--config-name segmentation3d/ptv3/nuscenes/voxel005_b16_50e_nuscenes_51m \
--weights mlruns/ptv3_seg3d/NuScenesDataset-base-v1.0.0/nuscenes/voxel005_b16_50e_nuscenes_51m/<run_id>/artifacts/checkpoints/best.ckpt
autoware-ml test \
--config-name detection3d/ptv3/nuscenes/voxel005_b16_30e_nuscenes_51m \
--weights mlruns/ptv3/NuScenesDataset-base-v1.0.0/nuscenes/voxel005_b16_30e_nuscenes_51m/<run_id>/artifacts/checkpoints/best.ckpt
Deployment¶
PointTransformerV3 ONNX export is available. The generic TensorRT stage remains disabled in Autoware-ML because PTv3 requires a runtime with matching sparse convolution plugins.
autoware-ml deploy \
--config-name segmentation3d/ptv3/nuscenes/voxel005_b16_50e_nuscenes_51m \
--weights mlruns/ptv3_seg3d/NuScenesDataset-base-v1.0.0/nuscenes/voxel005_b16_50e_nuscenes_51m/<run_id>/artifacts/checkpoints/best.ckpt \
deploy.tensorrt.enabled=false
autoware-ml deploy \
--config-name detection3d/ptv3/nuscenes/voxel005_b16_30e_nuscenes_51m \
--weights mlruns/ptv3/NuScenesDataset-base-v1.0.0/nuscenes/voxel005_b16_30e_nuscenes_51m/<run_id>/artifacts/checkpoints/best.ckpt \
deploy.tensorrt.enabled=false
The deployment command switches PTv3 attention blocks into non-flash export mode automatically.
Every shipped detection config, including the LitePT ones that inherit from
multi/ptv3, exports the detection head with TensorRT-fusable attention. Bf16 is
required for numerically stable operator fusion, so the configs pair the head flag
with an fp16 precision for the detection-head module:
model:
bbox_head:
use_bf16_cross_attention: true
deploy:
onnx:
modules:
ptv3_det3d_head:
precision: fp16
Both settings are required to enable the fused path, and the resulting engine requires an SM80 or newer GPU. Export refuses to run with only one of them set. To fall back to the stable but slower non-fused attention path, disable both:
autoware-ml deploy \
--config-name detection3d/ptv3/nuscenes/voxel005_b16_30e_nuscenes_51m \
--weights <checkpoint> \
model.bbox_head.use_bf16_cross_attention=false \
deploy.onnx.modules.ptv3_det3d_head.precision=fp32
The exported ONNX model returns both pred_labels and pred_probs. The
probability output is produced by a final softmax layer, while training and
evaluation continue to use logits inside the Lightning model.
Deployment uses an explicit PTv3 export wrapper and a copied encoder, so the training model is not mutated when export-only sparse-convolution and serialization settings are applied.
The height channel of the detection head's bbox_pred output is the z of the
box gravity center. Earlier releases regressed the top face (z + 0.5 * h), and
the autoware_ptv3 node still undoes that shift with z = height - box_h * 0.5
in detection3d_postprocess.cu. A model trained with this release therefore
needs the node updated to z = height (no half-height subtraction) before it is
deployed. Models trained before this release keep working with the current node.
ONNX Preprocessing Contract¶
The exported PTv3 encoder ONNX expects all pooling-shape metadata to be
generated by preprocessing outside the engine. N_0 is the input voxel count, P the
number of points a voxel keeps (max_num_points of the data preprocessing), and O is the
number of serialization orders.
| Base input | Shape | Meaning |
|---|---|---|
voxels |
[N_0, P, C] |
Points of every voxel, zero padded. C = 4 with (x, y, z, intensity) for the single frame models, C = 5 with (x, y, z, intensity, time_lag) for the 6 cm teacher. time_lag is in seconds, 0 for the current frame, positive for a past sweep and negative for a future one. |
num_points_per_voxel |
[N_0] |
Number of points every voxel holds. |
grid_coord |
[N_0, 3] |
Integer voxel coordinates. |
patch_order |
[O, Npad_0] |
The order padded to whole attention windows (see below). |
serialized_inverse |
[O, N_0] |
Inverse of the serialization order per curve (argsort of the codes). |
Npad_k = ceil(N_k / patch_size_k) * patch_size_k is the padded length of level k. The
fill is described in Attention window fill at export;
the runtime must build patch_order with the per-level patch_sizes stamped into the
encoder's ONNX metadata.
For every encoder pooling stage i, with input voxel count N_i and pooled
output voxel count M_i, preprocessing also provides:
| Pooling metadata | Shape | Meaning |
|---|---|---|
serialized_pooling_i_indices |
[N_i] |
ONNX Gather indices grouping features before CSR reduction. |
serialized_pooling_i_indptr |
[M_i + 1] |
CSR row pointer consumed by autoware::SegmentCSR. |
serialized_pooling_i_cluster |
[N_i] |
Input voxel to pooled voxel id mapping for unpooling. |
serialized_pooling_i_head_indices |
[M_i] |
Representative input voxel for each pooled voxel. |
serialized_pooling_i_grid_coord |
[M_i, 3] |
Integer coordinates of pooled voxels. |
serialized_pooling_i_patch_order |
[O, Npad_{i+1}] |
The pooled level's (level i + 1) order padded to whole attention windows. |
serialized_pooling_i_serialized_inverse |
[O, M_i] |
Inverse serialization order for pooled voxels. |
Because preprocessing resolves every pooling shape ahead of time, the exported
graph contains no data-dependent pooling shape discovery. Pooled feature
reduction is implemented with native ONNX Gather and the
autoware::SegmentCSR plugin.
Attention window fill at export¶
Serialized attention runs on fixed-size windows of K = patch_size tokens, so a
sample of n voxels needs its last window filled unless n is a multiple of K:
n % K == 0- the windows are exact, nothing to fill.- otherwise,
n > K- the last window borrows tokens from the preceding one to reachK, which is what training does. - otherwise,
n < K- there is nothing to borrow from, so the sample's own tokens are cycled round-robin to equalize their weight in the softmax as far as possible.
Dynamic window sizes and masking are both awkward to express in TensorRT without
a performance penalty, hence this fill.
Preprocessing computes the fill into patch_order with build_patch_order
(encoders/ptv3.py), which the deployed runtime reimplements.
Split-export module contract¶
The split export produces one graph per deploy.onnx.modules entry:
encoder- the encoder; outputs per-stage featurespoint_feat_0…point_feat_{S-1}(finest to deepest,Sencoder stages). It consumes the per-stage pooling metadata exceptserialized_pooling_i_cluster, which only drives head-side unpooling and enters the head graphs aspooling_cluster_iinstead.seg3d_head- consumes all per-stage features plus the per-poolingpooling_cluster_itensors (theserialized_pooling_i_clustermetadata) and outputspred_labels/pred_probs. For every decoder stageiwith attention blocks (dec_depths[i] > 0) the graph additionally consumes that stage's serialization metadata, under the same names as the encoder inputs:serialized_pooling_{i-1}_patch_order,serialized_pooling_{i-1}_serialized_inverseandserialized_pooling_{i-1}_grid_coord(stage 0 instead takes the basepatch_order,serialized_inverseandgrid_coord). The rule is implemented once inseg3d_head_export_input_namesand must be mirrored by deployment consumers from the artifact'sdec_depths.det3d_head- consumespoint_feat_{S-2},point_feat_{S-1},pooling_cluster_{S-2}, andpoint_grid_coord_{S-2}and outputs the detection head tensors.
Implementation¶
| Path | Description |
|---|---|
autoware_ml/models/segmentation3d/ptv3.py |
PTv3 Lightning model wrapper |
autoware_ml/models/segmentation3d/heads/ptv3.py |
PTv3 segmentation decoder head |
autoware_ml/models/detection3d/ptv3.py |
PTv3 BEV neck and detection model wrapper |
autoware_ml/models/detection3d/heads/transfusions/transfusion_head.py |
TransFusion detection head |
autoware_ml/models/segmentation3d/encoders/ptv3.py |
Reusable PTv3 encoder components |
autoware_ml/models/segmentation3d/encoders/voxel.py |
Voxel feature encoders of single frames and sweeps |
autoware_ml/utils/point_cloud/ |
Shared point-cloud utilities and serialization |
autoware_ml/ops/segment/segment_csr.py |
Segment reduction export operator |
autoware_ml/losses/segmentation3d/ |
Segmentation losses used by PTv3 |
autoware_ml/datamodule/t4dataset/dataset.py |
T4Dataset records as a dataset |
autoware_ml/datamodule/nuscenes/dataset.py |
nuScenes dataset |
autoware_ml/datamodule/t4dataset/segmentation3d.py |
Semantic masks of a T4Dataset record |
autoware_ml/datamodule/common/detection3d.py |
3D boxes of a record |
autoware_ml/transforms/point_cloud/ |
Shared point-cloud transforms used by PTv3 |
autoware_ml/configs/tasks/segmentation3d/ptv3/ |
Segmentation experiment configurations |
autoware_ml/configs/tasks/detection3d/ptv3/ |
Detection experiment configurations |
Acknowledgment¶
The Autoware-ML PointTransformerV3 implementation was ported from the official PointTransformerV3 project by Pointcept.
- Repository: https://github.com/Pointcept/PointTransformerV3
- License: MIT
- Paper: Wu, Xiaoyang, et al. "Point Transformer V3: Simpler, Faster, Stronger." CVPR, 2024.