lightning_pose.lossesο
lightning_pose.losses.factory Moduleο
Factory utilities for building and combining losses from a Hydra config.
Three components work together:
get_loss_classes()β returns the registry mapping loss-name strings to classes.get_loss_factories()β readscfg.lossesandcfg.model.losses_to_use, assembles per-loss parameter dicts, and returns a{'supervised': LossFactory, 'unsupervised': LossFactory}dict ready to be passed to a model constructor.LossFactoryβ aLightningModulethat holds instantiated loss objects and computes the total weighted loss in its__call__method.
Adding a new loss:
Define the class in
losses/losses.py, inheriting fromLoss. For a heatmap-based loss (operating onheatmaps_targ/heatmaps_pred), inherit fromHeatmapLossinstead β it already provides NaN handling and the__call__pipeline, so onlycompute_lossneeds overriding. Set aloss_name: strclass attribute (single name) or multipleLOSS_NAME_*: strclass attributes when one class serves several config strings (e.g.PCALoss).Import the class at the top of this file and add one entry per name to the dict returned by
get_loss_classes().Parameter wiring in
get_loss_factories(); only needed in two cases:Unsupervised loss, param derived from ``cfg.data``/``cfg.model`` (not a literal
cfg.losses.<loss_name>key β literal keys are forwarded automatically): add anelifbranch, e.g.:elif loss_name == 'my_new_loss': loss_params_dict['unsupervised'][loss_name]['my_param'] = cfg.data.some_field
Supervised loss (any
supervised_*name): never auto-forwarded β add an explicit block reading each param you need, e.g.:log_weight = cfg.losses.get('my_new_loss', {}).get('log_weight') if log_weight is not None: loss_params_dict['supervised']['my_new_loss'] = {'log_weight': log_weight}
Skipping this step when itβs actually required doesnβt raise a
KeyErrorβ the loss is simply never added toloss_params_dict, so it silently never runs.
lightning_pose.losses.losses Moduleο
Supervised and unsupervised losses implemented in pytorch.
The lightning pose package defines each loss as its own class; an initialized loss object, in addition to computing the loss, stores hyperparameters related to the loss (weight in the final objective funcion, epsilon-insensitivity parameter, etc.)
A separate LossFactory class (defined in lightning_pose.losses.factory) collects all losses for a given model and orchestrates their execution, logging, etc.
The general flow of each loss class is as follows: - input: predicted and ground truth data - step 0: remove ground truth samples containing nans if desired - step 1: compute loss for each batch element/keypoint/etc - step 2: epsilon-insensitivity: set loss to zero for any batch element with loss < epsilon - step 3: reduce loss (usually mean) - step 4: log values to a dict - step 5: return loss
Classesο
Parent class for all losses. |
|
Parent class for heatmap-shaped losses (MSE, KL, JS divergence, etc). |
|
MSE loss between heatmaps. |
|
Kullback-Leibler loss between heatmaps. |
|
Jensen-Shannon loss between heatmaps. |
|
Penalize predictions that fall outside a low-dimensional subspace. |
|
Penalize temporal differences for each target. |
|
Penalize temporal differences for each heatmap. |
|
MSE loss between ground truth and predicted coordinates. |
|
Root MSE loss between ground truth and predicted coordinates. |
|
Penalize projections from each pair of cameras into 3D world space. |
|
Penalize error between predicted 2D->3D->2D->heatmap and ground truth heatmap. |