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

Latent diffusion och text-till-bild

Kunna förklara hur textstyrd bildgenerering fungerar och köra en modell lokalt.

Förkunskaper

Intuition

Diffusion i ett par meningar: lär en modell att ta bort brus. Träna genom att lägga till brus i steg på riktiga bilder och låta modellen förutsäga bruset. Generera genom att börja i rent brus och ta bort lite i taget.

Latent diffusion lägger till ett avgörande steg: gör det i ett komprimerat rum i stället för i pixlar.

bild 512×512×3 ──VAE-encoder──→ latent 64×64×4 ──diffusion här──→ VAE-decoder ──→ bild
   786 432 tal                     16 384 tal

En faktor 48 färre tal att arbeta med. Det var det som gjorde bildgenerering möjlig på vanliga grafikkort — Stable Diffusion i stället för modeller som krävde ett datacenter.

Tre delar i en text-till-bild-modell:

DelGör
Textkodare (CLIP eller T5)text → vektorer
U-Net eller DiTtar bort brus, styrd av textvektorerna via cross-attention
VAEmellan pixelrum och latent rum

Formellt

Framåtprocessen lägger till brus enligt ett schema:

xt=αˉt x0+1−αˉt ε,ε∼N(0,I)x_t = \sqrt{\bar\alpha_t}\,x_0 + \sqrt{1-\bar\alpha_t}\,\varepsilon, \qquad \varepsilon \sim \mathcal{N}(0, I)

Det fina är att xtx_t kan beräknas direkt för valfritt tt — ingen iteration behövs vid träning.

Träningsmålet är förvånansvärt enkelt:

L=Ex0,ε,t[∥ε−εθ(xt,t,c)∥2]\mathcal{L} = \mathbb{E}_{x_0, \varepsilon, t}\left[\left\|\varepsilon - \varepsilon_\theta(x_t, t, c)\right\|^2\right]

Modellen ska gissa vilket brus som lades till, givet den brusiga bilden, tidssteget och betingningen cc (textembeddingen). Ingen adversariell träning, ingen instabilitet — det är en av anledningarna till att diffusion slog GAN.

Classifier-free guidance är det som gör textstyrningen stark. Under träningen tas betingningen bort slumpmässigt i cirka 10 % av fallen, så att modellen lär sig både betingad och obetingad generering. Vid sampling extrapoleras:

ε~=εθ(xt,∅)+w(εθ(xt,c)−εθ(xt,∅))\tilde\varepsilon = \varepsilon_\theta(x_t, \varnothing) + w\left(\varepsilon_\theta(x_t, c) - \varepsilon_\theta(x_t, \varnothing)\right)

wwEffekt
1ingen styrning
5–8typiskt — följer prompten väl
> 15övermättade färger, artefakter, tappad variation

Kostnaden är att varje steg kräver två modellanrop.

Samplers avgör hur många steg som behövs:

SamplerStegKommentar
DDPM1 000originalet, opraktiskt
DDIM20–50deterministisk, reproducerbar
DPM-Solver++15–25snabbast för god kvalitet
Konsistensmodeller, LCM1–4destillerade, lägre kvalitet

Styrning utöver text:

MetodStyr med
ControlNetkantbild, djupkarta, pose
Inpaintingmask — generera bara i ett område
img2imgstartbild plus brusstyrka
LoRAinlärd stil eller karaktär
IP-Adapterreferensbild för stil

Det juridiska och etiska hör ihop med tekniken: träningsdatans upphovsrätt, memorering av enskilda bilder, och märkning av syntetiskt innehåll enligt AI-förordningens artikel 50. Kör en memoreringskontroll innan du publicerar.

Kod

import torch
from diffusers import StableDiffusionXLPipeline, DPMSolverMultistepScheduler

pipe = StableDiffusionXLPipeline.from_pretrained(
    "stabilityai/stable-diffusion-xl-base-1.0",
    torch_dtype=torch.float16, variant="fp16").to("cuda")
pipe.scheduler = DPMSolverMultistepScheduler.from_config(pipe.scheduler.config)
pipe.enable_attention_slicing()          # mindre minne, något långsammare

generator = torch.Generator("cuda").manual_seed(42)      # frö → reproducerbart
bild = pipe(
    prompt="ett pedagogiskt diagram över en neuronnätsarkitektur, ren linjekonst, vit bakgrund",
    negative_prompt="suddig, text, vattenstämpel, lågupplöst",
    num_inference_steps=25,
    guidance_scale=7.0,
    generator=generator,
).images[0]
bild.save("diagram.png")

# Guidance scale: mät effekten i stället för att gissa
for w in (1.0, 3.0, 7.0, 15.0, 25.0):
    b = pipe(prompt="en röd kub på ett blått bord", guidance_scale=w,
             num_inference_steps=25,
             generator=torch.Generator("cuda").manual_seed(0)).images[0]
    b.save(f"cfg_{w}.png")
# w=1: ignorerar prompten  ·  w=7: följer den  ·  w=25: övermättat och sönderskuret

# Steg mot kvalitet och tid
import time
for steg in (10, 20, 25, 50):
    t0 = time.perf_counter()
    pipe(prompt="en katt", num_inference_steps=steg,
         generator=torch.Generator("cuda").manual_seed(0))
    print(f"  {steg:>2} steg: {time.perf_counter() - t0:.1f} s")
#  ↑ över ~25 steg är förbättringen marginell med DPM-Solver++

# Minneskrav
def minne_gb(fp16=True):
    delar = {"U-Net": 2.6, "textkodare": 0.8, "VAE": 0.2}      # SDXL, ungefärligt
    faktor = 1.0 if fp16 else 2.0
    return {k: round(v * faktor, 2) for k, v in delar.items()} | {
        "summa": round(sum(delar.values()) * faktor, 2)}
print(minne_gb())     # {'U-Net': 2.6, ..., 'summa': 3.6}

# Memoreringskontroll före publicering
def liknar_traningsdata(bild, index, clip_modell, troskel=0.95):
    v = clip_modell.encode_image(bild)
    v = v / v.norm()
    traff = index.search(v, k=5)
    return [t for t in traff if t["likhet"] > troskel]
# Icke-tom lista → generera om; bilden ligger för nära ett träningsexempel.

Behärskning innebär

  • Förklarar diffusion i latent rum
  • Beskriver hur textstyrningen fungerar
  • Väljer sampler och steg medvetet

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

Källor

Alla källor och licenser