18

From text to image

How does the model understand what you ask for in words?

13 min

From text to image

With voice. You can pause and jump to any step.

Lesson complete

Subtitles

You type “an astronaut cat” and, in seconds, a program hands you an image nobody drew. How does it turn a sentence into an image?

Voice

No voice: the lesson advances on its own with subtitles.

The voice for this lesson is being recorded: for now it advances on its own with subtitles.

0:00 / 0:00

What you will achieve

  • Explain how CLIP trains an image encoder and a text encoder together so each image lands close to its sentence, by reading the similarity table and its diagonal.
  • Describe how the sentence’s vector conditions diffusion, and predict what happens to faithfulness and variety as the guidance scale goes up.
  • Recognize the limits of these models (amplified biases, never-seen combinations, what goes with what, counting and writing) and the risks around rights, impersonation, and provenance.

Key ideas

  1. CLIP trains an image encoder and a text encoder together. Both output vectors of the same size, compared with cosine similarity.
  2. Training is contrastive: in each batch, the similarity table must light up its diagonal (the correct pairs) and dim the rest. No hand labels are needed, just images with their sentences.
  3. To generate from text, the diffusion network gets an extra input: the sentence’s vector. That is conditioning. The prompt is that sentence, and the model only understands the words it saw during training.
  4. Classifier-free guidance predicts the noise with and without the sentence and exaggerates the difference by the guidance scale: more scale, more faithfulness and less variety; too much distorts.
  5. Models inherit and amplify the biases in their data, do worse on the never-seen, can mix up what goes with what, and struggle to count and write. Their data raises questions about rights, and their images about impersonation and provenance.

What many people believe

Common belief An image generator understands the sentence the way a person does: if the words are written correctly, it draws exactly what you asked for.

What is true It turns the sentence into a vector learned from image-and-text pairs, and diffusion is guided by that vector. Whatever was missing from its data (words, combinations, quantities, letters) it handles poorly, and whatever was frequent in its data it repeats too much.

Check yourself

Four questions. No grade, no account: they just show whether the idea stuck.

ConceptWhat does CLIP learn during training?
ConceptYou raise the guidance scale from one to three with the same prompt. What do you expect?
CalculationAt one step, the network predicts 0.2 without the sentence and 0.5 with it. With guidance scale 3, what value is used?
ApplicationYour team generates illustrations with the prompt “a nurse caring for a patient,” and almost all of them show a young woman. What is the most appropriate response?

Under the hoodFor those who want the math and the code. You do not need it to follow the course.

CLIP’s contrastive loss

In a batch of NN pairs, the image encoder ff and the text encoder gg produce unit vectors ui=f(xi)u_i = f(x_i) and vj=g(tj)v_j = g(t_j). Their cosine similarity is Sij=ui⋅vjS_{ij} = u_i \cdot v_j. These are divided by a temperature τ\tau (also learned), and cross-entropy asks each image to pick its own sentence and each sentence to pick its own image:

L=12N∑i=1N[−ln⁡eSii/τ∑jeSij/τ  −ln⁡eSii/τ∑jeSji/τ]\mathcal{L} = \frac{1}{2N}\sum_{i=1}^{N}\Big[-\ln\frac{e^{S_{ii}/\tau}}{\sum_j e^{S_{ij}/\tau}} \; - \ln\frac{e^{S_{ii}/\tau}}{\sum_j e^{S_{ji}/\tau}}\Big]

This is the symmetric loss from Radford and colleagues’ paper (Figure 3): it raises the diagonal of the table SS and lowers the rest of its row and column. CLIP used batches of 32,768 pairs, that is, tables of more than a billion cells at every step, and about 400 million image-and-text pairs gathered from publicly available sources on the internet. The model card is dated January 2021.

In our toy, the image encoder receives 720 numbers (12 × 12 pixels, each with 5 one-hot color slots) and has a hidden layer of 96; the text encoder reads 5 word positions, each word with a 16-number vector plus a vector for its position, and has a hidden layer of 64. Both output D=32D = 32. It trained for 2,500 steps with batches of 96; the temperature went from 1/τ≈14.31/\tau \approx 14.3 to 22.022.0. In the fixed six-pair batch the scene shows, the diagonal ends between 0.78 and 0.88. The batch error does not reach zero with batches of 96: many incomplete sentences (“circle”) repeat within the same batch and cannot tell their images apart.

Conditioning and guiding

The diffusion network predicts the noise ϵθ(zt,t,c)\epsilon_\theta(z_t, t, c) of a 16-number latent ztz_t, at step tt, given the sentence vector cc. During training, the sentence is replaced with the empty sentence ∅\varnothing 10% of the time (as in Stable Diffusion v1-4). When sampling, with guidance scale ss:

ϵ^=ϵθ(zt,t,∅)+s [ϵθ(zt,t,c)−ϵθ(zt,t,∅)]\hat\epsilon = \epsilon_\theta(z_t, t, \varnothing) + s\,\big[\epsilon_\theta(z_t, t, c) - \epsilon_\theta(z_t, t, \varnothing)\big]

With s=0s = 0 the sentence does not count; with s=1s = 1 it is the plain conditional network; with s>1s > 1 it is exaggerated. This is the convention of the diffusers library (default scale 7.5, “enabled when greater than 1”). Ho and Salimans write the same thing as (1+w) ϵc−w ϵ∅(1+w)\,\epsilon_c - w\,\epsilon_\varnothing, with w=s−1w = s - 1, and present it as a trade-off between sample quality and diversity. GLIDE (Nichol and colleagues, 2021) already used it with text, and human evaluators preferred it to CLIP guidance.

Our sampler follows the lesson 17 recipe: T=40T = 40 steps, βt\beta_t linear from 0.02 to 0.30, and reverse-step variance σt2=βt\sigma_t^2 = \beta_t. The latent comes from a 16-number VAE and is decoded at the end. Stable Diffusion conditions differently (cross-attention over the per-word vectors from CLIP’s text encoder); here, to fit in the browser, the sentence vector is appended to the input of a three-layer network.

What the scene measured

  • Guidance scale with “circle” (256 starting noises): circles 36% at s=0s = 0, 80% at s=1s = 1, 95% at s=2s = 2, 93% at s=4s = 4, and 63% at s=8s = 8. The scene’s twenty-four images (seeds 1000 to 1023, prompt “circle”) give 11, 20, 23, and 13 circles at s=0,1,3,8s = 0, 1, 3, 8, and 18, 11, 6, and 8 distinct combinations of shape, color, and background (with the Spanish prompt «círculo»: 11, 19, 21, and 16 circles; 18, 12, 7, and 7 combinations).
  • Bias: in the data, 64.9% of circles are magenta (one image in two gets its shape’s typical color, the other a random one). Among the twenty-four images, 15 are magenta at s=1s = 1 and 22 at s=3s = 3.
  • The never-seen (ten combinations left out of training, 16 noises per combination, s=3s = 3): 86.4% correct on the 70 seen combinations and 75.6% on the 10 never-seen ones. At s=1s = 1 the gap is wider: 85.6% versus 45.6%.
  • What goes with what (60 pairs with swapped colors, in both languages): the encoder that reads word order picks the right sentence 100% of the time; the bag of words gives exactly the same vector to both sentences (0%: always a tie).

The shape and color counts come from a fixed-rule reader, not a learned one: the background is the most common color along the border, the shape is the rest, and the shape type is the template (circle, square, triangle, or cross, at several positions and sizes) that overlaps best; if none exceeds 0.6 intersection over union, the image counts as “no shape.” It reads all 20 real images in the lesson correctly. It is less reliable with squares: the model often draws them with rounded corners and the reader takes them for circles, so the scene does not use them for counting.

In code

import numpy as np

def contrastive_loss(U, V, tau=0.07):
    """U, V: unit vectors of N images and N sentences (row i = pair i)."""
    S = U @ V.T / tau
    S = S - S.max(axis=1, keepdims=True)
    rows = -np.mean(np.diag(S) - np.log(np.exp(S).sum(axis=1)))
    S2 = (U @ V.T / tau).T
    S2 = S2 - S2.max(axis=1, keepdims=True)
    cols = -np.mean(np.diag(S2) - np.log(np.exp(S2).sum(axis=1)))
    return (rows + cols) / 2

rng = np.random.default_rng(0)
U = rng.normal(size=(4, 8)); U /= np.linalg.norm(U, axis=1, keepdims=True)
V_random = rng.normal(size=(4, 8)); V_random /= np.linalg.norm(V_random, axis=1, keepdims=True)
V_good = U + 0.1 * rng.normal(size=(4, 8)); V_good /= np.linalg.norm(V_good, axis=1, keepdims=True)
print(round(contrastive_loss(U, V_random), 3), round(contrastive_loss(U, V_good), 6))

def guidance(e_without, e_with, s):
    return e_without + s * (e_with - e_without)

e_without, e_with = np.array([0.2, -0.4]), np.array([0.5, 0.1])
for s in (0, 1, 3):
    print(s, guidance(e_without, e_with, s))
# 6.064 0.000141
# 0 [ 0.2 -0.4]
# 1 [0.5 0.1]
# 3 [1.1 1.1]

With random sentences the error is high; with sentences almost identical to their image, the diagonal dominates and the error falls to nearly zero. The second function is the whole guidance scale.

What comes next

Here text only went in: it was turned into a vector. In lesson 19 text comes out: a language model assigns probabilities to the next word and writes one word after another.

Decision lens

What this idea means if your job is to decide, not to code.

  • Provenance and rights: ask what data the model was trained on, under what licenses, and what the vendor covers if there is a claim. The U.S. Copyright Office reported in 2025 dozens of pending lawsuits over using works for training; the legal answer is not settled yet.
  • Impersonation: have your policy forbid generating images of real people without their consent, review what gets published, and never accept an image alone as proof. Mark what you publish: C2PA content credentials and, if the vendor offers it, a watermark.
  • Bias: the model repeats, and with guidance exaggerates, whatever is frequent in its data. Audit with many images per prompt (not one), especially when people appear, and check who is shown and how.
  • Control and reproducibility: keep the prompt, seed, and guidance scale of every image you use. More guidance is not always better: it reduces variety and, pushed too far, distorts.

Terms in this lesson

Full transcript
CommentsThis lesson’s public conversation: questions, facts to check, ideas.

Comments live in GitHub Discussions, in the course’s public repository; writing one requires a GitHub account. They load from giscus.app when you open this section. The course reviewers read them, and if a change is accepted, it is applied in both languages. Open the thread on GitHub

Sources