Show, numerically, the structural difference between CLIP and SigLIP: CLIP's match probability for a pair depends on which other examples share the batch, SigLIP's does not. Score the same pairs twice - once in the full batch, once after the batch is truncated - under both objectives.
Both models score a pair with a scaled cosine similarity. They differ only in how that score becomes a probability.
CLIP normalises across the row - the denominator sums over every text in the batch:
piiCLIP=∑j=1nesI^i⋅T^jesI^i⋅T^i
SigLIP normalises nothing - each pair is its own logistic regression, with a learned bias:
piiSigLIP=σ(sI^i⋅T^i+b),σ(x)=1+e−x1
Now keep only the first k rows and columns and rescore those same k pairs. Every CLIP denominator has lost n - k terms, so every p^CLIP_ii moves - the identical image-caption pair is scored differently purely because its batch-mates went away. The SigLIP values are bit-for-bit unchanged: no term in p^SigLIP_ii mentions any other example.
That is the whole argument for the sigmoid loss. CLIP's gradient couples the batch, which is why it needs enormous batches and an all-gather of logits across devices; SigLIP's does not, so it trains as happily at batch 4k as at 32k and shards without cross-device communication.
Implement:
def compare_objectives(image_emb, text_emb, logit_scale, bias, subset_size):
Every returned value is a mean over the first subset_size diagonal pairs - the same pairs in all four cases. What changes is the context:
Return [clip_full, clip_subset, siglip_full, siglip_subset], each rounded to 4 decimals.
A list of four floats rounded to 4 decimals. The last two are always equal - that is the point of the exercise.
img = [[1.0, 0.0], [0.0, 1.0], [1.0, 1.0]]
txt = [[1.0, 0.1], [0.1, 1.0], [1.0, 0.9]]
print(compare_objectives(img, txt, 5.0, -2.0, 2))
Output:
[0.8002, 0.9888, 0.9514, 0.9514]
img = [[1.0, 0.0], [0.0, 1.0], [1.0, 1.0]] txt = [[1.0, 0.1], [0.1, 1.0], [1.0, 0.9]] print(compare_objectives(img, txt, 5.0, -2.0, 2))
[0.8002, 0.9888, 0.9514, 0.9514]
Pairs 0 and 1 are scored in both settings. Dropping the third pair removes one competitor from each CLIP row, so their mean softmax probability jumps from 0.8002 to 0.9888 even though no embedding changed. The SigLIP probability of a pair reads only that pair's own similarity, so it is 0.9514 in both settings.
1 <= n <= 64, 1 <= d <= 64; no row is the zero vectorsubset_size diagonal pairssubset_size rows