Hello! Welcome back to our module on Multimodal and Cross-Domain AI.
In our last lesson, you implemented CLIP, a model that learns a shared space to associate images with text. We trained it to understand that a picture of a dog and the phrase "a photo of a dog" are semantically similar. Now, we'll take the next logical step: moving from association to generation. Instead of just matching an image to existing text, we'll build a model that can look at an image and write a caption for it from scratch.
Your learning outcome for this lesson is to build an image captioning model using an encoder-decoder architecture. This is a classic and powerful paradigm in multimodal AI that combines a vision model (the encoder) with a language model (the decoder). We'll explore this architecture from its foundational CNN+RNN implementation to its modern, fully Transformer-based form.
1. The Core Idea: Show and Tell
At its heart, image captioning works like this:
- The Encoder ("Show"): A neural network "looks" at an image and compresses its visual information into a compact numerical representation, often a single vector. This network is typically a Convolutional Neural Network (CNN) pre-trained on a large image classification task (like ImageNet), as its layers have already learned to recognize rich visual features.
- The Decoder ("Tell"): Another network, designed for sequential data, takes this image vector and generates a caption, one word at a time. Recurrent Neural Networks (RNNs), particularly LSTMs or GRUs, are the classic choice for this task.
This combination forms the basis of an encoder-decoder model for image captioning.
Building an Image Captioner with Neural Networks
To begin, let's watch a video that builds this intuition from first principles. It frames the problem as designing a mathematical function that maps an image (a matrix/tensor) to a caption (a sequence).
Watch from 01:56 to 05:21. This segment covers: Identifying the input (image) and output (sequence/caption) and why an RNN is a natural fit for the decoder. How a pre-trained CNN can be used as a feature extractor (encoder) to convert an image into a dense vector. How these two components are combined to form the basic 'Show-and-Tell' architecture.
The architecture described in the video is a cornerstone of multimodal research. Here is a diagram illustrating the data flow:

2. Implementation with PyTorch (CNN + LSTM)
Now let's translate this concept into code. Your background in Python and software engineering will be very useful here as we look at a practical PyTorch implementation. We will examine how to define the encoder and decoder as separate nn.Module classes and then combine them into a single model.
A key concept during training is teacher forcing. When training the decoder, instead of feeding its own predicted word from the previous step as input to the next, we feed the correct word from the ground-truth caption. This stabilizes training and helps the model learn faster. During inference (when generating a caption for a new image), this "teacher" is absent, and the model must rely on its own predictions.
Pytorch Image Captioning Tutorial
The following video provides a clear, step-by-step walkthrough of implementing this CNN-LSTM architecture in PyTorch.
Focus on these key segments to understand the implementation: Model Overview (02:22 - 03:34): See how a pre-trained CNN's output is fed as the initial input to the LSTM decoder. Training vs. Inference (03:34 - 05:04): Understand the crucial difference between using teacher forcing during training and generating captions autoregressively during inference. Code Structure (06:00 - 12:17): Skim through the implementation of the EncoderCNN and DecoderRNN classes. Notice how the pre-trained model is loaded and its final layer is replaced to produce embeddings, and how the DecoderRNN is a standard LSTM-based model. Combining Modules (13:48 - 16:08): See how the CNNtoRNN class cleanly wraps the encoder and decoder.
Test your understanding!
In the CNNtoRNN forward method shown in the video, the training process looks something like this:
# Simplified pseudo-code
features = self.encoder(images)
outputs = self.decoder(features, captions) # `captions` are the ground-truth
During inference (in the caption_image function), there is no captions argument. How does the decoder generate a sequence in this case?
Show answer
During inference, the decoder operates in a loop.
- It starts with the image features (and a
<start>token) to predict the first word. - The predicted word from step 1 is then fed back as the input for the next time step to predict the second word.
- This process continues, with each predicted word becoming the input for the next prediction, until the model predicts an
<end>token or a maximum length is reached. This is an autoregressive process, in contrast to the teacher-forced training.
3. A Deeper Dive: "Show, Attend, and Tell"
The basic model condenses the entire image into a single vector. This can be a bottleneck, forcing the model to cram all visual information into one representation. What if the model could focus on different parts of the image as it generates different words in the caption? This is the motivation for the attention mechanism.
For example, when generating the word "frisbee," the model should "attend" to the region of the image containing the frisbee.
Building an Image Captioner with Neural Networks
Let's revisit the first video to get a conceptual understanding of how attention is incorporated.
Watch from 08:11 to 11:16. The video explains the 'Show, Attend, and Tell' architecture. Pay attention to how it uses feature maps from the CNN's convolutional layers (which preserve spatial information) instead of the final vector, and how an attention network calculates weights (alpha) over these spatial regions at each step of the decoding process.
Implementing this is more involved because we can't use a standard nn.LSTM module that processes the whole sequence at once. Instead, we must use an nn.LSTMCell and write a manual loop for each time step of the decoding process, allowing the attention mechanism to intervene between steps.
A PyTorch Tutorial to Image Captioning
This GitHub repository provides a detailed and exceptionally well-commented PyTorch tutorial for the 'Show, Attend, and Tell' model. We will study its key components to understand the implementation.
Read through the following sections of the README to understand the advanced implementation: Overview Section: Briefly read the descriptions of the Encoder, Decoder, and Attention to solidify the concepts. Implementation Section: Study the code descriptions for the Encoder, Attention, and DecoderWithAttention classes. Notice these key details: The Encoder no longer uses the final linear layer of the ResNet. It provides the 14x14x2048 feature map from a convolutional block. The Attention network takes the encoder's output and the decoder's previous hidden state to compute the attention weights. The DecoderWithAttention class uses a for loop and an LSTMCell. This manual iteration is the critical part that allows attention to be computed at each step. Training Section: Note the mention of the 'doubly stochastic regularization' loss. This is an auxiliary loss that encourages the model to attend to all parts of theimage over the course of generating a full caption.
This tutorial is a great example of a research paper implementation, providing the kind of in-depth detail you're looking for.
4. The Modern Approach: A Full Transformer Architecture
The CNN+RNN approach has been highly successful. However, given the dominance of Transformers in both vision (ViT) and language (GPT, BERT), a natural evolution is to build the entire encoder-decoder system using Transformers.
This modern architecture replaces the CNN with a Vision Transformer (like the one you studied in our CLIP lesson) and the RNN with a language Transformer decoder (like GPT).
The Hugging Face transformers library provides a convenient VisionEncoderDecoderModel class that allows you to easily combine any pre-trained vision model from the Hub with any pre-trained language model.
Image Captioning using PyTorch and Transformers in Python
This tutorial demonstrates how to fine-tune a VisionEncoderDecoderModel using PyTorch and the Hugging Face library. It's a very practical guide to building a state-of-the-art captioning model.
Read through the following sections to understand the modern workflow: Model Architecture: Reinforce your understanding of the ViT/Swin Encoder and Language Model Decoder structure. Loading the Model: See how VisionEncoderDecoderModel.from_encoder_decoder_pretrained is used to plug a microsoft/swin-base encoder into a gpt2 decoder. Preprocessing the Dataset: Notice the use of with_transform for on-the-fly preprocessing, a memory-efficient technique for large datasets that aligns well with your data pipeline experience. Evaluation Metrics: Read about the common metrics used for this task, like BLEU and ROUGE. These are essential for evaluating any generative text model. Training: Skim the 'Using the Trainer Class' section to see how the high-level Seq2SeqTrainer automates the fine-tuning process.
This approach leverages the power of large, pre-trained models and transfer learning, which is the dominant paradigm in AI today. Your familiarity with Python and ML frameworks makes this Hugging Face-based workflow a powerful and practical tool to have.
Conclusion
You have done an excellent job exploring the evolution of image captioning models. We've journeyed from the foundational "Show-and-Tell" concept to the powerful attention mechanism and finally to the modern, end-to-end Transformer architecture.
Key Takeaways:
- Encoder-Decoder Framework: Image captioning is fundamentally an encoder-decoder problem, where a vision encoder creates a representation of the image and a language decoder generates a text sequence from it.
- Classic vs. Modern: The architecture has evolved from CNN encoders + RNN decoders to fully Transformer-based encoders and decoders.
- Attention is Key: The attention mechanism was a critical innovation, allowing the decoder to dynamically focus on relevant image regions while generating the caption, leading to more descriptive and accurate results.
- Training vs. Inference: You reinforced your understanding of the distinction between teacher forcing for stable training and autoregressive generation for real-world inference.
- Practical Tooling: You've seen how libraries like PyTorch and Hugging Face Transformers provide the building blocks and high-level APIs to implement both classic and state-of-the-art models.
Preview of the Next Lesson:
We have now seen how a model can generate a general description of an image. What if we want to ask a specific question about it? In the next lesson, you will implement a Visual Question Answering (VQA) model. This task requires a more sophisticated fusion of vision and language, as the model must understand the image, understand the question, and then generate a relevant answer.