fn

triplet_margin_loss

Tensor
triplet_margin_loss(anchor: Tensor, positive: Tensor, negative: Tensor, margin: float = 1.0, p: float = 2.0, eps: float = 1e-06, swap: bool = False, reduction: str = 'mean')
source

Triplet margin loss for metric learning.

Pulls an "anchor" embedding toward a "positive" example (same class / matching pair) and pushes it away from a "negative" example by at least a fixed margin. This is the workhorse objective for learning embeddings used in face verification (FaceNet), image retrieval, and contrastive representation learning.

Optionally applies the "anchor-swap" trick of Balntas et al. 2016 — when d(p, n) < d(a, n) the positive is closer to the negative than the anchor is, so we swap roles and use the harder of the two distances, focusing gradient on the more informative triplet.

Parameters

anchorTensor
Embedding of shape (N,D)(N, D).
positiveTensor
Positive sample embedding of the same shape.
negativeTensor
Negative sample embedding of the same shape.
marginfloat= 1.0
Minimum desired gap between positive and negative distances (default 1.0). Triplets satisfying the margin already receive zero loss / zero gradient.
pfloat= 2.0
Norm degree of the pairwise distance (default 2.0 — Euclidean).
epsfloat= 1e-06
Numerical floor inside the distance to avoid zero-derivative at coincident points (default 1e-6).
swapbool= False
Enable the Balntas-anchor-swap trick (default False).
reductionstr= 'mean'
"mean" (default), "sum", or "none".

Returns

Tensor

Scalar or per-triplet tensor of shape (N,)(N,).

Notes

Per-triplet loss:

Li=max ⁣(0,  d(ai,pi)d(ai,ni)+margin),L_i = \max\!\big(0,\; d(a_i, p_i) - d(a_i, n_i) + \text{margin}\big),

where d(,)d(\cdot, \cdot) is the LpL_p pairwise distance. Easy triplets (already separated by margin) contribute exactly zero — only "semi-hard" / "hard" triplets drive the update, which is why batch mining strategies matter so much in practice.

Examples

>>> import lucid
>>> from lucid.nn.functional import triplet_margin_loss
>>> a = lucid.tensor([[1.0, 0.0]])
>>> p = lucid.tensor([[1.0, 0.1]])
>>> n = lucid.tensor([[0.0, 1.0]])
>>> triplet_margin_loss(a, p, n, margin=1.0)
Tensor(0.6862...)