Contrastive loss trains an embedding space rather than a classifier. It takes pairs and pulls similar ones together while pushing dissimilar ones apart — but only up to a point.
For a pair at embedding distance d, with y = 1 meaning similar and y = 0 meaning dissimilar:
loss = y * d² + (1 - y) * max(0, margin - d)²
Task: write contrastive_loss(distances, labels, margin) returning the mean loss, rounded to 4 decimal places.
d² — the cost grows without limit the further apart they drift.margin. Once past it they cost nothing.Without the margin, the loss would reward pushing dissimilar pairs infinitely far apart and the embedding would just explode. Capping it at a fixed radius says "far enough is far enough", which is what keeps the space bounded and the geometry meaningful.