Part XV — Multimodal Foundation Models: CLIP, Cross-Attention & VLMs · Chapter 3

Cross-attention mechanisms

Hook

A shared embedding space lets you measure distance between a whole image and a whole caption. But a caption is made of individual words, and an image is made of individual regions — what if a word could look at specific parts of the image instead of the image as one averaged point?

Intuition
sky patch0.14ground patch0.58dog patch0.28query
weights: sky=0.14, ground=0.58, dog=0.28

This is Part IV's attention mechanism again, but QQ now comes from a text token while KK and VV come from image patches — sky, ground, and dog. Drag the query: it's still one attention computation, just spanning two modalities instead of one sequence attending to itself.

Formalize

The formula hasn't changed at all from Part IV:

scorei=qkid,wi=softmax(score)i,context=iwiki\text{score}_i = \frac{q \cdot k_i}{\sqrt{d}}, \qquad w_i = \text{softmax}(\text{score})_i, \qquad \text{context} = \sum_i w_i\, k_i
  • qq — the query vector, coming from a text token.
  • kik_i — the key vector for image patch ii.
  • scorei\text{score}_i — the raw compatibility between the query and image patch ii, before normalizing.
  • wiw_i — the attention weight on image patch ii, after softmax turns the scores into a distribution.
  • context\text{context} — the weighted blend of all image patches that the query actually attends to.
  • dd — the dimensionality of the key vectors, used to rescale the raw scores.
  1. Self-attention: everything from one sequence

    In Part IV, qq, kik_i, and viv_i all came from the same sequence attending to itself.

  2. Cross-attention: q and k/v from different modalities

    Here qq comes from one modality's encoder (text) while ki,vik_i, v_i come from a completely different one (image patches) — the same mechanism, just pointed across a modality boundary instead of within one sequence.

Play
sky patch0.14ground patch0.58dog patch0.28query
context = (0.56, 1.44) — a blend, not any single patch

Watch the context vector as you drag. It's always a weighted blend of all three image patches — never any single one exactly, unless one weight reaches all the way to 11. This is what a text token "looking at" an image actually produces: not a chosen patch, but a soft mixture shaped by how much each patch matters to that particular word.

Worked example

At query q=(1,2)q=(1,2) over patches sky=(2,0)=(2,0), ground=(0,2)=(0,2), dog=(1,1)=(1,1):

  1. Raw scores, scaled by root d

    Dot product with each key, then divide by 2\sqrt{2}:

    • Sky: qksky=1(2)+2(0)=2q\cdot k_{\text{sky}} = 1(2)+2(0) = 2, so 2/21.4142/\sqrt2\approx1.414
    • Ground: qkground=1(0)+2(2)=4q\cdot k_{\text{ground}} = 1(0)+2(2) = 4, so 4/22.8284/\sqrt2\approx2.828
    • Dog: qkdog=1(1)+2(1)=3q\cdot k_{\text{dog}} = 1(1)+2(1) = 3, so 3/22.1213/\sqrt2\approx2.121
  2. Softmax into weights

    Exponentiate each and divide by their sum 4.114+16.92+8.339=29.373\approx4.114+16.92+8.339=29.373:

    • Sky: e1.4144.114e^{1.414}\approx4.114, so 4.114/29.3730.1404.114/29.373\approx0.140
    • Ground: e2.82816.92e^{2.828}\approx16.92, so 16.92/29.3730.57616.92/29.373\approx0.576
    • Dog: e2.1218.339e^{2.121}\approx8.339, so 8.339/29.3730.2848.339/29.373\approx0.284

    The ground patch dominates, since this query leans more toward "ground" than "sky" or "dog" in raw dot product.

  3. The context vector

    Weighting each patch by its share and summing:

    • Sky: 0.140(2,0)=(0.280,0)0.140(2,0) = (0.280, 0)
    • Ground: 0.576(0,2)=(0,1.152)0.576(0,2) = (0, 1.152)
    • Dog: 0.284(1,1)=(0.284,0.284)0.284(1,1) = (0.284, 0.284)

    Summing componentwise: (0.280+0+0.284, 0+1.152+0.284)=(0.564, 1.436)(0.280+0+0.284,\ 0+1.152+0.284) = (0.564,\ 1.436) — noticeably closer to the ground patch's own coordinates than to sky's, but pulled partway toward the other two, exactly reflecting their smaller but nonzero weights.

Checkpoint

Drag the query until the sky patch receives more than 0.7 of the attention weight.

sky patch0.33ground patch0.33dog patch0.33query
sky weight: 0.33
Drag the query to try it
Summary
context=isoftmax ⁣(qkid)iki\text{context} = \sum_i \text{softmax}\!\left(\frac{q \cdot k_i}{\sqrt{d}}\right)_i k_i

Cross-attention is what lets a caption-generating model ask, word by word, "which part of the image is relevant to the word I'm about to produce" — instead of summarizing the whole image into one fixed vector up front and hoping every word can work from that. The next chapter assembles this alongside Chapter 1's joint embeddings into one working vision-language pipeline.