Loss Composite#
composite
#
| CLASS | DESCRIPTION |
|---|---|
CompositeLoss |
Combine multiple loss functions with configurable weights. |
Classes#
CompositeLoss(losses: list[Loss] | dict[str, Loss], weights: list[float] | dict[str, float] | None = None, context_fn: Callable[[dict[str, Any]], dict[str, Any]] | None = None, context_maps: dict[str, Callable[[dict[str, Any]], dict[str, Any]]] | None = None)
#
Bases: Loss
Combine multiple loss functions with configurable weights.
Enables composition of multiple loss functions into a single weighted sum, with support for named losses and individual component tracking. Useful for multi-objective optimization in parametric methods.
| PARAMETER | DESCRIPTION |
|---|---|
losses
|
Loss functions to combine. Can be a list for unnamed losses with equal or sequential weights, or a dict for named losses with custom weights. |
weights
|
Weights for each loss function. If None, all weights default to 1.0.
TYPE:
|
context_fn
|
Optional function to compute shared context for all losses. Called once per forward pass to avoid redundant computation.
Receives the merged context dict (context + kwargs from Signature:
TYPE:
|
context_maps
|
Optional per-loss context mapping functions for resolving key collisions. Maps loss names to functions that transform the merged context into loss-specific context. Useful when multiple losses need different tensors under the same key name (e.g., both need 'K' but for different purposes). Keys must match loss names. Functions receive merged context and return dict with keys expected by that specific loss. Signature:
TYPE:
|
| ATTRIBUTE | DESCRIPTION |
|---|---|
losses |
Internal storage of loss functions as name-to-loss mapping.
TYPE:
|
weights |
Weights for each loss function.
TYPE:
|
context_fn |
Context computation function.
TYPE:
|
loss_components |
Most recently computed individual loss components. Populated after each forward pass for logging purposes. Initialized as empty dict.
TYPE:
|
Examples:
Combine losses with equal weights:
>>> from spectre.loss import CompositeLoss, EigenvalueLoss, OrthogonalLoss
>>> composite = CompositeLoss(
... losses=[EigenvalueLoss(reduce="gap", n_eigen=2), OrthogonalLoss()],
... )
Combine losses with custom weights:
>>> composite = CompositeLoss(
... losses=[EigenvalueLoss(reduce="gap", n_eigen=2), OrthogonalLoss()],
... weights=[1.0, 0.1],
... )
Combine named losses with custom weights:
>>> composite = CompositeLoss(
... losses={
... "spectral": EigenvalueLoss(reduce="gap", n_eigen=2),
... "orthogonal": OrthogonalLoss(),
... },
... weights={"spectral": 1.0, "orthogonal": 0.1},
... )
>>>
>>> # Access individual components after forward pass
>>> context = {"eigval": eigvals, "Z": latent_space}
>>> total_loss = composite(context)
>>> print(composite.loss_components)
{'spectral': tensor(0.5), 'orthogonal': tensor(0.02)}
Use with context function for shared computation:
>>> def compute_context(context, **kwargs):
... X = context["X"]
... z = encoder(X)
... pdist = pairwise_fn(z)
... kernel = kernel_fn(pdist)
... eigvals = torch.linalg.eigvalsh(kernel)
... return {"eigval": eigvals, "Z": z, "kernel": kernel}
>>>
>>> composite = CompositeLoss(
... losses={"spectral": EigenvalueLoss(...), "ortho": OrthogonalLoss()},
... weights={"spectral": 1.0, "ortho": 0.1},
... context_fn=compute_context,
... )
Resolve key collisions with context_prefix:
>>> composite = CompositeLoss(
... losses={
... "kl": KLDivergenceLoss(context_prefix="kl"),
... "distill": DistillationLoss(context_prefix="distill"),
... },
... weights={"kl": 1.0, "distill": 0.5},
... )
>>> context = {
... "kl_P": P_distribution,
... "kl_Q": Q_distribution,
... "distill_T": teacher_output,
... "distill_S": student_output,
... }
>>> loss = composite(context)
Resolve key collisions with context_maps:
>>> composite = CompositeLoss(
... losses={
... "kl": KLDivergenceLoss(),
... "distill": DistillationLoss(),
... },
... context_maps={
... "kl": lambda ctx: {"P": ctx["P_prob"], "Q": ctx["Q_prob"]},
... "distill": lambda ctx: {"T": ctx["teacher"], "S": ctx["student"]},
... },
... )
| METHOD | DESCRIPTION |
|---|---|
forward |
Compute weighted sum of all loss functions. |
exists |
Check if composite loss contains a loss component matching the pattern. |
Source code in spectre/loss/composite.py
148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 | |
Attributes#
loss_types: list[LossType]
property
#
Aggregate loss types from all constituent losses.
| RETURNS | DESCRIPTION |
|---|---|
list[LossType]
|
List of unique loss types across all child losses. |
Functions#
forward(context: dict[str, torch.Tensor] | None = None, **kwargs) -> torch.Tensor
#
Compute weighted sum of all loss functions.
Accepts either a context dictionary or kwargs (or both). All arguments are merged and passed to child losses.
| PARAMETER | DESCRIPTION |
|---|---|
context
|
Dictionary containing tensors required for child losses. If None, uses empty dict.
TYPE:
|
**kwargs
|
Additional keyword arguments merged into context for child losses.
If
DEFAULT:
|
| RETURNS | DESCRIPTION |
|---|---|
Tensor
|
Scalar total loss as weighted sum of individual components. |
Notes
Individual loss components are stored in self.loss_components.
Source code in spectre/loss/composite.py
exists(pattern: str) -> bool
#
Check if composite loss contains a loss component matching the pattern.
| PARAMETER | DESCRIPTION |
|---|---|
pattern
|
Pattern to match against loss component names. Supports prefix matching (e.g., "mincut" matches "loss_mincut", "loss_mincut_1", etc.).
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
bool
|
True if any loss component name contains the pattern, False otherwise. |