How does a Vision Transformer turn an image into a sequence, and what mask runs over it?
Same topic, related formats. Practice these next.
Same topic, related formats. Practice these next.
A Vision Transformer (ViT) applies the same attention machinery as a language model, but the inputs are images. Walk through how the per-token sequence is built from an image, what attention mask is used, and how the model knows where each patch came from.
Split the image into fixed-size patches, linearly project each into a token, prepend a CLS token, run full bidirectional attention, and add learned 2D positional embeddings.
Imagine cutting a photograph into a grid of small square tiles, like a jigsaw puzzle. You hand the model the tiles in a stack along with a sticky note on each one saying 'I came from row 3, column 7'. The model looks at every tile and lets each one see every other tile, no rules about which tiles came first because all tiles exist at once. After all that looking, one special blank tile (the CLS token) collects everything the model figured out about the whole picture and hands the summary off for classification.
Everything you need to truly understand this topic: intuition, mechanics, step by step explanation, code, formulas, and worked example. Click to expand.
Everything you need to truly understand this topic: intuition, mechanics, step by step explanation, code, formulas, and worked example.
Everything important, quickly.
6m: patch tokenization pipeline, CLS token role and alternatives, why bidirectional attention is the right choice for images, position encoding variants, hierarchical Swin alternative, and downstream applications (CLIP, DINOv2, SAM).
import torch
import torch.nn as nn
class PatchEmbed(nn.Module):
def __init__(self, img_size=224, patch_size=16, in_chans=3, d_model=768):
super().__init__()
self.proj = nn.Conv2d(in_chans, d_model,
kernel_size=patch_size, stride=patch_size)
num_patches = (img_size // patch_size) ** 2
self.cls_token = nn.Parameter(torch.zeros(1, 1, d_model))
self.pos_embed = nn.Parameter(torch.zeros(1, num_patches + 1, d_model))
def forward(self, x): # x: (B, 3, 224, 224)
x = self.proj(x) # (B, d_model, 14, 14)
x = x.flatten(2).transpose(1, 2) # (B, 196, d_model)
cls = self.cls_token.expand(x.size(0), -1, -1)
x = torch.cat([cls, x], dim=1) # (B, 197, d_model)
x = x + self.pos_embed
return xReal products, models, and research that use this idea.
What an interviewer would ask next. Try answering before peeking at the approach.
Red flags and common mistakes that signal junior thinking. Click to expand.
Using a causal mask for ViT. Images have no temporal direction, all patches exist simultaneously, so attention is fully bidirectional. Causal masking would arbitrarily block patches from seeing later patches in the (artificial) raster order.
The night-before-the-interview bullets. Scan these on the way to the call.
Primary sources. Skim if you want the original framing.