Redes Neurais Artificiais e Deep Learning · Insper

Stable Diffusion

Quatro ideias, empilhadas

Quatro ideias, empilhadas

  1. Um processo de difusão: gerar vira uma longa sequência de problemas fáceis de remover ruído.
  2. Um espaço latente, vindo de um VAE: a sequência roda num espaço 48× menor que os pixels.
  3. Um encoder de texto, vindo do CLIP: dá para dizer ao processo o que fazer.
  4. Classifier-free guidance: ele de fato obedece.

A maioria das explicações para na terceira. O que dá errado se você amostrar honestamente um modelo condicionado em texto, sem a quarta?

Duas cadeias sobre os mesmos quadros

As duas cadeias de um modelo de difusão sobre os mesmos quatro quadros: x0, x t−1, x t e x T. Na direta (em cima), um processo fixo acrescenta ruído passo a passo e um único salto leva de x0 a x t. Entre as linhas, o passo reverso verdadeiro q(x t−1 | x t) está riscado: é intratável. Na reversa (embaixo), uma U-Net prevê o ruído e leva x t de volta a x t−1; a amostragem repete esse passo T vezes a partir de ruído novo. DIRETA · FIXA · ACRESCENTA RUÍDO REVERSA · APRENDIDA · REMOVE RUÍDO ⋯ q(xt​ | xt−1​) ⋯ um salto: xt​ = √ᾱt​ x0​ + √(1 − ᾱt) ε q(xt−1​ | xt) é desconhecido: exige todas as imagens ⋯ ⋯ amostragem: comece de ruído novo e aplique o passo aprendido T vezes x0​ xt−1​ xt​ xT​ x0​ xt−1​ xt​ xT​ pθ(xt−1​ | xt)U-Netεθ(xt​, t)

Difusão direta: o ruído num salto só

O treino precisa de num aleatório entre 1 e 1000. É preciso rodar a cadeia vezes?

  • Não: uma composição de gaussianas é gaussiana.

  • Sorteie , sorteie , salte. Cada exemplo de um lote pode estar num nível de ruído diferente.
  • O processo direto é fixo: nada nele é aprendido e a inferência nunca o usa.

: a imagem limpa · : ela depois de passos de ruído, de · : quanto ruído o passo acrescenta (o cronograma) · : gaussiana em com média e covariância · : a identidade, ruído independente por pixel · : ruído gaussiano padrão.

A perda cabe numa linha

  • O alvo é um ruído que você mesmo sorteou; é o texto.
  • Regressão supervisionada comum: sem adversário, treino estável, uma perda que significa algo.
  • Isso, mais que a qualidade das imagens, é o que fez a difusão deslocar a GAN.

As previsões de , de e de são intercambiáveis dados e o cronograma. Elas diferem em como a perda pesa os níveis de ruído.

: a rede (a U-Net, com pesos ) · : média sobre imagens, ruídos e sorteados · : uma mistura dos dois alvos.

A volta: da previsão de ruído a um passo

A rede devolve . Como obter o palpite atual dela para a imagem limpa?

  • Inverta a forma fechada:

  • Perto de , : qualquer erro em é amplificado. Daí os objetivos de e de velocidade.
  • O agendador (scheduler: a regra que transforma a previsão num passo) anda um pouco de na direção de . Repita.

Uma rede, dois laços

Treino e amostragem compartilham uma U-Net. À esquerda, o treino: um lote em que cada imagem sorteia o seu t, um salto até x t em forma fechada e uma perda entre o ruído sorteado e o previsto, que atualiza os pesos. À direita, a amostragem: comece do ruído x T, dê um passo para trás com o ruído previsto e repita T vezes até x0. TREINO · UMA PASSAGEM POR IMAGEM AMOSTRAGEM · T PASSAGENS, EM ORDEM ε εθ​ atualiza θ εθ​ × T t = 1: fim Um lote: cada imagem sorteia o seu t t = 14 t = 350 t = 721 Salto para aquele nível de ruído=√ᾱt​+√(1−ᾱt)xt​x0​ε Perda: ‖ε − εθ(xt​, t)‖²um passo de gradiente; depois, o próximo lote U-Net εθ(xt​, t)θ Início: xT​ ~ 𝒩(0, I), t = Truído sorteado pela semente Um passo para trásxt−1​ = μθ(xt​, t) + σt​ zμθ​ remove uma parte, em escala, de εθ​σt​ z: ruído novo no DDPM; 0 no DDIM Depois do último passo: x0​uma imagem nova

O cronograma de ruído não é um detalhe

SD 1.x: "linear escalado" ( em linha reta) de 0,00085 a 0,012, em passos.

Quanto da imagem sobrevive no último passo de treino, ?

  • , então da imagem ainda está lá — não zero.
  • A amostragem começa de ruído puro: um descompasso treino/teste.
  • Consequência: o SD 1.x não consegue fazer uma imagem realmente preta ou realmente branca. O brilho médio vaza.
  • A correção: reescalar o cronograma para SNR terminal zero (Lin et al., 2024).

SNR (razão sinal-ruído) , a variância do sinal sobre a do ruído em . Terminal: em . No SD 1.x, . O laboratório lê no agendador, que conta de 0 a 999: .

Simulador · a razão sinal-ruído ao longo de t

Difusão latente: de onde vem o 48

pixels latente do SD 1.5
formato (altura × largura × canais) 512 × 512 × 3 64 × 64 × 4
números 512 · 512 · 3 = 786.432 64 · 64 · 4 = 16.384

786.432 / 16.384 = 48. De onde vem o fator 48?

512 × 512 × 3imagem8 × 8 pixels × 3 cores= 192 númerosencoder do VAE192 / 4 = 484 canais= 4 números64 × 64 × 4latente
  • Cada lado encolhe 8×: uma célula do latente resume 8 × 8 pixels × 3 cores = 192 números em 4. .
  • Pago em cada passo de amostragem. O VAE custa uma codificação ou uma decodificação.

A ida e volta pelo VAE, medida

Laboratório, seção 2: uma foto 512 × 512, codificada e decodificada.

latente 1 × 4 × 64 × 64
desvio, latente cru 4,12
desvio × 0,18215 0,75
PSNR da reconstrução 27,7 dB
latente → RGB linear, R² 0,92
  • O fator de escala 0,18215 leva o latente à variância unitária no conjunto de treino, a escala do ruído. Nesta foto: 4,12 × 0,18215 = 0,75.
  • O decoder devolve o detalhe fino; o latente guarda layout e cor.
  • Um mapa linear de 4 canais para RGB já dá uma prévia reconhecível — o truque por trás das prévias de cada passo do Diffusion Explainer.

Formato: (imagens, canais, altura, largura). PSNR = 10 log₁₀(pico² / erro quadrático médio), em dB: mais alto é mais fiel. R²: fração da variância das cores da foto, reduzida a 64 × 64, que o mapa linear explica.

Difusão latente, de ponta a ponta

Difusão latente em três espaços. Pixels: a imagem x, o encoder E e o decoder D do VAE e a imagem gerada x̃. Latente, 64 × 64 × 4: no treino, z0 vindo do encoder, ruído acrescentado num t sorteado, z t na U-Net e a perda; na geração, z T vindo do ruído, a U-Net e o agendador repetidos T vezes e depois z0 para o decoder. Texto: o prompt, o encoder de texto do CLIP e os embeddings c, que chegam à U-Net pela atenção cruzada. PIXELS · 512 × 512 × 3 LATENTE · 64 × 64 × 4 TEXTO · 77 TOKENS zt​, t εθ​ × T K, V xuma foto ℰencoder(congelado) 𝒟decoder(congelado) x̃a imagem z0​ some ruídot sorteado, um salto zt​ perda‖ε − εθ‖² U-Net εθ(zt​, t, c)atenção cruzada:Q de zt​; K e V de c zT​𝒩(0, I) agendadorzt​ → zt−1​ z0​ “um gato no espaço”prompt encoder de textoCLIP · congelado c · 77 × 768

Três componentes; um deles faz o trabalho

componente papel parâmetros chamadas por imagem
encoder de texto do CLIP prompt → (tokens × números) 123,1 M 2 (prompt e prompt vazio)
U-Net prevê no latente 859,5 M 50 (25 passos × 2)
decoder do VAE latente → pixels 49,5 M 1
  • O encoder de texto e o VAE estão congelados; só a U-Net foi treinada para a difusão.
  • Todo ganho de velocidade que você vai ver age na linha da U-Net: menos passos, destilação, sem guidance.

M = milhões de parâmetros, contados na seção 1 do laboratório. O VAE inteiro tem 83,7 M, mas na geração só o decoder (49,5 M) roda. A U-Net é 81% do total: 859,5 / (123,1 + 859,5 + 83,7).

O prompt, do jeito que a U-Net o vê

  • O tokenizador completa ou trunca todo prompt para 77 tokens: <start>, as palavras, <end> e preenchimento.
  • O encoder de texto devolve um vetor por token: (768 é a largura do encoder do CLIP ViT-L/14).
  • "Sem prompt" é a codificação da string vazia — não zeros.
cosseno entre as matrizes inteiras, achatadas (laboratório, seção 3)
"a lighthouse on a cliff at sunset" vs "…, watercolor painting" 0,78
"a lighthouse on a cliff at sunset" vs "a bowl of ramen on a wooden table" 0,24
"a lighthouse on a cliff at sunset" vs "" 0,20

A única porta: atenção cruzada

  • vem das features do latente, em cada resolução da U-Net: 64², 32², 16² e 8² (o lado cai à metade por nível).
  • vêm dos 77 vetores do texto. : a dimensão de cada query e chave.
  • A imagem pergunta, o texto responde: a atenção cruzada de um decoder Transformer.

Dois prompts que diferem por uma palavra, mesma semente. O que é idêntico nas duas execuções e o que muda?

  • Idênticos: , os pesos da U-Net, o agendador.
  • Muda: só e .

O laço de amostragem, por extenso

latentes = randn(1, 4, 64, 64, generator=semente)     # z_T: a semente o decide
emb = cat([codificar(""), codificar(prompt)])          # ∅ e c
for t in agendador.timesteps:                          # 25 passos
    eps_u, eps_c = unet(cat([latentes] * 2), t, emb).chunk(2)
    eps = eps_u + w * (eps_c - eps_u)                  # guidance: uma linha
    latentes = agendador.step(eps, t, latentes).prev_sample
imagem = vae.decode(latentes / 0.18215)
  • O laboratório escreve este laço e o confere contra o pipeline da biblioteca: maior diferença de pixel 1 (em 255).
  • 50 chamadas da U-Net (25 passos × 2); 1,41 s por passo num Apple M2 (uma T4 é mais rápida).

chunk(2): separa o lote de 2 nas duas previsões (∅ e c) · prev_sample: o latente do passo seguinte · / 0.18215: desfaz o fator de escala do VAE.

Simulador · uma imagem, em números

iteração

Classifier-free guidance

Treine com a legenda descartada 10% das vezes: uma rede aprende e .

O que dão e ? E o padrão dos pipelines, ?

  • é o guidance_scale dos pipelines. : o modelo incondicional, que ignora o prompt. : amostragem condicional pura.
  • extrapola além do condicional: nenhuma distribuição que o modelo aprendeu. Funciona mesmo assim.
  • Custo: duas passagens da U-Net por passo, para qualquer diferente de 0 e de 1.

: a previsão de ruído da U-Net com o prompt (o passo fica implícito) · : o prompt vazio.

Simulador · guidance numa distribuição de brinquedo

Guidance no modelo de verdade, medido

Laboratório, seção 6: "a red fox sitting in a snowy forest, photograph", sementes 0, 1, 2, 20 passos de DDIM.

nota CLIP (prompt) saturação diversidade entre sementes
0 13,2 0,20 0,259
1 33,0 0,20 0,184
3 34,7 0,22 0,064
7,5 33,4 0,31 0,057
15 33,9 0,40 0,041
  • A aderência sobe rápido e depois achata; a saturação continua subindo.
  • A diversidade entre sementes cai a cada passo, 0,259 → 0,041: com grande as três sementes desenham a mesma raposa centralizada.

Nota CLIP: 100 × o cosseno entre os embeddings CLIP ViT-B/32 da imagem e do prompt. Diversidade: distância de cosseno média entre os embeddings CLIP das três sementes. Saturação: saturação HSV média.

Semente e prompt: quem decide o quê

Laboratório, seção 6: "a lighthouse on a cliff at sunset" ± ", watercolor painting", DDIM, .

par correlação entre as duas imagens, em cinza e reduzidas a 64 × 64 (o layout)
mesmo prompt, sementes 0 e 1 0,15
mesma semente 0, com e sem o modificador 0,85
  • A semente fixa e, com ele, a maior parte do layout, decidido nos primeiros passos.
  • O modificador muda estilo e cor pela atenção cruzada.
  • Os das duas trajetórias já diferem no passo 1 (), mas os layouts terminam com correlação 0,85.

Vá e experimente: Diffusion Explainer

  1. Associe as três caixas dele ao capítulo: encoder de texto → refinador (U-Net + agendador) → decoder.
  2. Controle de timestep (50 passos): quando dá para dizer o que é o objeto? Quando só o detalhe muda?
  3. Guidance 0, 1, 7, 20: preveja cada um pela fórmula antes.
  1. Semente: quais caixas mudam e quais não?
  2. Compare dois prompts que diferem por um modificador, com a mesma semente e o mesmo guidance: quando eles divergem?

As imagens são pré-calculadas: nada de prompt próprio — para isso existe o laboratório. Lee et al., IEEE VIS 2024. Interface em inglês.

poloclub.github.io/diffusion-explainer →

Samplers: o mesmo modelo, de cinco a cinquenta passos

sampler o que é passos típicos
DDPM ancestral, estocástico 1000
DDIM ODE determinística; invertível, então serve para editar 50
Euler / Heun solvers de ODE comuns 20–30
DPM-Solver++ integrador exponencial; o padrão prático 15–25
UniPC, DEIS multipasso de ordem mais alta 10–20
  • O treino dá ; transformá-lo em imagem é um problema numérico separado.
  • Abaixo de ~10 passos nenhum solver salva: esse regime exige destilação.

Ancestral: sorteia ruído novo a cada passo · ODE: equação diferencial sem sorteio, então a semente fixa a imagem · ordem mais alta: usa várias avaliações (ou as dos passos anteriores) para dar um passo mais preciso.

Destilação: de cinquenta passos para um

método ideia passos
destilação progressiva um aluno dá dois passos do professor de uma vez; repita 8192 → 4 (metade por rodada, 11 rodadas)
LCM-LoRA salta de qualquer ponto da trajetória para o fim; vem como um LoRA 2–8
ADD (SDXL-Turbo) acrescenta um discriminador: a perda de GAN volta 1–4

Laboratório, seção 7, mesmo prompt e mesma semente:

chamadas da U-Net nota CLIP tempo (M2)
DDIM, 1 passo, 2 (1 × 2) 13,1 2,4 s
DDIM, 4 passos, 8 (4 × 2) 32,5 6,1 s
DDIM, 25 passos, 50 (25 × 2) 34,1 34,1 s
LCM-LoRA, 4 passos, 4 (4 × 1: sem guidance) 33,9 4,5 s

Controle: o que se faz de fato com ele

mecanismo o que faz como
img2img começa de uma imagem codifica, ruidifica até um , remove o ruído; força = qual
inpainting refaz uma região mascarada mantém o original ruidificado fora da máscara a cada passo
ControlNet pose, profundidade, bordas cópia treinável da metade encoder, ligada por convoluções zeradas
IP-Adapter uma imagem de referência atenção cruzada extra que lê embeddings de imagem do CLIP
LoRA um estilo, um personagem atualização de posto baixo das camadas de atenção (aula de transfer learning)

Todos congelam a base e acrescentam um pequeno caminho ao lado. O ControlNet e o LoRA o iniciam em zero, então o treino começa exatamente no modelo base. É por isso que eles compõem.

O que mudou depois do SD 1.5

SD 1.5 (2022) SDXL (2023) SD3 / FLUX (2024)
backbone U-Net, 860M U-Net, 2,6B + refinador MMDiT (Transformer de difusão multimodal)
encoder de texto CLIP ViT-L dois CLIP T5-XXL + CLIP
latente 4 canais 4 canais 16 canais
objetivo , DDPM fluxo retificado
tamanho nativo 512² 1024² 1024²+, cronograma deslocado
  • Quatro mudanças de fundo (Transformer, T5, 16 canais, fluxo); nenhuma delas é "mais parâmetros".
  • O fluxo retificado é a próxima aula; o backbone Transformer, a seguinte.

De onde vieram os dados de treino

O SD 1.x foi treinado em subconjuntos do LAION-5B: pares imagem–URL raspados do Common Crawl e filtrados por similaridade do CLIP. Ninguém cujo trabalho está ali foi consultado.

  • Litígio sobre dados de treino, ainda em aberto.
  • O estilo de um artista vivo, com nome e sobrenome, reproduzido sob demanda.
  • Memorização documentada de imagens individuais de treino.
  • Material ilegal encontrado numa auditoria, que tirou o conjunto do ar.

Proveniência é uma propriedade de engenharia do seu sistema, não uma nota de rodapé.

Laboratório · o Stable Diffusion, aberto

Notebook no Colab, ~2 h, GPU T4 (nível gratuito), Stable Diffusion 1.5 com diffusers. Cada seção termina num checkpoint.

  1. três componentes, contados
  2. a ida e volta pelo VAE e os 48×
  3. o encoder de texto: 77 × 768
  4. o processo direto e o SNR terminal
  1. o laço de amostragem, à mão, contra o pipeline
  2. guidance e semente, medidos
  3. passos e um LCM-LoRA em 4 passos
  4. img2img à mão: a tabela é sua

abrir no Colab →

Para levar

  1. Difusão = muitos problemas fáceis de remover ruído; a forma fechada torna o treino paralelo.
  2. A perda é um erro quadrático contra um ruído que você sorteou: estável e a razão de a difusão bater as GANs.
  3. O cronograma decide o que se aprende: é por que o SD 1.x não renderiza preto.
  4. Difusão latente: 48× menos números por passo; o VAE cuida do detalhe.
  5. Guidance: uma linha, duas passagens da U-Net, aderência comprada com diversidade.
  6. O sampler é uma escolha separada; abaixo de ~10 passos, destilação (e a GAN volta).
  7. ControlNet, IP-Adapter, LoRA: base congelada + pequeno caminho. Desde o SD 1.5: Transformer, T5, 16 canais, fluxo.

Roteiro: (1) difusão: processo direto, perda, volta; (2) o cronograma de ruído; (3) difusão latente e os três componentes; (4) classifier-free guidance; (5) Diffusion Explainer; (6) samplers, destilação, controle; (7) o que mudou depois do SD 1.5. Fecha com o laboratório no Colab.

Resposta nos slides de guidance: a aderência ao prompt decepciona; w = 7,5 não é amostragem "honesta".

Avance pelas seis etapas: as duas direções, um passo direto, o salto em forma fechada (o próximo slide), o passo reverso verdadeiro, que é intratável, o palpite da U-Net e a amostragem. Passe o mouse sobre um quadro para ver as suas setas. A linha reversa termina numa figura diferente: a amostragem faz uma imagem nova.

O laboratório decodifica x̂0 a cada passo; o Diffusion Explainer mostra a mesma progressão.

Treino (à esquerda): um lote em que cada imagem tem o seu t, o salto, a perda; uma passagem por imagem, todas em paralelo. Amostragem (à direita): comece do ruído, dê um passo para trás, repita T vezes seguidas. A mesma U-Net, os mesmos pesos.

Comece no cronograma linear escalado: ponto vermelho em t = 1. Marque "forçar SNR terminal zero". Depois suba a resolução para 1024: a curva sobe, a imagem fica ruidificada de menos. Aumente o deslocamento para ver a correção do SD3 (o tracejado é a curva sem deslocamento na mesma resolução).

Clique em Treino, depois em Geração. O treino usa o encoder e nunca o decoder; a geração usa o decoder e nunca o encoder. Os dois usam a U-Net e o encoder de texto. O próximo slide conta os parâmetros.

Números impressos pela seção 1 do laboratório.

O laço do slide anterior num latente de 4 números, com uma U-Net de brinquedo exata (os latentes de cada legenda são uma gaussiana) e o cronograma real do SD 1.5. Padrão: "uma maçã vermelha", semente 3, w = 7,5, 25 passos. Avance: 5 tokens reais + 5 de enchimento; ‖c‖ = 1,18 e ‖∅‖ = 1,11 (não é zero); t = 961 … 1, ᾱ_961 = 0,00728. Iteração 1: ε_∅ e ε_c quase iguais (π ≈ 0,25 cada); ε̃₁ = 1,2481; x̂₀₁ = −5,36 (÷ 0,0853: erros × 11,7). Trajetória: x̂₀ converge, 10,5 → 0,23 → 0,008. Depois mude um controle por vez: w = 1 (amostra honesta, a 0,41 de μ_c), w = 0 (a semente 3 desenha um campo de neve), w = 15 (0,98 além de μ_c, 64 de 192 valores cortados), N = 1 (t = 1: o próprio ruído), N = 4 (começa em t = 751 e termina a 0,18 do resultado de 25 passos).

Scores exatos, então w = 1 já dá 99% no prompt aqui; um condicional aprendido não dá. Com 32 passos: dispersão de 1,03σ em w = 1, 0,76σ em w = 3, 0,63σ em w = 7,5; fora da variedade 1% em w = 3, 17% em w = 10, 63% em w = 15.