Cherti, Beaumont, Wightman, Wortsman, Ilharco, Gordon, Schmidt, Schuhmann, Jitsev (LAION / UW / Stability AI) — CVPR 2023

OpenCLIP: Reproducible Scaling Laws for Contrastive Language-Image Learning

The first fully-open reproduction of CLIP at scale — and the study that measured how zero-shot accuracy improves as a smooth power law in model size, data scale, and compute. Trained on the open LAION-2B/5B datasets, OpenCLIP's largest model reached roughly 80% zero-shot ImageNet top-1.

Prerequisites: Softmax + Dot products / cosine similarity + Cross-entropy loss. Transformers help but aren't required.
10
Chapters
10+
Simulations
2
Code Labs

Chapter 0: The Reproducibility Gap

It's early 2022. CLIP — OpenAI's "Contrastive Language-Image Pre-training" model — has reshaped computer vision. You can hand it a photo and a list of plain-English class names ("a photo of a cat," "a photo of a dog," …), and without ever training on those classes, it tells you which caption fits best. This is zero-shot classification: 76% top-1 on ImageNet with no ImageNet training labels. It feels like magic.

But you want to study why it works. How much of that accuracy comes from the model being big? How much from the 400 million image-text pairs it saw? If you double the data, do you get a predictable bump, or does it plateau? These are the questions that turn a trick into a science. And here is the wall you hit: you cannot run the experiment.

CLIP was trained on WIT — a 400M image-text dataset OpenAI scraped from the web and never released. The model weights for the smaller variants were public, but the data, the largest models, and the training code that produced them were not. You could use CLIP. You could not reproduce it, vary it, or extrapolate from it. Every claim about "why CLIP scales" rested on a single closed run you had no access to.

The bet of this paper: Build the whole pipeline in the open — an open dataset (LAION-400M, then LAION-2B, then LAION-5B), open training code (the open_clip library), and a grid of runs spanning model size, data size, and compute. Then measure the scaling behavior empirically. If zero-shot accuracy follows a clean power law, you can predict the accuracy of a model you haven't trained yet — and decide, before spending a million GPU-hours, whether more data or a bigger model is the better investment.

That is exactly what Cherti et al. did. The headline result of the reproduction: an OpenCLIP ViT-G/14 trained on LAION-2B reached roughly 80% zero-shot top-1 on ImageNet — surpassing OpenAI's original CLIP and demonstrating that the open-data pipeline was not a watered-down imitation but a genuine, scalable alternative. But the deeper contribution was the scaling laws: smooth power-law relationships between compute and downstream accuracy across more than two orders of magnitude of scale.

Closed CLIP vs. Open Reproduction

CLIP (left) is trained on closed data with a single released run — you can use it but not extrapolate. OpenCLIP (right) opens data, code, and a grid of runs, so you can fit a scaling curve and predict the next point. Click "Reveal grid" to populate the scaling sweep.

Closed vs open
PropertyOpenAI CLIP (2021)OpenCLIP (this paper)
Training dataWIT-400M (closed, never released)LAION-400M / 2B / 5B (open, downloadable)
Training codePartial; largest models closedopen_clip, fully open
Runs availableA few released checkpointsA grid sweeping model × data × compute
Scaling studyNot reproducible by outsidersPower-law fits across >2 orders of magnitude
Largest modelViT-L/14 (released)ViT-G/14, ~80% zero-shot ImageNet

Before we can study the scaling, we need to understand the object being scaled. CLIP is not a classifier. It is a pair of encoders that learn a shared embedding space for images and text. Let's build that up from zero.

What "zero-shot" actually means here

The phrase "zero-shot" is overloaded, so let's pin it down. A supervised ImageNet classifier has a fixed output head with exactly 1000 neurons — one per class. To recognize a new class it has never seen, you must add a neuron and fine-tune. CLIP has no output head. Instead, classification is reframed as retrieval: embed the image once, embed each candidate caption once, and pick the caption whose embedding is closest. New classes cost nothing but a new caption string. That is what makes the accuracy-vs-scale curve so interesting: the same pre-trained encoder is evaluated on dozens of downstream datasets without any task-specific training.

So the question the paper answers is not "how good is one model" but "how does the recipe behave as you pour in more compute." That is a far more useful thing to know, and it required the open pipeline to even ask.

What was the core obstacle that OpenCLIP set out to remove, and why did it matter scientifically?

Chapter 1: The Dual-Encoder Architecture

CLIP, and therefore OpenCLIP, is two networks that never share weights but learn to agree. One reads pixels; one reads text. Each maps its input into the same d-dimensional vector space, and training pulls matching image-text pairs together while pushing mismatched pairs apart.

Image encoder fI
A Vision Transformer (or ResNet) maps an image to a vector. ViT-B/32, ViT-L/14, ViT-H/14, ViT-G/14 are the rungs of the scaling ladder.
↓ both project into the SAME space
Text encoder fT
A causal Transformer reads the caption tokens; the final token's representation is the text vector.

Concretely, trace one batch of B image-text pairs through the network. Let d be the shared embedding dimension (512 for ViT-B, 768 for ViT-L, 1024 for ViT-H/G).

StepOperationTensor shape
Image inputB images, 224×224, RGB[B, 3, 224, 224]
Image encoderfI(image) then linear projection[B, d]
Text inputB captions, tokenized, padded to length L (77)[B, L]
Text encoderfT(tokens), take end-of-text token, project[B, d]
L2 normalizeeach row divided by its own norm[B, d], unit vectors
Similarity matriximage_emb · text_embT[B, B]

The two crucial design decisions live in the last two rows. First, L2 normalization: every embedding is divided by its own length, so it lands on the unit hypersphere. After this, the dot product between an image vector and a text vector is exactly their cosine similarity — a number in [−1, 1] that depends only on the angle between them, not their magnitudes. The model can no longer cheat by making "confident" pairs simply longer vectors; it must align their directions.

Second, the similarity matrix. With B images and B texts, every image is scored against every text, producing a B×B grid. The diagonal entries are the B correct pairs (image i with its own caption i); the off-diagonal entries are the B²−B mismatched pairs. This single matrix is the entire substrate of the loss — and it is why a large batch matters so much, as we'll see.

Why two encoders instead of one? A single network that takes both image and text as input (like a captioning model) must process every image-text pair jointly — O(B²) forward passes to score a batch. The dual-encoder embeds each image once and each text once — O(B) forward passes — then scores all B² pairs with a single cheap matrix multiply. This factorization is the whole reason contrastive pre-training scales to billions of pairs. Embeddings are computed once and reused across the entire batch.

A worked forward pass (tiny numbers)

Take d = 2 and B = 3 so we can do it by hand. Suppose after the encoders and L2 normalization we have:

image_emb = [[1, 0], [0.6, 0.8], [0, 1]]    text_emb = [[0.8, 0.6], [0, 1], [−0.6, 0.8]]

(Each row already has unit norm: 1²+0² = 1, 0.6²+0.8² = 0.36+0.64 = 1, and so on.) The raw similarity matrix S = image_emb · text_embT has entry Sij = cosine(image i, text j):

S = [[0.80, 0.00, −0.60], [0.96, 0.80, 0.28], [0.60, 1.00, 0.80]]

Read row 1: image 0 is most similar to text 0 (0.80) — good, that's the correct pair. Row 2: image 1 is most similar to text 0 (0.96), not its own text 1 (0.80) — a mistake the loss will punish. Row 3: image 2 is most similar to text 1 (1.00), not text 2 (0.80) — another mistake. An untrained model produces a messy S like this; training drives the largest value in each row onto the diagonal.

Two Encoders → One Similarity Matrix

Image embeddings (teal) and text embeddings (warm) on the unit circle. The B×B similarity matrix on the right is their pairwise cosine. Drag the slider to rotate the image embeddings toward their captions and watch the diagonal of the matrix brighten.

Alignment 0.15
Common misconception: "CLIP outputs a caption for an image." It does not. Neither encoder ever generates text — there is no decoder. CLIP only scores how well a given image and a given text match. To classify, you supply the candidate captions yourself ("a photo of a {class}") and CLIP ranks them. It is a matching engine, not a generator. The image encoder cannot describe a picture; it can only place it in the shared space.
python
import torch, torch.nn.functional as F

# B image-text pairs through the two encoders
img_feat  = image_encoder(images)   # [B, d]
txt_feat  = text_encoder(tokens)    # [B, d]

# L2-normalize: every row becomes a unit vector on the hypersphere
img_emb = F.normalize(img_feat, dim=-1)  # [B, d]
txt_emb = F.normalize(txt_feat, dim=-1)  # [B, d]

# Cosine similarity of EVERY image with EVERY text
S = img_emb @ txt_emb.T            # [B, B], entries in [-1, 1]
# diagonal = the B correct pairs; off-diagonal = the B^2 - B negatives
After L2-normalizing both image and text embeddings, what does the dot product between an image vector and a text vector measure, and why is that the right quantity?

Chapter 2: The Symmetric Contrastive Loss

Now the heart of the method — and the mechanism you'll implement in the Code Labs. We have the B×B similarity matrix S. We want to push every diagonal entry (correct pair) up and every off-diagonal entry (wrong pair) down. The tool for that is the InfoNCE loss (also called the contrastive loss), applied symmetrically across both axes.

Step 1: scale by the temperature

First we multiply S by a scalar called the logit scale. CLIP parameterizes it as exp(t) where t is learned, and we'll call τ the temperature with logit_scale = 1/τ. The scaled logits are:

L = (1/τ) · S     [B, B]

Cosine similarities live in [−1, 1] — far too flat to act as softmax logits, which would give an almost-uniform distribution. Multiplying by a large factor (a trained value of 1/τ around 100) spreads them out so the softmax can become sharp. We devote all of Chapter 3 to why this scalar matters so much; for now treat it as a knob that sharpens the distribution.

Step 2: read each row as a classification problem

Here is the key reframing. Look at row i of L: it contains the score of image i against every one of the B texts. We want the highest score to be at column i (its own caption). That is exactly a B-way classification problem where the correct class is i. So we apply softmax across the row and take the cross-entropy against the target label i:

pi→j = exp(Lij) / Σk exp(Lik)     lossimg = −(1/B) Σi log pi→i

In words: for each image, turn its row of similarities into a probability distribution over the B texts, and penalize the model by the negative log-probability it assigns to the correct text. This is the image-to-text loss — "given this image, find its caption."

Step 3: do it again the other way (the "symmetric" part)

By exactly the same logic, each column j of L is a classification problem: "given this text, find its image," with correct answer j. Apply softmax down the columns (equivalently, over the rows of LT) and cross-entropy against label j:

losstxt = −(1/B) Σj log [ exp(Ljj) / Σk exp(Lkj) ]

The final CLIP loss is the average of the two directions:

LCLIP = (lossimg + losstxt) / 2
Why symmetric? An image-to-text-only loss would happily put image i's caption at the top of its row while letting some other image also rank caption i first — the column would be ambiguous. Enforcing the constraint in both directions makes the correct pair the unique argmax of both its row and its column. The diagonal becomes a perfect bijection between images and texts. This is why CLIP uses the symmetric form and not a one-directional retrieval loss.

A fully worked example (B = 3, by hand)

Use the scaled logit matrix below (already multiplied by 1/τ). We'll compute the image-to-text loss completely.

L = [[4.0, 1.0, 0.0], [2.0, 3.0, 1.0], [0.0, 2.0, 5.0]]

Row 0 softmax: exponentials are e4=54.60, e1=2.72, e0=1.00; sum = 58.32. So p0→0 = 54.60/58.32 = 0.936. Loss contribution: −log(0.936) = 0.066.

Row 1: e2=7.39, e3=20.09, e1=2.72; sum = 30.20. p1→1 = 20.09/30.20 = 0.665. Contribution: −log(0.665) = 0.408.

Row 2: e0=1.00, e2=7.39, e5=148.41; sum = 156.80. p2→2 = 148.41/156.80 = 0.947. Contribution: −log(0.947) = 0.055.

Average: lossimg = (0.066 + 0.408 + 0.055)/3 = 0.176. Row 1 dominates the loss because the model is least confident there (image 1 scores 2.0 on text 0, almost as high as 3.0 on its correct text 1). The gradient will push image 1's embedding away from text 0 and toward text 1. Doing the same column-wise gives losstxt, and the reported loss is their average.

From Similarity Matrix to Loss

Left: the scaled logit matrix L. Middle: row-softmax (image→text) probabilities — the diagonal is what we want to maximize. Right: the per-row negative log-likelihood. Slide the temperature knob to see sharp vs. flat distributions and how the loss responds.

logit scale 1/τ 2.0
python
import torch, torch.nn.functional as F

def clip_loss(img_emb, txt_emb, logit_scale):
    # img_emb, txt_emb: [B, d], already L2-normalized
    logits = logit_scale * img_emb @ txt_emb.T   # [B, B]
    B = logits.shape[0]
    labels = torch.arange(B, device=logits.device)  # target = diagonal
    # image->text: each ROW is a B-way classification, answer = i
    loss_i = F.cross_entropy(logits, labels)
    # text->image: each COLUMN is a B-way classification, answer = j
    loss_t = F.cross_entropy(logits.T, labels)
    return (loss_i + loss_t) / 2

Notice how compact this is. The labels are simply arange(B) — the diagonal — because the i-th image's correct text is at index i by construction. The entire contrastive objective is two cross-entropies over a B×B matrix. That simplicity is what let it scale to billions of pairs.

Common misconception: "The negatives need to be hand-picked hard examples." They don't. In CLIP the negatives are simply the other captions in the same batch — they're free. Image i's negatives are the B−1 other texts that happen to be sampled alongside it. This is why batch size doubles as the negative count: a batch of 32,768 gives every image 32,767 in-batch negatives at no extra labeling cost. The loss is "find your partner in this random crowd," and the crowd is the batch.
In the CLIP loss, where do the "negative" examples for each image come from?

Chapter 3: Temperature & the Power of a Big Batch

Two scalars dominate contrastive training in ways that surprise people the first time: the temperature τ and the batch size B. Both are about the same thing — how sharply the model is forced to discriminate — and OpenCLIP's scaling depended on getting both right.

Temperature: a learned sharpness knob

Recall the loss uses logits L = (1/τ)·S where S is cosine similarity in [−1, 1]. The factor 1/τ is the logit scale. If τ is large (logit scale small, say 1), the softmax over a row is nearly uniform — even the correct pair gets only a slightly higher probability, so the loss can't distinguish good from bad alignment. If τ is tiny (logit scale huge, say 1000), the softmax becomes one-hot — the model bets everything on its top guess, and a single mistake produces a gigantic loss, making training unstable.

CLIP learns τ rather than fixing it. It parameterizes logit_scale = exp(t) with t a trainable parameter, and clamps it so that logit_scale ≤ 100 (i.e. τ ≥ 0.01) to prevent it from collapsing to a degenerate one-hot regime. Empirically t converges so that 1/τ sits near 100 — a sweet spot where the softmax is sharp enough to separate the diagonal but smooth enough to keep gradients well-behaved.

Why parameterize as exp(t)? The logit scale must stay strictly positive (a negative scale would reward mismatches). Optimizing t in log-space and exponentiating guarantees positivity automatically, and makes multiplicative changes in the scale correspond to additive steps in t — which gradient descent handles gracefully. The clamp at exp(t) = 100 is a guardrail against the loss driving the scale to infinity early in training.

Worked example: same matrix, two temperatures

Take a single row of cosine similarities S = [0.4, 0.1, 0.0] where index 0 is correct. At logit scale 5 the logits are [2.0, 0.5, 0.0]; softmax = [0.74, 0.17, 0.09], so −log(0.74) = 0.30. At logit scale 25 the logits are [10, 2.5, 0]; softmax ≈ [0.9994, 0.0006, 0.0001], so −log(0.9994) = 0.0006. Same embeddings, same cosines — but the higher scale makes the model far more confident, and therefore far more sensitive to any residual error. The gradient signal on the off-diagonal entries is proportionally larger, which is what drives faster separation early in training.

Batch size = number of negatives

The other lever is B. Each image is contrasted against the B−1 other texts in its batch. A larger batch gives each image a harder, more informative discrimination task: it must stand out not against 255 distractors but against 32,767. The expected loss of pure guessing is log(B), so as B grows the model is solving a strictly harder classification, and the representations it learns are correspondingly more discriminative.

This is why CLIP-style training uses enormous global batch sizes — 32k and beyond — assembled across many GPUs. OpenCLIP pushed batch sizes to tens of thousands and found this essential for the largest models. The catch: the B×B logit matrix and the all-gather of embeddings across GPUs make very large batches a systems-engineering problem, not just a hyperparameter.

Temperature Sharpens, Batch Size Hardens

Top: a row of cosine similarities turned into a softmax distribution; slide the logit scale to watch it go from flat to one-hot. Bottom: the expected loss of pure guessing, log(B), rising with batch size — a larger batch is a harder, more informative task.

logit scale 10
KnobToo smallToo largeCLIP's choice
1/τ (logit scale)Flat softmax, weak gradient, can't separateOne-hot softmax, exploding loss, unstableLearned via exp(t), clamped ≤ 100
Batch BFew negatives, easy task, weak featuresMemory + all-gather cost across GPUsTens of thousands, sharded across devices
Common misconception: "Temperature is just a fixed hyperparameter you tune by grid search." In CLIP it is a learned parameter — the network adjusts its own confidence during training. Hard-coding a bad temperature can stall training entirely, but letting it learn (in log-space, clamped) lets the model find its own sharpness as the embeddings improve. Early on the embeddings are noisy and a smaller scale is safer; as they sharpen, the learned scale rises toward its clamp.
python
import torch, torch.nn as nn, numpy as np

# logit_scale is a learned parameter, initialized to log(1/0.07) ~ 2.66
logit_scale = nn.Parameter(torch.tensor(np.log(1/0.07)))

# in the forward pass, exponentiate and clamp so 1/tau never exceeds 100
scale = logit_scale.exp().clamp(max=100.0)
logits = scale * img_emb @ txt_emb.T   # [B, B]
Why does CLIP both learn the logit scale in log-space (as exp(t)) and clamp it to at most 100?

Chapter 4: Zero-Shot Transfer — the Evaluation

The whole point of pre-training is what you can do without further training. CLIP turns classification into retrieval, and that conversion is worth understanding precisely because it is how every number in the scaling-law plots was measured.

How a contrastive model classifies

To classify an image among C candidate classes (say the 1000 ImageNet classes), you do not add a head. Instead:

1. Build text prompts
For each class name c, form a caption: "a photo of a {c}". Embed all C prompts once with the text encoder → a [C, d] matrix of class embeddings.
2. Embed the image
Run the image through the image encoder → one [d] vector, L2-normalized.
3. Pick the closest
Cosine-similarity the image vector against all C class embeddings → [C] scores. The argmax is the predicted class.

The class text embeddings act as a weightless classifier head: you compute them once and reuse them for the whole test set. Swapping to a different dataset means swapping the prompts, not retraining. This is precisely what makes a single pre-trained OpenCLIP model directly comparable across dozens of downstream tasks — and therefore what makes a clean scaling law possible.

Prompt engineering and ensembling

The exact wording of the prompt matters. "a photo of a {c}" beats the bare class name "{c}" because the pre-training captions were natural sentences, not isolated words — the prompt nudges the text embedding into the same distribution the model saw during training. CLIP further uses prompt ensembling: embed each class under many templates ("a photo of a {c}", "a blurry photo of a {c}", "a sculpture of a {c}", …), then average the resulting text vectors before normalizing. Averaging cancels template-specific noise and reliably adds a point or two of accuracy.

Worked example: a 3-class decision

Image vector v = [0.6, 0.8] (already normalized). Three class embeddings: cat = [0.7, 0.7], dog = [0.0, 1.0], car = [−0.9, 0.4] (each near unit norm). Cosine scores: v·cat = 0.6(0.7)+0.8(0.7) = 0.42+0.56 = 0.98; v·dog = 0+0.8 = 0.80; v·car = −0.54+0.32 = −0.22. The argmax is cat (0.98). Apply softmax with logit scale 100 and the model is essentially certain. No ImageNet labels were ever touched — the decision came entirely from the shared embedding space.

Zero-Shot Classification as Nearest Caption

An image embedding (warm dot) and several class-prompt embeddings (teal dots) on the unit circle. The predicted class is the nearest one. Drag the image around the circle and watch the prediction flip as it crosses the decision boundaries.

image angle 50°
Common misconception: "Zero-shot means the model gets no information about the task." It does get information — through the class names you supply as prompts. CLIP knows what "a photo of a golden retriever" means because such captions appeared in pre-training. What's zero is the number of labeled training images for the task. The supervision is the natural-language prompt, not a gradient step. Picking good prompt wording is itself a (label-free) part of the recipe.
python
import torch, torch.nn.functional as F

# Build the weightless classifier head once
classes = ["cat", "dog", "car"]
prompts = [f"a photo of a {c}" for c in classes]
text_emb = F.normalize(text_encoder(tokenize(prompts)), dim=-1)  # [C, d]

# Classify a new image with no training
img_emb = F.normalize(image_encoder(image), dim=-1)   # [1, d]
scores  = (img_emb @ text_emb.T)                       # [1, C] cosines
pred    = classes[scores.argmax()]                   # nearest caption
In zero-shot CLIP classification, what plays the role of the "classifier weights" that a supervised network would learn?

Chapter 5: Scaling Laws for Contrastive Learning

Here is the paper's central scientific contribution. Once you can train the same recipe at many scales, you can ask: how does downstream accuracy depend on how much you spend? The answer, across more than two orders of magnitude, is a power law.

The shape of the law

Let C be the total training compute (roughly: model size × number of samples seen), and let E be the downstream error (1 − accuracy). The empirical finding is that error falls as a power of compute:

E(C) ≈ β · C−α + E

Three pieces. β sets the overall height. The exponent α (a small positive number) is the slope on a log-log plot — it says how fast error drops as you add compute. E is an irreducible floor: the error you'd have with infinite compute, set by label noise and the intrinsic difficulty of the task. On a log-log axis, the power-law part is a straight line with slope −α, which is why these plots look so clean and so predictive.

Why a straight line on log-log? Take logs of E ≈ βC−α: log E = log β − α log C. That is a line in (log C, log E) coordinates with slope −α and intercept log β. So if you plot accuracy-error against compute on log-log axes and see a straight line, you have empirically confirmed a power law — and you can read α straight off the slope. Two trained points on that line are enough to extrapolate to a third you haven't paid for.

The crucial caveat: data distribution sets the exponent

The most cited finding of the paper is not that scaling laws exist — Kaplan and Hoffmann had shown that for language models. It is that the scaling exponent depends on the training data distribution. OpenCLIP found that models trained on LAION (open) and models trained on WIT (OpenAI's closed set) scale along different power laws, and which one is "better" flips depending on the downstream task. Roughly: OpenAI's CLIP had a steeper improvement on ImageNet-style classification, while LAION-trained models scaled better on retrieval tasks. The data, not just the model, controls the slope.

This is a deep point. It means you cannot speak of "the" scaling law for contrastive learning. There is a scaling law for a given dataset evaluated on a given task. Bigger models help, more data helps, more compute helps — but the rate of help is a property of the data distribution you train on. Choosing the dataset is choosing your slope.

Bottleneck analysis: which axis is starved?

Scaling has three axes — model size, dataset size, and samples seen (compute) — and a model can be bottlenecked on any one. If you grow the model but freeze the data, accuracy plateaus: you've saturated what the data can teach. If you grow the data but freeze the model, the model can't absorb it. The paper's grid lets you read off which axis is the binding constraint at each scale, and the practical guidance is to grow all three roughly in concert.

Power-Law Fit on Log-Log Axes

Synthetic scaling points (dots) and a fitted power law (line). On a log-log plot the law is a straight line of slope −α. Slide the exponent and watch the line tilt — steeper means each unit of compute buys more accuracy. The dashed floor is the irreducible error E∞.

exponent α 0.28
Scaling axisWhat it controlsSymptom of bottleneck
Model size (ViT-B→L→H→G)Capacity to absorb patternsLoss plateaus though data is plentiful
Dataset size (400M→2B→5B)Diversity of patterns availableBigger model stops helping
Samples seen (compute)How many gradient steps over the dataCurve still descending — undertrained
Common misconception: "A scaling law lets you predict accuracy from compute, full stop." Only within one data distribution and one task. OpenCLIP's headline result is that the exponent itself changes when you change the training set — so extrapolating an ImageNet curve fit on WIT to a LAION model is invalid. The law is conditional on (dataset, task), not universal. This is the single most misquoted finding of the paper.
What is the most important and most-misquoted finding of OpenCLIP's scaling study?

Chapter 6: Data Scale, Curation & Deduplication

A scaling study is only as trustworthy as its data. If your test images leak into your training set, every accuracy number is inflated. OpenCLIP put real engineering into building LAION and into proving the scaling wasn't an artifact of contamination.

How LAION was built

LAION (Large-scale Artificial Intelligence Open Network) datasets are filtered from Common Crawl. The pipeline: extract every <img> tag with a non-empty alt attribute (the alt-text is the "caption"), then filter by CLIP itself — keep only pairs whose existing-CLIP cosine similarity exceeds a threshold (around 0.28 for the English subset). This bootstraps quality from a weaker model: pairs where the image and its alt-text already roughly agree are kept; random or broken alt-text is dropped. The result is LAION-400M, then LAION-2B (the English subset of the multilingual LAION-5B).

The bootstrap trick: You can't hand-label two billion images. So you use a pre-existing CLIP as a cheap, automatic quality filter: it scores each candidate image-text pair and you keep the agreeable ones. The new, larger CLIP trained on this filtered data then surpasses the filter that built it. Quality is bootstrapped from scale — a noisy automatic filter over billions of pairs beats a clean hand-labeled set of millions.

Why deduplication is non-negotiable

Common Crawl is full of near-duplicate images, and some of them are the very ImageNet validation images you evaluate on. If "test" images sit in "train," zero-shot accuracy is no longer zero-shot — the model has effectively seen the answer. OpenCLIP therefore ran deduplication: compute a perceptual/embedding hash of every training image, find near-duplicates of the evaluation sets, and remove them. The critical experiment is to retrain with the overlap removed and confirm the accuracy barely moves. It did, which means the scaling gains are real generalization, not memorized test images.

Worked example: how much can dedup matter?

Suppose 1.0% of your training set are near-duplicates of test images, and the model gets those "seen" examples right 99% of the time vs. 75% for genuinely novel ones. The inflation to a measured 76% accuracy is approximately 0.01×(0.99−0.75) = 0.0024, i.e. about a quarter of a point — small here, but it grows with the contamination fraction and is exactly the kind of effect that can manufacture a fake "scaling" trend if it correlates with dataset size. The only way to know it's small is to measure it by retraining deduplicated, which is what the paper did.

Dataset Filtering & Dedup Pipeline

Common Crawl → alt-text pairs → CLIP-score filter → dedup against eval sets. Click a stage to see how many pairs survive it. The thin red sliver is the near-duplicate overlap that must be removed before any accuracy is trusted.

Stage 0/4 — raw crawl
DatasetPairsFilterRole in the study
LAION-400M~400 millionCLIP cosine > threshold, EnglishReproduces original CLIP's data scale
LAION-2B~2 billionEnglish subset of LAION-5BThe workhorse for the largest models (ViT-G/14)
LAION-5B~5 billionMultilingual, full crawlThe full-scale open dataset
Common misconception: "More data is unconditionally better." Not without dedup and not without distribution-awareness. Raw web scale brings (1) test-set contamination that inflates scores and (2) a fixed data distribution that sets your scaling exponent. OpenCLIP's careful deduplication is what lets the scaling claims survive scrutiny — and its data-distribution finding (Chapter 5) is what keeps "scale is all you need" honest. Scale helps along the slope your data gives you, on tests your data didn't leak.
python
# LAION-style filtering: keep pairs an existing CLIP already finds agreeable
import torch, torch.nn.functional as F

img_emb = F.normalize(clip_image(image), dim=-1)
txt_emb = F.normalize(clip_text(alt_text), dim=-1)
sim     = (img_emb * txt_emb).sum(-1)        # cosine
keep    = sim > 0.28                          # English-subset threshold

# Dedup: drop training images that near-match any eval image
h_train = perceptual_hash(image)
contaminated = h_train in eval_hash_set      # remove before training
Why is deduplication against the evaluation sets essential to OpenCLIP's scaling claims?

Chapter 7: Headline Results & Ablations

With the recipe, the loss, and the data understood, what did the runs actually show? The numbers below are the load-bearing claims of the paper.

The flagship number

An OpenCLIP ViT-G/14 trained on LAION-2B reached roughly 80% zero-shot top-1 on ImageNet. This is the result that mattered most politically: an entirely open pipeline — open data, open code, open weights — matched and surpassed OpenAI's closed CLIP (whose released ViT-L/14 sat in the high-70s). The open ecosystem was no longer a second-class imitation; it was the frontier.

ModelDataZero-shot ImageNet top-1 (approx.)
OpenAI CLIP ViT-B/32WIT-400M~63%
OpenAI CLIP ViT-L/14WIT-400M~75%
OpenCLIP ViT-B/32LAION-2B~66%
OpenCLIP ViT-L/14LAION-2B~75%
OpenCLIP ViT-H/14LAION-2B~78%
OpenCLIP ViT-G/14LAION-2B~80%

(These figures are approximate and depend on training duration; treat them as the shape of the ladder, not exact decimals.) The point is the monotone climb: each rung — more parameters, more samples seen, more data — buys a predictable increment of accuracy, exactly as the power law promises.

Beyond ImageNet: robustness and transfer

The paper evaluated zero-shot across dozens of datasets, not just ImageNet. Two patterns stand out. First, robustness: OpenCLIP models held up well on distribution-shifted ImageNet variants (ImageNet-R, ImageNet-Sketch, ObjectNet), where supervised models often collapse — a known strength of contrastive pre-training on diverse web data. Second, task-dependence of scale: the relative ranking of LAION- vs WIT-trained models flipped between classification and retrieval, the empirical core of the data-distribution finding from Chapter 5.

What the ablations isolated

The careful, reproducible grid let the authors attribute gains to specific axes rather than to a lucky run:

LeverEffect when scaled up
Model size (B→L→H→G)Smooth accuracy gain, provided data and samples scale too
Samples seen (3B→13B→34B)Major gains; undertraining a large model wastes its capacity
Dataset (400M→2B)Larger, more diverse data lifts and steepens the curve
Batch sizeLarger batches (more negatives) help, especially for big models
Data distributionSets the scaling exponent itself — the headline finding
The Scaling Ladder

Approximate zero-shot ImageNet top-1 for the OpenCLIP model rungs. Each bar is a bigger model trained on LAION-2B. Click a bar to see the parameter count and embedding dimension. The climb is the power law made visible.

ViT-B/32 — ~66%
Common misconception: "OpenCLIP just retrained CLIP and got the same number." It produced a family of models spanning more than two orders of magnitude of compute, the largest of which (ViT-G/14) surpassed the closed original — and, more importantly, it measured how accuracy moves with scale. The deliverable wasn't one model; it was a calibrated map of the entire scaling regime that anyone can extend.
What did the largest OpenCLIP model (ViT-G/14 on LAION-2B) demonstrate beyond just achieving high accuracy?

Chapter 8: The Scaling Explorer

This is the payoff — the paper's central mechanism made fully interactive. Train a (simulated) OpenCLIP by choosing a model size, a dataset, and a compute budget. The explorer computes the implied zero-shot accuracy from a power law whose exponent depends on the dataset you pick — the paper's key finding — and shows you the contrastive batch the model is learning from underneath.

Watch two things as you slide the controls. (1) The accuracy gauge climbs along the power law; doubling compute moves you a fixed step along the log-log line, not a fixed number of points. (2) The similarity matrix on the right sharpens its diagonal as effective training increases — more negatives and more compute make the model better at putting each image's caption on the diagonal. (3) Switch the dataset and the slope changes: the same compute buys a different accuracy because the data distribution sets the exponent.

OpenCLIP Scaling Explorer

Pick model size, dataset, and compute. Left: the projected accuracy on its power-law curve. Right: a live contrastive similarity matrix whose diagonal sharpens with effective training. Notice how switching the dataset tilts the curve — that is the data-distribution-sets-the-exponent finding.

model
dataset
compute (samples seen) ViT-B · LAION-400M

The explorer encodes the three lessons of the paper in one picture. Model size shifts which curve you're on. Dataset choice tilts the curve's slope (the exponent). Compute slides you along it. And the matrix reminds you what is actually being optimized the whole time: a symmetric contrastive objective pushing the diagonal up and everything else down. Scale is not magic — it is moving along a measured line, on a slope your data picked.

Reading the explorer like the paper: Put the model on ViT-G and sweep compute on LAION-2B — you trace the flagship ~80% run. Now switch the dataset to WIT-400M at the same model and compute: the accuracy lands on a different point because the slope changed. That single switch is the whole "data distribution sets the exponent" result, which no closed-data study could have shown.

Chapter 9: Limitations & Connections

OpenCLIP changed what the open community could do, but it inherits real limits — and pointing them out honestly is part of understanding the contribution.

Limitations

LimitationWhy it bites
Data quality & biasLAION is unfiltered web alt-text; it carries the web's biases, NSFW content, and toxic associations into the model. Open data is not clean data.
Compute costThe largest runs cost hundreds of thousands of GPU-hours and tens-of-thousands batch sizes — reproducible in principle, expensive in practice.
Power laws saturateThe E∞ floor is real: past some scale, each doubling of compute buys vanishingly little. Scaling is not free accuracy forever.
Exponent is conditionalA scaling law fit on one dataset/task does not transfer — you must re-measure for your distribution and your evaluation.
No generationCLIP only matches; it cannot caption, segment, or detect without bolting on extra heads.
Contrastive ceilingThe dual-encoder factorization that makes scaling cheap also prevents fine-grained image-text interaction (every pair scored by one dot product).

Where it led

OpenCLIP became the default vision backbone for the open generative era. Stable Diffusion's text conditioning uses an OpenCLIP text encoder; countless retrieval, captioning, and VLM systems build on OpenCLIP image features. The open_clip library and the LAION datasets turned "train your own CLIP" from an OpenAI-only capability into a community one. The data-distribution finding directly motivated later data-centric work (DataComp, MetaCLIP) that scales the dataset curation rather than just the model.

Connections on Engineermaxxing

The Transformer that powers both of CLIP's encoders — self-attention, multi-head, positional encoding.
The original Radford et al. CLIP, built from zero — the model OpenCLIP reproduces and scales.
The shared vector space and cosine similarity that the dual-encoder learns to align.
Power-law fits, exponents, and irreducible error — the framework this paper applies to contrastive learning.
The ViT-B/L/H/G image encoder that is the rungs of OpenCLIP's scaling ladder.

The cheat sheet

ConceptOne-line summary
OpenCLIPOpen reproduction of CLIP on LAION; measures contrastive scaling laws.
Dual-encoderSeparate image & text encoders mapping into one shared, L2-normalized space.
Similarity matrixB×B cosines; diagonal = correct pairs, off-diagonal = in-batch negatives.
Symmetric InfoNCECross-entropy over rows (image→text) + columns (text→image), averaged.
Logit scale 1/τLearned via exp(t), clamped ≤ 100; sharpens the softmax.
Batch = negativesEach image's negatives are the other captions in the batch (free).
Zero-shotClassify by embedding class prompts and picking the nearest — no labeled images.
Scaling lawError ≈ βC−α + E∞; straight line of slope −α on log-log.
Key findingThe exponent α depends on the training data distribution and the task.
DedupRemove eval near-duplicates so zero-shot stays honest.
FlagshipViT-G/14 on LAION-2B, ~80% zero-shot ImageNet, surpassing closed CLIP.
The closing idea: OpenCLIP's gift was not a model but a measurement. By opening the entire pipeline and training a grid that spans orders of magnitude, it turned "scale works for CLIP" from folklore into a calibrated, extrapolatable law — while showing that the law's slope is something you choose when you choose your data. Reproducibility is not bureaucracy; it is what lets a result become science you can build on.