Image Captioning
Image captioning models act as a bridge between vision and language, taking an image as input and generating a coherent textual description of its contents.
Why Does This Exist?
While image classification can say a picture contains a dog and a disc, it cannot say a golden retriever catches a disc mid-air. Real uses need objects plus attributes plus relations in words: screen readers, search indexes, and chat agents that start from pixels and end in sentences. Captioning crosses that gap.
This page covers encoder-decoder captioning with attention. Joint scoring of pairs lives in image-text retrieval, object lists in object detection, and joint pretraining in multimodal learning.
Think of It Like This
The reporter and the typist
A visual analyst studies a photo and lists facts: dog, jumping, disc, park. A writer who never saw the photo takes that list and writes a smooth sentence using grammar alone. Captioning joins the two experts in one pipeline.
The encoder is the analyst, the decoder is the writer, and attention is the writer pointing at list lines per word. Where it stops: human writers ask follow-ups and revise, while decoders commit left to right with no revision pass.
How It Actually Works
An encoder turns pixels into a feature grid with a CNN or ViT backbone. A transformer decoder writes words through one by one: at step it attends over plus the past words to and predicts with cross-attention, so the word dog looks at dog pixels. Training minimizes cross-entropy over the positions, and generation stops at the end token. Beam search can replace greedy picks at test time.
In plain words: holds the scene, holds the sentence so far, and attention picks the spot per word.
Worked example
Suppose the next word after a golden retriever catching a scores dog , cat , disc in unnormalized terms with exponentials , , over sum . Normalized shares are , , . Pick dog with loss . Attention weights over dog, grass, and sky patches sum to and point at the dog for this word.
Code
Greedy decoding from per-step scores with only the standard library:
def greedy_caption(scores: list[list[float]], vocab: list[str]) -> str: words: list[str] = [] # picked ids so far for row in scores: # one score row per step best = max(range(len(row)), key=lambda i: row[i]) if vocab[best] == "<EOS>": # stop token ends it break words.append(vocab[best]) return " ".join(words)
vocab = ["a", "dog", "catches", "disc", "<EOS>"]scores = [[2.0, 0.2, 0.1, 0.1, 0.0], [0.1, 2.1, 0.2, 0.1, 0.0], [0.1, 0.2, 1.9, 0.3, 0.0]]print(greedy_caption(scores, vocab)) # -> a dog catchesOutput a dog catches shows left-to-right picks with no search and no revision.
Watch Out For
Hallucinating from strong language priors
Symptom: fluent captions mention objects that are not in the photo, because the decoder repeats common text habits such as kitchen gear instead of reading pixels. Fix: check attention maps per noun and add grounding tests before trusting nouns in accessibility uses.
Training on truth but serving on guesses
Symptom: fine sentence starts with garbled endings, because training feeds true past words while serving feeds the model's own past words, so one early slip cascades. Fix: sample the model's own predictions during training and decode with beam search at test time.
The Quick Version
- Image captioning maps photos to sentences with an encoder, a decoder, and cross-attention.
- Words generate left to right until an end token, with no revision pass.
- Attention links each word to image spots, such as weight on the dog patch.
- The fixture picks dog at with loss for the worked step.
- Strong language priors hallucinate objects, and truth-fed training splits from guess-fed serving.