Quant Memo
Core

Cosine Embedding and Triplet Losses

Some models aren't trained to predict a label at all — they're trained to arrange examples in space, pulling similar ones together and pushing dissimilar ones apart, using pairs (cosine embedding loss) or anchor-positive-negative triples (triplet loss).

Prerequisites: Loss Functions for Regression

Most losses compare a prediction to a single known target value. But some problems have no fixed target at all — finding similar news articles, matching a trade description to a taxonomy, clustering related market events — and instead just need a notion of "these two things are alike" and "these two are not." Cosine embedding loss and triplet loss both train a network to place its outputs (embeddings — vectors in a learned space) so that similar inputs land near each other and dissimilar ones land far apart, without ever specifying a numeric target for any individual output.

The analogy: arranging desks by who works together

Imagine rearranging an open office so colleagues who collaborate daily sit close together and colleagues who never interact sit far apart — with no map giving "correct" coordinates for any one desk, only a list of who should be near whom. Cosine embedding loss looks at pairs ("these two should be close" or "far"), while triplet loss looks at triples ("closer to a teammate than to a stranger, by at least some margin").

The formulas

Cosine embedding loss takes a pair of embeddings u,vu, v with a label y{1,1}y \in \{1, -1\} (similar or dissimilar), and a margin mm:

L(u,v,y)={1cos(u,v)y=1max(0, cos(u,v)m)y=1L(u,v,y) = \begin{cases} 1 - \cos(u,v) & y=1 \\ \max(0,\ \cos(u,v) - m) & y=-1 \end{cases}

In words: cosine similarity cos(u,v)\cos(u,v) measures how aligned two vectors' directions are, from 1-1 (opposite) to 11 (identical direction), ignoring their length. If the pair is meant to be similar, the loss is 11 minus that similarity — pushed to zero only when the vectors point in exactly the same direction. If the pair is meant to be dissimilar, there's no penalty at all once similarity has already dropped below the margin mm — the loss stops caring once "far enough apart" is achieved.

Triplet loss takes an anchor aa, a positive example pp (same class as the anchor), and a negative example nn (different class), with distance function dd and margin α\alpha:

L(a,p,n)=max(0, d(a,p)d(a,n)+α)L(a,p,n) = \max\big(0,\ d(a,p) - d(a,n) + \alpha\big)

In words: the anchor's distance to its positive should be smaller than its distance to its negative, by at least the margin α\alpha; the loss is zero once that's already true by a comfortable margin, and grows linearly the more that ordering is violated.

Worked example 1: cosine embedding loss on two pairs

Pair A, labeled similar (y=1y=1): embeddings with cos(u,v)=0.8\cos(u,v) = 0.8. Loss =10.8=0.2= 1 - 0.8 = 0.2.

Pair B, labeled dissimilar (y=1y=-1), margin m=0.2m = 0.2: cos(u,v)=0.5\cos(u,v) = 0.5. Loss =max(0, 0.50.2)=0.3= \max(0,\ 0.5 - 0.2) = 0.3 — still similar enough (0.5) to exceed the margin, so there's a real penalty pushing them further apart. If instead this pair's similarity were already 0.10.1 (below the margin), loss would be max(0, 0.10.2)=0\max(0,\ 0.1-0.2) = 0 — no further push needed, they're already far enough apart.

Worked example 2: triplet loss with real distances

Anchor-positive squared distance d(a,p)=0.4d(a,p) = 0.4, anchor-negative squared distance d(a,n)=0.9d(a,n) = 0.9, margin α=0.2\alpha = 0.2. Loss =max(0, 0.40.9+0.2)=max(0,0.3)=0= \max(0,\ 0.4 - 0.9 + 0.2) = \max(0, -0.3) = 0 — the positive is already closer than the negative by more than the margin, so this triplet contributes nothing to training. Now suppose instead d(a,n)=0.5d(a,n) = 0.5 (a "hard" negative, nearly as close as the positive): loss =max(0, 0.40.5+0.2)=0.1= \max(0,\ 0.4 - 0.5 + 0.2) = 0.1 — a real, nonzero gradient. This is why "hard negative mining" — deliberately choosing negatives that are currently confusingly close — is standard practice: easy triplets like the first contribute zero gradient and waste a training step.

-1 opposite 0 unrelated 1 identical similar pair: 0.8 dissimilar pair: 0.5
Cosine similarity measures alignment of direction only, from -1 to 1; cosine embedding loss pulls similar-labeled pairs toward 1 and pushes dissimilar-labeled pairs below the margin.
anchor positive d(a,p) negative d(a,n) ≥ d(a,p) + α
Triplet loss pushes the anchor-positive distance below the anchor-negative distance by at least a margin α; once satisfied, that triplet stops contributing gradient.

Both losses train embeddings by relative structure rather than a fixed target: cosine embedding loss pulls labeled-similar pairs toward the same direction and pushes labeled-dissimilar pairs apart past a margin, while triplet loss enforces that an anchor sits closer to a same-class positive than to a different-class negative by at least a margin, with zero gradient once that's already satisfied.

What this means in practice

These losses underlie any "find similar X" system — semantic search over research notes, matching historical market regimes, deduplicating news feeds — where embeddings are later compared with cosine similarity or nearest-neighbor search at inference time, separate from whatever labels were used during training. Triplet loss is sensitive to how triplets are sampled: random triplets are mostly "easy" (zero gradient) and training stalls unless hard or semi-hard negatives are deliberately mined.

The common confusion is thinking a small loss value means the embedding space is well-organized overall. Both losses are computed per-pair or per-triplet and say nothing about the global geometry — a network can drive loss to near zero on every sampled triplet while still leaving some far-apart classes tangled together, simply because no triplet involving that particular pair was ever sampled during training. The sampling strategy is as much a part of "the loss" in practice as the formula itself.

Related concepts

Practice in interviews

Further reading

  • Schroff, Kalenichenko & Philbin, FaceNet: A Unified Embedding for Face Recognition and Clustering (2015)
ShareTwitterLinkedIn