Hoppa till innehållet
AI-grafen
F· AI engineeringdatorseende· ca 90 min· volatil — kontrolleras ofta· verifierad 2026-09-20

CLIP och kontrastiv bild–text-inlärning

Kunna förklara kontrastiv förlust och använda CLIP för zero-shot-klassificering.

Förkunskaper

Intuition

CLIP tränades på 400 miljoner (bild, text)-par från webben med en enda, förvånansvärt enkel uppgift: para ihop rätt bild med rätt bildtext inom batchen.

Ta 32 768 par. Koda alla bilder och alla texter. Bygg likhetsmatrisen — 32 768 × 32 768. Rätt svar ligger på diagonalen. Träna med korsentropi över raderna och över kolumnerna.

Det låter som en kuriositet. Men eftersom bildtexterna på webben beskriver allt — objekt, stilar, platser, känslor, skisser, memes — lär sig modellen ett rum där nästan vilket begrepp som helst har en riktning.

Och det ger något som inte gick förut: zero-shot-klassificering. Vill du skilja på 200 fågelarter skriver du 200 meningar och kodar dem. Ingen träning, inga märkta bilder.

Formellt

Den symmetriska förlusten. Med bildvektorer II och textvektorer TT, båda L2-normaliserade, och inlärd temperatur τ\tau:

S=IT⊤τ,L=12[CE(S,y)+CE(S⊤,y)],y=(0,1,…,N−1)S = \frac{I T^\top}{\tau}, \qquad \mathcal{L} = \tfrac{1}{2}\left[\mathrm{CE}(S, y) + \mathrm{CE}(S^\top, y)\right], \quad y = (0, 1, \dots, N-1)

Tre designval som spelar roll:

  1. Normaliseringen gör skalärprodukten till cosinuslikhet, begränsad till [−1,1][-1, 1]. Utan den exploderar logitsen.
  2. Temperaturen lärs in (som log⁡1/τ\log 1/\tau, klippt vid 100) och hamnar runt 0,01 — en skarp fördelning.
  3. Batchen är negativexemplen. Därav den stora batchstorleken; distribuerad träning samlar in vektorer från alla GPU:er innan matrisen byggs.

Promptteknik spelar oväntat stor roll. «katt» är sämre än «ett foto av en katt», som är sämre än ett medelvärde över ett 80-tal mallar («ett suddigt foto av en {}», «en skiss av en {}» …). Skillnaden är flera procentenheter — träningsdatans bildtexter är hela meningar, inte lösryckta ord.

Svagheter, och hur du mäter dem på din egen data:

SvaghetTest
Kompositionalitetlikhet mellan «A jagar B» och «B jagar A»
Räkning«tre X» mot «fem X» på bilder med känt antal
Text i bilderen bild av ordet «äpple» klassas ofta som äpple
Finkornighetfågelarter, hundraser, komponenter
Skevhetträffsäkerhet uppdelad per grupp
Svenskasamma klasser på svenska mot engelska

Den sista raden är avgörande för AI-grafen: original-CLIP är tränad på övervägande engelska bildtexter och presterar sämre på svenska prompter. Antingen översätter man klassnamnen till engelska, eller använder en flerspråkig variant — men mät skillnaden innan du väljer.

Kod

import torch, torch.nn.functional as F

def clip_forlust(bild_v, text_v, logit_skala):
    """bild_v, text_v: (N, d). logit_skala: exp(inlärd parameter), klippt vid 100."""
    I = F.normalize(bild_v, dim=-1)
    T = F.normalize(text_v, dim=-1)
    S = logit_skala * I @ T.t()                       # (N, N)
    y = torch.arange(len(S), device=S.device)
    return (F.cross_entropy(S, y) + F.cross_entropy(S.t(), y)) / 2

# Kontroll: en perfekt modell ger nära noll, en slumpmässig ger log(N)
N, d = 8, 16
perfekt = torch.randn(N, d)
print(round(float(clip_forlust(perfekt, perfekt.clone(), 100.0)), 4))        # 0.0
print(round(float(clip_forlust(torch.randn(N, d), torch.randn(N, d), 1.0)), 3),
      round(float(torch.tensor(N).float().log()), 3))                        # ~2.0  2.079

# Zero-shot med promptensemble
MALLAR = ["ett foto av en {}", "en bild på en {}", "en närbild av en {}",
          "en suddig bild av en {}", "en teckning av en {}"]

def klassvektorer(klasser, koda_text):
    ut = []
    for k in klasser:
        v = torch.stack([koda_text(m.format(k)) for m in MALLAR])
        v = F.normalize(v, dim=-1).mean(0)
        ut.append(F.normalize(v, dim=0))
    return torch.stack(ut)                             # (K, d)

# Kompositionalitetstestet — kör det innan du litar på rummet
a = koda_text("en hund som jagar en katt")
b = koda_text("en katt som jagar en hund")
print(round(float(F.cosine_similarity(a[None], b[None])), 3))    # ~0.95

Kontrollen på rad 12–14 är värd att ha kvar i testsviten: en riktig implementation ska ge noll på identiska vektorer och log⁡N\log N på slumpmässiga. Fel i normalisering eller transponering syns direkt där.

Behärskning innebär

  • Implementerar och förklarar den symmetriska kontrastiva förlusten
  • Använder CLIP för zero-shot-klassificering
  • Känner till CLIP:s svagheter och hur de mäts

Logga in för att göra övningarna och bygga upp din behärskning.

Källor

Alla källor och licenser