A triplet objective asks an anchor to be closer to a reviewed positive than a reviewed negative by a chosen margin in one declared distance space.
Triplet margin and normalized embedding geometry
Fix the distance convention
A component image encoder maps each photo to a vector. This lesson uses Euclidean distance between unit-normalized vectors; squared distance and cosine similarity would change the numeric margin and gradients. Normalize consistently at training and serving. An encoder version change invalidates stored gallery vectors unless the gallery is rebuilt. Pair identity comes before choosing the loss.
Read the loss as a constraint
For anchor a, positive p and negative n, triplet loss is the maximum of zero and distance(a,p) minus distance(a,n) plus margin. Zero means that triplet already meets the margin; it does not prove the full gallery is separated. A larger margin can force unnecessary distortion when defect families overlap or labels are noisy. Tune it only on development identities.
Separate objective from retrieval quality
A decreasing training loss can come from repeated easy identities or collapse in one slice. Evaluate whether a new component query retrieves a correct defect-family neighbor from a realistic gallery, and inspect false matches that would trigger the wrong repair. Recall and collapse checks address that operational question.
Use real encoder training for deployment
The code computes normalized two-dimensional vectors and one loss value. It is a geometry check, not a trainable neural model. A production encoder needs batching, augmentation tied to allowed transformations, checkpoint selection, and paired source/target error analysis. The encoder contract handles input and target alignment.
Watch invariances
Color and lighting augmentation can help if defect identity should remain stable. It can also erase a color-specific heat mark that technicians need. Every augmentation is a claim that transformed images preserve the label. Test that claim with inspected pairs before making it part of training.
Implementation
from math import sqrt
def unit_vector(embedding):
length = sqrt(sum(value * value for value in embedding))
if length == 0:
raise ValueError("zero embedding has no direction")
return tuple(value / length for value in embedding)
def euclidean(first, second):
return sqrt(sum((left - right) ** 2 for left, right in zip(first, second)))
anchor = unit_vector((3.0, 4.0))
positive = unit_vector((3.2, 3.8))
negative = unit_vector((-4.0, 3.0))
margin = 0.35
triplet_loss = max(0.0, euclidean(anchor, positive) - euclidean(anchor, negative) + margin)
assert len(anchor) == len(positive) == len(negative) == 2
assert triplet_loss == 0.0
assert round(euclidean(anchor, positive), 3) < round(euclidean(anchor, negative), 3)Performance and operating cost
Normalization and two distances cost O(D) time for D vector dimensions and O(D) output storage. Full encoder training costs far more and scales with triplets, image decode and backpropagation. Precomputing gallery vectors saves repeated encoder calls but requires a versioned rebuild when weights or preprocessing change.
Common Mistakes
- Do not mix normalized gallery vectors with raw query vectors.
- Do not treat zero triplet loss as proof of high retrieval recall.
- Do not choose a margin from the final test identities.
