Losses¶
--set <stage>.<term>_loss=20 optionsEvery loss term of a stage is a small config node of its own and is swapped on its own, for
example --set head.score_loss=quality-focal. A loss fits only the kinds of term it accepts;
HGGD computes its losses inside the detector, so this slot is not HGGD's.
Use it¶
grasppanda compose graspnet_baseline/graspnet-baseline_pointnet2_g1b-realsense_18e \
--set head.angle_loss=focal -o graspnet-baseline_focal.yaml
grasppanda compose graspnet_baseline/graspnet-baseline_pointnet2_g1b-realsense_18e --list loss
grasppanda compose gsnet/gsnet_sunet14_g1b-realsense_10e \
--set proposal.objectness_loss=focal -o gsnet_focal.yaml
grasppanda compose gsnet/gsnet_sunet14_g1b-realsense_10e --list loss
grasppanda compose scale_balanced_grasp/sbg_pointnet2-transformer_g1b-realsense_18e \
--set head.angle_loss=focal -o scale-balanced-grasp_focal.yaml
grasppanda compose scale_balanced_grasp/sbg_pointnet2-transformer_g1b-realsense_18e --list loss
grasppanda compose economicgrasp/economicgrasp_sunet14_g1b-realsense_10e \
--set head.score_loss=focal -o economicgrasp_focal.yaml
grasppanda compose economicgrasp/economicgrasp_sunet14_g1b-realsense_10e --list loss
grasppanda compose finegrasp/finegrasp_sunet14_g1b-realsense_10e \
--set head.score_loss=focal -o finegrasp_focal.yaml
grasppanda compose finegrasp/finegrasp_sunet14_g1b-realsense_10e --list loss
The first command writes a checked config; the second lists every option of the slot under that method, with what was measured. Then grasppanda probe <file> tries the config on real frames and grasppanda train <file> trains it (Swap a component). Each method page lists the same: GraspNet-baseline · GSNet · Scale-Balanced-Grasp · EconomicGrasp · FineGrasp.
The left side of --set is <stage>.<term>, as the table of terms below the options lists it;
the right side is a preset or a component type (--set head.width_loss=Huber builds it with its
defaults). A preset carries no weight: compose keeps the weight of the loss it replaces and says
so.
Options¶
A probe shows that a combination trains on real frames of GraspNet-1Billion, not how good it is. Accuracy is claimed only for a method trained and evaluated here.
What the columns say, and who is left out
- Runs: out of the methods the option is a swap under, those under which its probe trained on real frames without error. A method that ships the option is named own and not counted; a method still undecided is counted and named. Measured on 20 training iterations on 8 RealSense frames of GraspNet-1Billion (one scene), seed 0, one run per cell; nothing was measured on GraspClutter6D or on Kinect frames.
- Trains like shipped: out of the methods under which the swap ran, those under which every comparable loss term ended within the method's tolerance of the component it ships, with nothing rising; a method left out is named with why. Measured on 250 iterations on 8 RealSense frames of GraspNet-1Billion (one scene), seed 0, at a constant learning rate (FineGrasp: its own warm-up), beside the method as shipped trained the same way twice.
- How we measure defines every word of these columns.
Who is left out, and why:
ghm-c, trains like shipped: worse under GraspNet-baseline, GSNet, Scale-Balanced-Grasp, EconomicGrasp; diverging under FineGrasp.distribution-focal, runs: fits only the width term of the head bundledecoupled-grid-bins; measured with it.
The loss terms of every method, and their kinds
class: (N, C) logits against (N,) class indices.unit: a prediction and a target of equal shape, the target a quality in [0, 1].value: a prediction and a target of equal shape, the target an unbounded quantity.bins: (N, C) logits over bins against (N,) fractional bin positions.
| Method | Term and its kind |
|---|---|
| GraspNet-baseline | view.objectness_loss (class), view.view_loss (value), head.score_loss (value), head.angle_loss (class), head.width_loss (value), head.tolerance_loss (value) |
| GSNet | proposal.objectness_loss (class), proposal.graspness_loss (unit), view.loss (unit), head.score_loss (unit), head.width_loss (value) |
| Scale-Balanced-Grasp | view.objectness_loss (class), view.view_loss (value), head.score_loss (value), head.angle_loss (class), head.width_loss (value), head.tolerance_loss (value) |
| EconomicGrasp | proposal.objectness_loss (class), proposal.graspness_loss (unit), view.loss (unit), head.angle_loss (class), head.depth_loss (class), head.score_loss (class), head.width_loss (value) |
| FineGrasp | proposal.objectness_loss (class), proposal.graspness_loss (unit), view.loss (unit), head.angle_loss (class), head.depth_loss (class), head.score_loss (class), head.width_loss (value) |
Choosing¶
- Objectness (
class, two classes, many easy points):focal(tryalpha: -1first),softmax-focal,class-balanced,ohem, or the set lossesdiceandlovasz-softmax. - Angle, depth and quality classes (
class, classes exclude each other):softmax-focal,label-smoothing,poly1,class-balanced,ohem. - Graspness, view scores, score grids (
unit):quality-focal,varifocal,ghm-candbcetrain a logit;balanced-l1,huber,ghm-r,charbonnier,cauchyandohem-smooth-l1keep the output a value. - Widths, tolerances, log-friction scores (
value): the value losses above; set their knee (delta,beta,mu) in the units of the target. - Balance the terms against each other:
uncertainty-weightingon every term that takes part.
Details¶
Input and output of a loss
class Loss(nn.Module):
def forward(self, prediction, target, mask=None, weights=None) -> Tensor # weight x mean over the supervised elements
A stage declares the kind of every loss term it has, a loss the kinds it accepts, and
grasppanda compose refuses a loss in a term of another kind, naming the losses that fit.
Two more attributes of a loss matter:
prediction:valueorlogit. A loss that trains the output of aunitterm as a logit (QualityFocal,Varifocal,GHMC,FocalLoss,BinaryCrossEntropy) changes what the raw output means; the stages read it through the sigmoid where they consume it.applies_weights: false for a loss that scores the supervised set as a whole (DiceLoss,LovaszSoftmaxLoss). It is refused in a term that receives a weight per seed from the assigner.
grasppanda components <Loss> prints both and the accepted kinds.
What compose writes
For --set head.score_loss=quality-focal, the composed config holds the new node with the
weight of the loss it replaced:
model:
head:
score_loss:
type: QualityFocal
beta: 2.0 # exponent of |target - sigmoid(prediction)|
weight: 15.0 # kept from the SmoothL1 it replaces: re-tune
By hand, --opts model.head.score_loss.type=FocalLoss on any command that takes --opts
changes the type and keeps the other keys of the node, so it works only when the new loss
has the options of the old one. Otherwise replace the whole node in a YAML file.
Wrappers: mining, class balance, multi-task weighting
TopK, ClassBalanced and UncertaintyWeighted take another loss as loss:.
model:
proposal:
objectness_loss:
type: TopK
fraction: 0.25 # share of the supervised elements that is kept
loss: {type: FocalLoss, weight: 1.0, alpha: -1, gamma: 2.0}
uncertainty-weighting is a preset without a loss of its own: compose wraps the loss that
is in the term, with its weight. A term that is not wrapped keeps its fixed weight. The
learned value is the parameter <stage>.<term>.log_variance; exclude it from weight decay.
Wrapped terms, and so the total loss, can become negative.
Sources and licences
| Loss | Paper | Code |
|---|---|---|
focal |
Lin et al., ICCV 2017, arXiv 1708.02002 | bridge to torchvision.ops.sigmoid_focal_loss (BSD-3-Clause) |
softmax-focal, dice, lovasz-softmax, charbonnier, cauchy |
focal loss; V-Net (arXiv 1606.04797); Berman et al., CVPR 2018; Barron, CVPR 2019 | bridges to kornia.losses (Apache-2.0) |
quality-focal, distribution-focal, varifocal, ghm-c, ghm-r, balanced-l1 |
Generalized Focal Loss (NeurIPS 2020), VarifocalNet (CVPR 2021), GHM (AAAI 2019), Libra R-CNN (CVPR 2019) | adapted from open-mmlab/mmdetection @ cfd5d3a (Apache-2.0) |
huber, bce, label-smoothing |
—; —; Szegedy et al., CVPR 2016 | PyTorch |
poly1 |
PolyLoss (arXiv 2204.12511) | the Poly-1 formula on PyTorch's cross-entropy, written here |
ohem, ohem-smooth-l1 |
online hard example mining (Shrivastava et al., CVPR 2016) | written here (a topk over the penalties) |
class-balanced |
Cui et al., CVPR 2019 | the weight formula of the paper, written here |
uncertainty-weighting |
Kendall et al., CVPR 2018 | the formula as in the UW weighting of LibMTL (MIT), written here |
No loss has weights. Without its library a config still loads; building the model raises an error that names the extra.
Pitfalls met while building this
-
A loss in the wrong kind of term is refused, with the alternatives, for example a focal loss on a width (
--set head.width_loss=focalunder GSNet):✗ assigner · head [structural]: SWADHead.width_loss is a `value` term (a prediction and a target of equal shape, the target an unbounded quantity), but FocalLoss fits `class` or `unit` terms. Losses for a `value` term: BalancedL1, GHMR, Huber, L1, MSE, RobustLoss, SmoothL1, TopK, UncertaintyWeighted. -
The scores of the GraspNet-baseline family are not qualities in [0, 1]. The score and view targets of
OperationHeadandObjectnessViewStageare log-friction scores up to ln 10, so they arevalueterms and the sigmoid losses are refused there. - Weights are kept, scales are not. A focal term is much smaller than the Smooth-L1 or
cross-entropy it replaces; compare the logged
loss/...values of both runs before trusting a weight. - GHM with
momentum > 0keeps running counts as a buffer, saved with the checkpoint. - Adding a constructor option to a loss the shipped configs use changes their config
hash, and with it every measured record. Label smoothing is therefore a class of its own
(
LabelSmoothingCrossEntropy), andCrossEntropykeeps its constructor.
Not wrapped
| Candidate | Why not |
|---|---|
| Gradient surgery between terms (PCGrad, Jacobian descent) | needs one backward pass per term inside the training step: a trainer hook, not a loss. |
| Ranking losses (allRank, torchsort) | a loss over the order of the grasps of a scene needs frame boundaries a loss does not see. |
| Ordinal regression of the quality classes (CORAL) | needs another output layer in EconomicHead: a new term kind and a head option. |
| Label and feature distribution smoothing for imbalanced regression | needs the label statistics of the training set per term. |
| Rotated-box losses (mmrotate) | they compare oriented image boxes; no seed-based stage predicts one. |
| Loss terms for HGGD | its loss terms are functions inside the detector, not config nodes. |