Skip to content

O Guia Ilustrado do Stable Diffusion

Este artigo é um guia ilustrado do básico como o Stable Diffusion funciona, completamente em português do Brasil!
Volte aqui sempre que quiser revisar e aprender os conceitos fundamentais do funcionamento interno do Stable Diffusion, a IA poderosa que gera imagens incríveis e realistas e que está por trás da maioria dessas ferramentas e apps que fazem isso!

Agradecimentos

Este artigo é uma tradução do artigo original feito pelo Jay Alamar:
The Illustrated Stable Diffusion – Jay Alammar – Visualizing machine learning one concept at a time. (jalammar.github.io)

Antes de mais nada, devo agradecer ao @JayAlammar que é o autor do artigo original e que permite que o seu post seja traduzido para outros idiomas em blogs pessoais.
Thank you @JayAlammar, your article is so good, so good, that I think the Brazilian technical community deserves to have this in Portuguese and adjusted to the context of those who are learning! Thank you very much for your incredible work!

Na verdade, este artigo não é somente uma tradução! Foi uma das minhas principais fontes de estudos mais deep sobre o Stable Diffusion!
Me ajudou a compreender o básico, e além de traduzir pra vocês, eu testei, fui atrás de informações complementares, e tentei ajustar o texto o máximo possível para facilitar o entendimento com a forma de falar que estamos acostumados! Certamente tudo que aprendi aqui vou levar pra muitas outras coisas que ainda vou construir e aprender com IA! Então, esse é um trabalho que vai além da tradução! É o resultado do processo de estudo e aprendizado que está sendo necessário nesta fase da minha carreira com IA

Também, quero deixar aqui meu agradecimento à Power Tuning, que está cedendo horas e horas do meu trabalho com eles, para que eu possa me dedicar a isso: aprender, ler, traduzir, revisar, etc! Muito obrigado Power! É uma empresa diferenciada para a tecnologia do Brasil!

Este material é publicado sob esta licença: CC BY-NC-SA 4.0 Deed | Attribution-NonCommercial-ShareAlike 4.0 International | Creative Commons

E antes de fechar essa introdução, me perdoem os erros de digitação e português que podem existir. Sempre reviso, mas podem passar! Se você encontrar erros, ou tiver sugestões de melhorias do conteúdo (e da tradução), fica a vontade! Manda nos comentários ou algum dos canais de comunicação no final do artigo.

Sem mais, vamos ao artigo, que é simplesmente sensacional!


Introdução ao Stable Diffusion

A geração de imagens por IA é a mais recente habilidade que está impressionando as pessoas (inclusive eu). A capacidade de criar visuais marcantes a partir de descrições de texto parece mágica e aponta claramente para uma mudança na forma como os humanos criam arte. O lançamento do Stable Diffusion é um marco claro nesse desenvolvimento, pois tornou um modelo de alto desempenho disponível para o público em geral (desempenho em termos de qualidade de imagem, bem como velocidade e requisitos de recursos/memória relativamente baixos).

Segue um vídeo do autor original desse artigo explicando sobre como imagens são geradas
[rodrigo: em breve eu gravo um para complementar]

Sites para você testar o Stable Diffusion, de graça (alguns oferecem alguns créditos de graça e quando acabar, você pode comprar mais, ou se renovam no dia seguinte):

Depois de sentir o gosto da geração de imagens com IA, pode ser que fique curioso para saber como isso tudo funciona.
Este artigo é uma pequena introdução sobre o funcionamento do Stable Diffusion!

[Rodrigo: Nem todas as imagens originais do artigo ainda estão traduzidas! Mas as originais são bem auto-explicativas e eu também coloquei legendas para auxiliar, enquanto traduzo todas!]

O Stable Diffusion é versátil, pois pode ser utilizado de várias maneiras diferentes. Vamos focar inicialmente na geração de imagens a partir de texto (chamado também de text2img em muitas interfaces e bibliotecas). A imagem acima mostra um exemplo de texto e a imagem resultante. Além do texto para imagem, outra maneira principal de usar é fazendo com que ele altere imagens (portanto, as entradas são texto + imagem).

Vamos começar olhando como as coisas funcionam por debaixo dos panos (internals), pois isso vai ajudar a entender os componentes, como eles interagem e o que as opções/parâmetros da geração de imagem significam.

Os componentes do Stable Diffusion

O Stable Diffusion é um sistema feito de vários componentes e modelos, ou seja, ele não apenas um único modelo de IA (monolítico).

A primeira coisa que podemos notar é que há um componente para o entendimento do texto (Text Understander encoder) que traduz o prompt (texto de entrada) em uma representação numérica, que representam as idéias no texto.

Ainda estamos falando em um nível mais macro da coisa e ja já entraremos no machine learning, mas já posso adiantar que o Text Understander encoder é um modelo Transformer (tecnicamente:é um modelo CLIP). Ele pega o texto de entrada e gera uma lista de números que representa cada palavra/token no texto (um vetor por token).
[Rodrigo: Esta lista/vetor é um array de números decimais, que são chamados de embeddings)]

Essa informação é então apresentada ao Image Generator (gerador de imagens), que por si só é composto por alguns componentes.

O Image Generator (Gerador de Imagens) possui dois estágios:

1 – Image Information Creator ( criador de informações de imagem )

Este componente é o ingrediente secreto do Stable Diffusion. É onde contém várias melhorias de performance em relação aos modelos anteriores.
São executadas várias etapas (steps) para gerar a imagem. Você consegue controlar essas etapas com o parâmetro steps nas interfaces e bibliotecas que usam o Stable Diffusion. Geralmente, o valor padrão é 50 ou 100.
O Image Information Creator opera completamente em uma área chamada Image Information Space (espaço de informação da imagem) ou espaço latente. Falaremos mais sobre o que isso significa mais adiante no post.
Esta propriedade o torna mais rápido que os modelos de difusão anteriores que funcionavam no espaço de pixels.
Em termos mais técnicos, este componente é composto por uma rede neural UNet e um algoritmo de agendamento (scheduling algorithm)
[Rodrigo: Este link explica essa parte do algoritmo de scheduling (procure por Noise Schedule) : Stable Diffusion Samplers: A Comprehensive Guide – Stable Diffusion Art (stable-diffusion-art.com)]


A palavra Diffusion(Difusão) descreve perfeitamente o que acontece neste componente. É um processamento da informação em etapas que leva à geração final de uma imagem de alta qualidade (quem gera a imagem final mesmo é o próximo componente, o Image Decoder).

aqui, o Image Generator foi quebrado em 2 componentes (rosa = Image Information Creator, amarelo = Image Decoder)

2 – Image decoder ( decodificador de imagem )

O image decoder desenha a imagem a partir da informação que ele obtém do information creator (o componente que acabamos de descrever).
Ele executa somente uma vez e no fim do processo de produção da imagem final em pixels.

Com isso, temos os três componentes principais (cada um com sua própria rede neural) que compõe o Stable Diffusion:

  • Text Encoder
    Modelo ClipText para conversão do texto
    Entrada: Um texto
    Saída: 77 arrays com os embeddings dos tokens do texto (cada array tem um tamanho de 768 posições)
  • Image Information Creator
    Rede Neural UNet + algoritmo Scheduler para processar/difundir gradativamente as informações no espaço latente
    Entrada: Os embeddings do texto + um array de várias dimensões (também chamado de tensor) que representam um ruído inicial da imagem (ja já você vai entender isso)
    Saída: Um array processado com as informações necessárias para desenhar a imagem final. (dimensões: 4x64x64)
  • Image Decoder
    Rede Neural Autoencoder  decodificadora que desenha a imagem final usando o array de informações
    Entrada: O array de informações 4x64x64
    Saída: A imagem final (dimensões: 3x512x512 que são (vermelho/verde/azul x largura x altura))

Afinal, o que é difusão?

Difusão é o processo que ocorre dentro deste componente rosa da imagem, o Image Information Creator (criador de informações de imagem). A partir de embeddings do texto de entrada e um array de informações da imagem aleatório o processo produz um array de informações que o decodificador de imagem usa para desenhar a imagem final.

1 – embedding do texto é gerado (77 arrays, cada um com 768 posições)
2 – Um outro array, inicializado aleatoriamente é gerado
3 – O Image Information Creator gera um array final, que contém tudo que o image decoder precisa para gerar a imagem final

Conforme mencionado anteriormente, esse processo acontece em várias etapas. Cada etapa, altera o array, adicionando mais informações relevantes para a imagem final.
Ou seja, esse array inicial aleatório é alterado vária e várias vezes até gerar um array final. Esse array também é chamado de latentes.
Se pegássemos o valor desse array aleatório, na primeira etapa, e passássemos ele no Image Decoder, ele produziria uma imagem granulada (cheia de ruídos).
Esta é uma maneira de fazer uma inspeção visual no processo.

Repare na imagem do lado esquerdo, ele direciona o array aleatório para o Image Decoder.
Neste caso, se você fizer isso, veria uma imagem completamente granulada.
Já no caso à direita, temos o array completamente processado. Ao passar no decoder, ele retornaria a imagem final que veríamos

A difusão acontece em várias etapas, cada etapa opera em um array (latentes) de entrada e produz outro array latente que vai se parecendo cada vez mais ao texto fornecido e contendo todas as informações visuais das imagens usadas para o treinamento do modelo.
[Rodrigo: Neste trecho deste vídeo do canal, eu também explico esse processo, mais visualmente, caso queria ver mais detalhes dessa explicação]

Note que dentro do Image Information Creator, a array iniciado é processado em várias etapas, modificando este array, até produzir a versão final que irá gerar a imagem.

Podemos visualizar um conjunto desses latentes para ver quais informações são adicionadas a cada etapa.

A imagem gerada é de o fôlego:

Algo especialmente fascinante acontece entre as etapas 2 e 4, neste caso. É como se os traços surgissem do nada em meio ao ruído.

Como funciona a difusão

A ideia central de gerar imagens com modelos de difusão baseia-se no fato que modelos de visão computacional poderosos. A partir de um dataset grande o suficiente grande, estes modelos podem aprender operações complexas. Os modelos de difusão geram imagem usando baseando-se no seguinte processo:

Digamos que temos uma imagem. Então, geramos um ruído e adicionamos esse ruído por cima da imagem:

Título: Exemplos de treinamento são criados gerando ruído e adicionando uma quantidade deles em imagens que estão no dataset de treino (forward diffusion, difusão direta)
  1. Pegue uma imagem
  2. Gere uma ruído aleatório
  3. Escolha uma percentual desse ruído
  4. jogue esse ruído na imagem nessa quantidade escolhida

Isso agora pode ser considerado um exemplo de treinamento. Podemos usar esta mesma fórmula para criar muitos exemplos de treinamento para treinar o componente central do nosso modelo de geração de imagens.

Título: Gerando um segundo exemplo de treinamento com ruído, ruído e quantidade diferentes (forward diffusion, difusão direta)

  1. Pegue uma outra imagem
  2. Gere uma ruído aleatório (amostra de ruído 2)
  3. Escolha uma percentual desse ruído (outro percentual diferente do anterior)
  4. jogue esse ruído na imagem nessa quantidade escolhida

Embora este exemplo mostre alguns valores de quantidade de ruído da imagem (quantidade 0, sem ruído) até o ruído total (quantidade 4, ruído total), podemos controlar facilmente quanto ruído adicionar à imagem e, assim, podemos distribuí-lo por dezenas de etapas, criando dezenas de exemplos de treinamento por imagem para todas as imagens em um dataset de treinamento.

Da esquerda pra direita: primeira coluna (Noise Amount) são os exemplos da quantidade de ruído.
A segunda (Noisy Image) é uma imagem onde esse onde esse ruído será aplicado.
A terceira (Noise sample) é o resultado que se espera
MODEL é o modelo a ser usado e como é chamado dentro do Stable Diffusion: Noise Predictor (que é treinado para prever o quanto de ruído tem na imagem)

Com este conjunto de dados, podemos treinar o Noise Predictor e obter um ótimo preditor (ou advinhador, se preferir) de ruído que realmente cria imagens quando executado em uma determinada configuração.
Uma etapa do treinamento deve ser familiar se você já mexeu com Machine Learning:

Título: Passo a passo de um treinamento UNet
  1. Obtenha um exemplo de treinamento a partir de um dataset de treino
  2. Peça ao modelo para prever o ruído
    As entradas são uma imagem (com algum nível de ruído) e o uma quantidade indicando esse nível
  3. Compare o que ele previu com o que esperado (label).
  4. Atualize o modelo (backpropagaton)

Agora, vamos ver como isso pode gerar imagens.

Desenhando imagens através da remoção do ruído

O Noise Predictor treinado, a partir de uma imagem e um número da etapa de eliminação de ruído, é capaz de prever uma imagem somente com o ruído da imagem de entrada:

Repare nas duas setas apontando para o modelo. É o input enviado ao modelo.
E logo acima, é saída do modelo, que é uma imagem representando o ruído que ele previu ser para esta etapa/imagem

O ruído é previsto para que, se o subtrairmos ele da imagem, possamos obter uma imagem mais próxima das imagens nas quais o modelo foi treinado (não as imagens exatas em si, mas a distribuição – como se fosse aquelas imagens pixelizadas onde o céu geralmente está azul e acima do solo, as pessoas têm dois olhos, os gatos têm uma determinada aparência – orelhas pontudas e claramente indiferentes).

A ilustração acima demonstra a subtração explica acima. Uma imagem com menos ruído (Sligtly de-noised image) = Imagem original – ruído previsto pelo modelo

Se o dataset de treinamento fosse de belas imagens ​​(por exemplo, LAION Aesthetics , no qual o Stable Diffusion foi treinado), então a imagem resultante tenderia a ser esteticamente agradável. Se treinarmos em imagens de logotipos, teremos um modelo de geração de logotipo.

Esta imagem demonstra o processo de forma repetida, em várias etapas. Repare que ele começa na imagem do canto inferior direito e vai repetindo o processo até gerar a imagem final.

Isso conclui a explicação da geração de imagens por modelos de difusão, principalmente conforme descrito em Modelos Probabilísticos de Difusão Denoising . Agora que você tem essa intuição de difusão, você conhece os principais componentes não apenas do Stable Diffusion, mas também do Dall-E 2 e do Imagen do Google.

Observe que o processo de difusão que descrevemos até agora gera imagens sem usar nenhum dado de texto. Então, se implantássemos esse modelo até aqui, ele geraria imagens com ótima qualidade, mas não teríamos como controlar se é uma pirâmide, um gato ou qualquer outra coisa. Mais adiante veremos com o texto é incorporado no processo para controlar que tipo de imagem o modelo gera.

Turbinando: Latente vs Pixels

Para acelerar o processo de geração de imagens, o paper do Stable Diffusion define que o processo não execute nos pixels de uma imagem e sim em uma versão comprimida dela. O artigo chama isso de “Ida para o Espaço Latente” (Departure to Latent Space).

Essa compressão (e posteriormente descompressão/desenho) é feita por meio de um autoencoder, que é quem comprime a imagem usando seu codificador, gerando um array latente, e em seguida, usando o decodificador, a reconstrói usando apenas as informações comprimidas.

Agora, você sabe que o processo de difusão é feito nas latentes (lembrando, o latente é aquele array de informações da imagem comprimido).
Aquelas imagens de ruído são aplicados nesses latentes, e não na imagem com pixel.
E, portanto, o Noise Predictor é, na verdade, treinado para prever o ruído na representação comprimida (o espaço latente).

Gerando exemplo de treinamentos com diferentes quantidades de ruído adicionado à suas versões comprimidas (laetentes)
Da esquerda pra direita: Imagem original > Image Encoder > Imagem Comprimida (latente) > latente +
amostra de ruido 1 na quantidade 1 …

O processo direto (usando o codificador do autoencoder) é como geramos os dados para treinar o Noise Predictor. Uma vez treinado, podemos gerar imagens executando o processo inverso (usando o decodificador do autoencoder).

Aqui a imagem acrescenta o processo reverso, na parte debaixo, mostrando que a partir de um ruído completo, aplicando as etapas, o modelo treinado vai reduzindo o ruído

Esses dois fluxos são mostrados na Figura 3 do artigo LDM/Stable Diffusion:

Esta figura mostra adicionalmente os componentes de “condicionamento”, que neste caso são os prompts de texto que descrevem qual imagem o modelo deve gerar (e existem outros).
Vamos entender como texto entra nessa história toda.


Rodrigo: Eu achava essa imagem complexa demais, e com a explicação desse artigo, ficou muito mais simples de entender. Aqui vai alguns complementos:

  • Em rosa, você pode ver escrito o “Pixel Space”, que é onde sai a imagem que vemos como resultado, ou o input que fornecemos.
  • E é o encoder e D o decoder, que transformam as imagens no Z (ou convertem para imagem), o array (latentes) , que é nada mais, nada menos, que a imagem comprimida.
  • Todo o trabalho pesado acontece nessa parte verde, que é esse espaço latente.
    • No topo do espaço verde, tem um Z –> ZT, que representa o processo de difusão. ZT é o resultado, que é o array de informações alterado pelo processo e pronto para ser convertido de volta.
    • ZT passa em várias etapas, que são representada dentro do quadro escrito “Denoising U-Net”. Basicamente é a representação do Noise Predictor sendo executado em várias etapas para ir reduzindo o ruído da imagem.
    • Tudo isso produz o ZT-1, que é a imagem depois do ruído, que foi o que vimos até aqui!
  • Ainda tem o “conditioning” e aqueles últimos passos finais após o quadro da U-Net! Esses eu ainda não relacionei direito com a explicação dada até aqui.
    Vamos continuar acompanhando o artigo e ver o que descobrimos!

O Text Encoder: Um modelo Transformer de linguagem

Um modelo Transformer de linguagem é usado como o componente que entende o texto do prompt e produz os tokens e seus embeddings. O modelo Stable Diffusion lançado usa ClipText (um modelo baseado em GPT, em inglês, escrito pelo próprio autor do artigo original), enquanto o descrito no paper usou o BERT.

A decisão do modelo de linguagem a ser usada é demonstrada pelo paper do Imagen (do Google) como sendo uma importante escolha.Trocar para um LLM teve muito mais impacto na qualidade da imagem do que adicionar mais componente na criação da imagem.

Os primeiros modelos Stable Diffusion foram plugados apenas no modelo ClipText, pré-treinado e lançado pela OpenAI. O Stable Diffusion V2 usa OpenClip e é possível que futuros modelos mudem para as outras variantes OpenCLIP, muito maiores do CLIP.
Este novo conjunto de modelos OpenClip incluem modelos de texto com tamanhos de até 354M de parâmetros, em oposição aos parâmetros de 63M no ClipText.

Como o CLIP é treinado

O CLIP é treinado com um dataset de imagens e suas legendas. Pense em dataset assim, com apenas com 400 milhões de imagens e suas legendas:

Exemplo de três imagens em um dataset: Temos a sua imagem uma descrição do que é

Na verdade, o CLIP foi treinado com imagens da web junto com suas tags “alt”. O CLIP é uma combinação de um Image Encoder (codificador de imagem) e um Text Encoder (codificador de texto). Pense em um processo onde você pega uma imagem e sua legenda. Então, nós usamos o Image Encoder e o Text encoder para codificar ambos, respectivamente.

1 – Calcule os embeddings (aquele array que representa o significado e as características) de uma imagem e de um texto

Em seguida, comparamos os embeddings resultantes usando a similaridade por cossenos (cosine similiarity, veja o comentário abaixo).

Ao iniciarmos o processo de treinamento, a similaridade será baixa, mesmo que o texto descreva a imagem corretamente.

  1. Pega o embedding do texto e imagem
  2. Comparar os embeddings e dizer se são similiares ou não

Então, atualizamos os dois modelos para que na próxima vez que os embeddings forem gerados, os resultados sejam semelhantes (isto é, a comparação do cosseno resulte como similiar)

  1. Pega o embedding do texto e imagem
  2. Comparar os embeddings e dizer se são similiares ou não
  3. Atualiza os modelos de volta (Image Encoder) e (Texto Encoder)

Repetindo isso em todo o dataset e com várias batchs, terminamos com os encoders sendo capazes de produzir embeddings onde a imagem de um cachorro e a frase “a foto de um cachorro” são semelhantes. Assim como em word2vec , o processo de treinamento também precisa incluir exemplos negativos de imagens e legendas que não correspondem, e o modelo precisa atribuir a eles pontuações baixas de similaridade.

Adicionando as informações de texto no processo de geração de imagens

Para tornar o texto parte do processo de geração de imagem, temos que ajustar nosso Noise Predictor para usar o texto como entrada.

Reparem que agora além da imagem, a quantidade de ruído, agora o embedding do texto é passado como entrada

Nosso dataset agora inclui o texto codificado. Lembre-se que tanto as imagens de entrada quanto o ruído previsto estão no espaço latente (aquele formato comprimido).

No treinamento, além do número da step, da imagem, passamos o texto!

Para ter uma noção melhor de como os tokens de texto são usados ​​na Unet, vamos descer o nível na Unet.

Camadas do Noise Predictor Unet (sem texto)

Vejamos primeiro uma Unet de difusão que não usa texto. Suas entradas e saídas seriam assim:

Se você pudesse dar um zoom nesse quadro rosa e ver a Unet funcionando, veria que:

  • A Unet é uma série de camadas que trabalham na transformação do array latente
  • Cada camada opera na saída da camada anterior
  • Algumas das saídas são alimentadas (através de conexões residuais) no processamento posterior na rede
    Conexão residuais (residual connections) são essas em que estão ligadas diretamente a saída da rede
  • O timestep é transformado em um timestep embedding vector, e é isso que é usado nas camadas
ResNet = Residual Neural Network

Camadas do Noise Predictor Unet (com texto)

Vejamos agora como alterar esse sistema para incluir atenção ao texto.

A principal mudança no sistema que precisamos, para adicionar suporte para entradas de texto (termo técnico: text conditioning/condicionamento de texto), é adicionar uma camada de atenção entre os blocos ResNet.

em roxo, foram adicionados as camadas de atenção (comparado com a mesma versao da imagem da Unet sem o texto)

Observe que o bloco ResNet não analisa diretamente o texto (repare que a linha branca não tem conexão com a azul, que representa o texto).
Mas as camadas de atenção mesclam essas representações de texto nas latentes. Como a ResNet processa o latent gerado pela camada anterior…
Agora, o próximo ResNet pode utilizar essas informações de texto incorporadas em seu processamento

Conclusão

Espero que isso lhe dê uma boa primeira visão sobre como funciona a Stable Diffusion.
Muitos outros conceitos estão envolvidos, mas acredito que sejam mais fáceis de entender quando você estiver familiarizado com esses fundamentos acima.

Recursos adicionais

Leave a Reply

Your email address will not be published. Required fields are marked *