Skip to content

← Loss Functions step 8 of 8

Medium Research

Contrastive Loss (InfoNCE)

InfoNCE turns matching embeddings into a classification task. An embedding is a vector representing an example. Each anchor has one designated match among a batch of candidates, and the loss rewards assigning that match a high probability. The objective comes from Contrastive Predictive Coding.

Here row i of anchors matches row i of positives. Compare each anchor with every row of positives using a dot product. Divide these scores by a positive temperature, then apply softmax across each row. The loss for anchor i is the negative natural log of probability (i, i). Other rows of positives serve as negatives for that anchor, even if they happen to contain identical vectors.

For anchors = positives = [[1, 0], [0, 1]] and temperature 1, the score matrix is [[1, 0], [0, 1]]. Each correct match receives probability exp(1) / (exp(1) + exp(0)), about 0.731059. The mean loss is about 0.313262. With only one candidate, its probability is 1 and the loss is zero.

Your task

Implement infonce_loss(anchors, positives, temperature):

  • Both floating-point inputs have shape (N, d), with N > 0 and d > 0.
  • temperature is a positive Python float. Assume scaled dot products are finite. A lower temperature emphasizes differences between scores.
  • Use the input embeddings as given. Do not normalize them.
  • Average the N anchor-to-candidate losses. Do not add a reverse-direction loss or compare anchors with other anchors.
  • Return the scalar loss as a Python float. Decimal rounding is optional; numerical comparisons allow normal floating-point error.

Compute log probabilities stably. Subtract each row's maximum score before exponentiating and keep the selected score in those same shifted coordinates. Adding a large maximum back only to subtract it again can lose the small normalization term. For a row of equal scores, the loss should be log(N) even when the common score is very large.

The Python-float return is this exercise's output format. In a training loop, keep the loss as a tensor so automatic differentiation can use it.