functional
Functional API of the losses: the tensor function of every themed module, re-exported here in the spirit of torch.nn.functional. Tensors in, tensors out, no state, no reduction unless the docstring says so.
Functions:
-
chamfer_distanceβSymmetric Chamfer distance between packed point sets.
-
corner_lossβPer-box mean smooth-\(L_1\) distance between the eight corners of two box sets, robust to the heading flip.
-
gaussian_focal_lossβPenalty-reduced focal loss over a Gaussian heatmap, normalized by the number of peaks.
-
one_hot_foregroundβOne-hot encode per-row class labels, dropping the background column.
-
poly1_focal_lossβPoly-1 focal loss between per-class logits and binary targets (no reduction).
-
sigmoid_focal_lossβSigmoid focal loss between per-class logits and binary targets (no reduction).
-
kpconv_deform_regularizerβRegularize the deformed kernel points of every deformable
KPConvinmodule. -
lovasz_softmaxβMulti-class LovΓ‘sz-Softmax loss over per-point class probabilities.
-
hungarian_matchβOne-to-one assignment of predictions to targets minimizing the total cost (Hungarian algorithm).
-
hungarian_match_batchedβOne-to-one assignment of every scene's predictions to its targets, with a single device transfer.
-
tnet_orthogonality_regularizerβPull the transforms predicted by every T-Net in
moduletowards an orthogonal matrix.
chamfer_distance [source] ΒΆ
chamfer_distance(
pred: Tensor,
target: Tensor,
*,
pred_batch: Optional[Tensor] = None,
target_batch: Optional[Tensor] = None,
norm: Literal["l1", "l2"] = "l2",
) -> Tensor
Symmetric Chamfer distance between packed point sets.
Set-to-set reconstruction objective introduced for point cloud generation in A Point Set Generation Network for 3D Object Reconstruction from a Single Image (Fan et al., 2017) and standard for masked point modeling pretraining. Every point is matched to its nearest neighbor in the other set of the same index (its group, its scene), and the squared euclidean distances are averaged over all points:
The "l2" variant sums the two directed means of squared distances (no square root, no halving); the "l1" variant averages the two directed means of euclidean distances. Both follow the reference pretraining convention, so losses are comparable with published values.
The nearest neighbors come from the sided_distance kernel of kaolin when it is installed and the points are on CUDA, otherwise from the kNN kernel of torch_geometric (pyg-lib); either way without autograd, and only the matched pairs are differentiated, so the memory grows with \(N + M\) rather than \(N \cdot M\) and whole clouds fit. Without either kernel the search falls back to the dense distance matrix.
Parameters:
-
pred(Tensor) βPredicted points of every set, packed, shape \((N, 3)\).
-
target(Tensor) βTarget points of every set, packed, shape \((M, 3)\).
-
pred_batch(Optional[Tensor], default:None) βSet index of every predicted point (sorted), shape \((N,)\);
Nonefor a single set. -
target_batch(Optional[Tensor], default:None) βSet index of every target point (sorted), shape \((M,)\);
Nonefor a single set. -
norm(Literal['l1', 'l2'], default:'l2') βDistance variant,
"l1"(euclidean) or"l2"(squared euclidean).
Returns:
-
TensorβScalar Chamfer distance averaged over all points.
Shape
- pred: \((N, 3)\)
- target: \((M, 3)\)
- pred_batch: \((N,)\)
- target_batch: \((M,)\)
- output: scalar
Example
import torch
from torch_pointcloud.losses import chamfer_distance
pred = torch.randn(64 * 32, 3, requires_grad=True)
target = torch.randn(64 * 32, 3)
batch = torch.arange(64).repeat_interleave(32)
loss = chamfer_distance(pred, target, pred_batch=batch, target_batch=batch)
loss.backward()
print(loss.shape)
corner_loss [source] ΒΆ
Per-box mean smooth-\(L_1\) distance between the eight corners of two box sets, robust to the heading flip.
The corner regularization of PointRCNN: 3D Object Proposal Generation and Detection from Point Cloud (Shi et al., 2019): each predicted corner is compared with the matching corner of the ground-truth box and of that box rotated by \(\pi\), and the closer of the two distances is penalized, so a heading off by half a turn is not punished as a position error.
Parameters:
-
pred_boxes(Tensor) βPredicted boxes \((c_x, c_y, c_z, d_x, d_y, d_z, \theta)\), shape \((N, 7)\).
-
gt_boxes(Tensor) βMatched ground-truth boxes, shape \((N, 7)\).
-
beta(float, default:1.0) βSmooth-\(L_1\) transition point.
Returns:
-
TensorβThe per-box loss, shape \((N,)\).
Shape
- pred_boxes: \((N, 7)\)
- gt_boxes: \((N, 7)\)
- output: \((N,)\)
gaussian_focal_loss [source] ΒΆ
gaussian_focal_loss(
pred: Tensor,
target: Tensor,
*,
alpha: float = 2.0,
gamma: float = 4.0,
eps: float = 0.0001,
) -> Tensor
Penalty-reduced focal loss over a Gaussian heatmap, normalized by the number of peaks.
The heatmap objective of Objects as Points (Zhou et al., 2019), used by the center-based detection heads (CenterPoint, VoxelNeXt, TransFusion). Cells whose target is exactly \(1\) are positives with the \((1 - p)^\alpha \log p\) term; every other cell is a soft negative whose \(p^\alpha \log(1 - p)\) term is down-weighted by \((1 - y)^\gamma\), so cells near a peak barely count. The sum is divided by the number of positives (or left as is when there is none).
Parameters:
-
pred(Tensor) βPredicted probabilities (post-sigmoid) of any shape; clamped to \([\varepsilon, 1 - \varepsilon]\).
-
target(Tensor) βGaussian heatmap target of the same shape, values in \([0, 1]\).
-
alpha(float, default:2.0) βFocusing exponent on the prediction.
-
gamma(float, default:4.0) βDown-weighting exponent on the soft negatives.
-
eps(float, default:0.0001) βClamp keeping the logarithms finite.
Returns:
-
TensorβThe scalar loss.
Shape
- pred: \((\ldots)\)
- target: \((\ldots)\)
- output: scalar
one_hot_foreground [source] ΒΆ
One-hot encode per-row class labels, dropping the background column.
Ignored (\(-1\)) and background (\(0\)) rows map to an all-zero row; a foreground row with label \(\ell \ge 1\) maps to a one-hot row on class \(\ell - 1\). The target format of sigmoid_focal_loss for the anchor and point heads.
Parameters:
-
labels(Tensor) βClass labels (\(-1\) ignore, \(0\) background, \(\ge 1\) foreground), shape \((\ldots)\).
-
num_classes(int) βNumber of foreground classes \(C\).
Returns:
-
TensorβOne-hot foreground targets, shape \((\ldots, C)\).
Shape
- labels: \((\ldots)\)
- output: \((\ldots, C)\)
poly1_focal_loss [source] ΒΆ
poly1_focal_loss(
logits: Tensor,
targets: Tensor,
*,
epsilon: float = 1.0,
alpha: Optional[float] = 0.25,
gamma: float = 2.0,
) -> Tensor
Poly-1 focal loss between per-class logits and binary targets (no reduction).
The focal loss plus its first Poly-1 correction term of PolyLoss: A Polynomial Expansion Perspective of Classification Loss Functions (Leng et al., 2022), with \(p\) the sigmoid of the logit, \(p_t = p\) on the positive entries and \(1 - p\) elsewhere,
Parameters:
-
logits(Tensor) βPer-class logits, shape \((\ldots, C)\).
-
targets(Tensor) βBinary (one-hot) targets of the same shape.
-
epsilon(float, default:1.0) βWeight \(\epsilon\) of the Poly-1 term.
-
alpha(Optional[float], default:0.25) βPositive/negative balance \(\alpha\);
Nonedisables it. -
gamma(float, default:2.0) βFocusing exponent \(\gamma\).
Returns:
-
TensorβThe per-element loss, shape \((\ldots, C)\).
Shape
- logits: \((\ldots, C)\)
- targets: \((\ldots, C)\)
- output: \((\ldots, C)\)
sigmoid_focal_loss [source] ΒΆ
sigmoid_focal_loss(
logits: Tensor,
targets: Tensor,
weights: Optional[Tensor] = None,
*,
alpha: float = 0.25,
gamma: float = 2.0,
) -> Tensor
Sigmoid focal loss between per-class logits and binary targets (no reduction).
The classification term of Focal Loss for Dense Object Detection (Lin et al., 2017), shared by the anchor, point and query heads: binary cross-entropy on the sigmoid of each logit, scaled by \(\alpha_t (1 - p_t)^\gamma\) so confident predictions contribute little. Same math as torchvision.ops.sigmoid_focal_loss, plus an optional per-row weight.
Parameters:
-
logits(Tensor) βPer-class logits, shape \((\ldots, C)\).
-
targets(Tensor) βBinary (one-hot) targets of the same shape.
-
weights(Optional[Tensor], default:None) βOptional weight of every row, shape \((\ldots)\), broadcast over the class dimension.
-
alpha(float, default:0.25) βPositive/negative balance \(\alpha\).
-
gamma(float, default:2.0) βFocusing exponent \(\gamma\).
Returns:
-
TensorβThe weighted per-element loss, shape \((\ldots, C)\).
Shape
- logits: \((\ldots, C)\)
- targets: \((\ldots, C)\)
- weights: \((\ldots)\)
- output: \((\ldots, C)\)
kpconv_deform_regularizer [source] ΒΆ
kpconv_deform_regularizer(
module: Module,
fitting_power: float = 1.0,
repulse_extent: float = 1.0,
) -> Tensor
Regularize the deformed kernel points of every deformable KPConv in module.
The point-to-point regularizer of KPConv: Flexible and Deformable Convolution for Point Clouds (Thomas et al., 2019): a fitting term pulls every deformed kernel point towards its closest input point, a repulsive term keeps the kernel points of one location further apart than repulse_extent. Both read the statistics the layers keep from their last forward pass (running_min_d2, running_deformed_kernel), so call it after the forward and before the backward of the same batch. Distances are expressed in units of each layer's kp_sigma.
Parameters:
-
module(Module) βModel holding the
KPConvlayers. -
fitting_power(float, default:1.0) βWeight of the whole term.
-
repulse_extent(float, default:1.0) βDistance, in units of
kp_sigma, below which kernel points repel each other.
Returns:
-
TensorβA scalar,
fitting_power * (2 * fitting + repulsive)summed over the deformable layers, zero when -
Tensorβmodulehas none.
Example
>>> import torch
>>> from torch_pointcloud.layers import KPConv
>>> from torch_pointcloud.losses import kpconv_deform_regularizer
>>> conv = KPConv(spatial_dim=3, in_channels=4, out_channels=8, kernel_size=15, kp_radius=1.0, kp_sigma=1.0, deformable=True)
>>> pos = torch.rand(32, 3)
>>> edge_index = torch.stack([torch.arange(32).repeat_interleave(4), torch.randint(0, 32, (128,))])
>>> out = conv(torch.randn(32, 4), pos, edge_index)
>>> kpconv_deform_regularizer(conv).shape
torch.Size([])
lovasz_softmax [source] ΒΆ
lovasz_softmax(
probas: Tensor,
labels: Tensor,
*,
classes: Literal["present", "all"] = "present",
ignore_index: int = -1,
) -> Tensor
Multi-class LovΓ‘sz-Softmax loss over per-point class probabilities.
The smooth surrogate of the mean-IoU objective of The LovΓ‘sz-Softmax loss: A tractable surrogate for the optimization of the intersection-over-union measure in neural networks (Berman et al., 2018); the function form of LovaszLoss, which takes logits.
Parameters:
-
probas(Tensor) βPer-point class probabilities (post-softmax), shape \((N, C)\).
-
labels(Tensor) βPer-point ground-truth labels, shape \((N,)\).
-
classes(Literal['present', 'all'], default:'present') β"present"averages only classes present inlabels;"all"averages every class. -
ignore_index(int, default:-1) βLabel value excluded from the loss.
Returns:
-
TensorβThe scalar loss (zero when no point or no class contributes).
Shape
- probas: \((N, C)\)
- labels: \((N,)\)
- output: scalar
hungarian_match [source] ΒΆ
One-to-one assignment of predictions to targets minimizing the total cost (Hungarian algorithm).
The matcher of the set-prediction detectors (3DETR, TransFusion): every target is matched to exactly one prediction and the sum of the matched costs is minimal. The cost matrix is built by the caller (e.g. a weighted sum of a classification, a center-distance and an IoU term) and must be finite.
Parameters:
-
cost(Tensor) βPairwise cost of every prediction / target pair, shape \((Q, M)\).
Returns:
-
TensorβA tuple
(pred_indices, target_indices)of long tensors oncost.device, each of length -
Tensorβ\(\min(Q, M)\), such that
pred_indices[i]is matched totarget_indices[i]; both are empty when -
Tuple[Tensor, Tensor]βeither side is.
Shape
- cost: \((Q, M)\)
- pred_indices: \((\min(Q, M),)\)
- target_indices: \((\min(Q, M),)\)
hungarian_match_batched [source] ΒΆ
One-to-one assignment of every scene's predictions to its targets, with a single device transfer.
The batched form of hungarian_match for a padded cost tensor: scene \(i\) uses the first num_targets[i] target columns of cost[i]. The whole tensor is moved to the CPU once and every scene is solved there, so a loop over scenes (and decoder layers, when they are stacked along the batch dimension) costs one synchronization instead of one per scene.
Parameters:
-
cost(Tensor) βPairwise costs, shape \((N, Q, M_\max)\); the columns beyond a scene's target count are ignored and may hold anything finite or not.
-
num_targets(Sequence[int]) βNumber of valid target columns of each scene, length \(N\).
Returns:
-
TensorβThe matched target index of every prediction, shape \((N, Q)\) long on
cost.device, \(-1\) where the -
Tensorβprediction is unmatched.
Shape
- cost: \((N, Q, M_\max)\)
- output: \((N, Q)\)
tnet_orthogonality_regularizer [source] ΒΆ
Pull the transforms predicted by every T-Net in module towards an orthogonal matrix.
The feature-transform regularization of PointNet: Deep Learning on Point Sets for 3D Classification and Segmentation (Qi et al., 2017), \(\lVert I - A A^\top \rVert_F\) averaged over the samples of the batch and summed over the T-Nets found in module. Pass the T-Net (or the sub-module) to regularize, e.g. a PointNet's feature transform model.ftnet to leave its input transform free, as the PointNet paper does.
The matrices are read from the running_transform the layers keep from their last forward pass, so call it after the forward and before the backward of the same batch.
Parameters:
-
module(Module) βA
TNet/DynamicTNet, or a module containing some.
Returns:
-
TensorβThe scalar regularizer (zero when
moduleholds no T-Net).
Raises:
-
RuntimeErrorβIf a T-Net has no stored transform (no forward pass yet, or
track_running_stats=False).