Ir para o conteúdo

4. VAE

Prazo e Entrega

📅 22.out (quinta) 2026

🕐 Commits até 23:59

Individual


Clique aqui para entregar

Atividade: Autoencoders Variacionais (VAEs)

Esta atividade é projetada para testar suas habilidades em Autoencoders Variacionais (VAEs).

O fio condutor da atividade é o cabo de guerra dentro da perda. Um VAE paga por duas coisas ao mesmo tempo: reconstruir a entrada e manter o espaço latente perto de um prior do qual se sabe amostrar. Primeiro um VAE de verdade no MNIST, registrando os dois termos separadamente; depois um espaço latente 2-D que dá para enxergar, para ver o que esse prior compra — e quanto custa.

Regras técnicas (valem para toda a atividade)

  • Fixe as sementes — torch.manual_seed(42) antes de construir cada modelo e o gerador da divisão dado no Exercício 1. Resultados que não podem ser reproduzidos não valem ponto;
  • Todo gráfico deve ter título e rótulos nos eixos; todo gráfico de dispersão, legenda das classes;
  • Bibliotecas permitidas: torch e torchvision (para carregar o MNIST), numpy, matplotlib/seaborn e scipy/scikit-learn para utilidades (quantis, PCA). Autograd é permitido desta vez — o ponto da atividade é o VAE, não a retropropagação. Mas as partes próprias do VAE — a reparametrização, os dois termos da perda e a amostragem — DEVEM SER ESCRITAS POR VOCÊ. Nada de classe de VAE pronta de biblioteca (pythae, o AutoencoderKL do diffusers, …) nem de torch.distributions.kl_divergence: a KL em forma fechada é escrita por extenso. Usar um deles zera o critério de implementação;
  • Reporte os dois termos da perda separadamente, em nats por imagem (somados sobre os 784 pixels, com média sobre as imagens). Um total que cai não diz nada sobre qual dos dois termos está vencendo;
  • O conjunto de teste é usado só para os números finais de cada modelo. Toda decisão durante o treino olha para o conjunto de validação;
  • Sempre que o enunciado pedir um número (um termo da perda, uma KL, um índice de teste), reporte o número no texto — não apenas na saída do código;
  • Organize o relatório com um título por exercício e um subtítulo por item (Exercício 1, A, B, …), na mesma ordem do enunciado e numere as figuras como indicado. A última seção do relatório deve ser o Resumo dos resultados descrito no fim desta página.

Exercício 1

Um VAE no MNIST

A — Carregue e divida os dados

Use o MNIST do torchvision, com pixels em \([0, 1]\) (o transforms.ToTensor() já faz isso), achatados em vetores de 784. Divida as 60 000 imagens de treino em 50 000 para treino e 10 000 para validação, exatamente assim:

from torch.utils.data import random_split

train_full = datasets.MNIST("data", train=True, download=True, transform=transforms.ToTensor())
test = datasets.MNIST("data", train=False, download=True, transform=transforms.ToTensor())
train, val = random_split(train_full, [50_000, 10_000],
                          generator=torch.Generator().manual_seed(42))

As 10 000 imagens oficiais de teste são o conjunto de teste.

B — Construa o modelo

Use esta arquitetura, para que os números do relatório possam ser comparados entre si e com os valores de referência abaixo:

Parte Camadas
Encoder \(784 \to 512 \to 256\), ReLU depois de cada uma
Cabeças duas camadas lineares \(256 \to d\): uma para \(\boldsymbol{\mu}\), outra para \(\log \boldsymbol{\sigma}^2\)
Decoder \(d \to 256 \to 512 \to 784\), ReLU depois das camadas ocultas, sigmoide na saída

com dimensão latente \(d = 16\). A perda por imagem, somada sobre os pixels e sobre as dimensões latentes:

\[ L = \underbrace{-\sum_{j=1}^{784} \Big[x_j \log \hat{x}_j + (1 - x_j) \log (1 - \hat{x}_j)\Big]}_{\text{reconstrução (BCE)}} \;+\; \beta \cdot \underbrace{\tfrac{1}{2}\sum_{i=1}^{d} \left(\mu_i^2 + \sigma_i^2 - 1 - \log \sigma_i^2\right)}_{\text{KL}} \]

com \(\beta = 1\) e média sobre as imagens do lote.

Por que BCE aqui e \(\|\mathbf{x} - \hat{\mathbf{x}}\|^2\) na aula

As duas são \(-\log p(\mathbf{x} \mid z)\), o termo de reconstrução do ELBO, sob duas hipóteses diferentes sobre os pixels. Uma verossimilhança gaussiana dá o erro quadrático; uma verossimilhança de Bernoulli — cada pixel uma probabilidade de estar "aceso", que é o que uma saída sigmoide significa — dá a entropia cruzada binária. Os pixels do MNIST são quase todos 0 ou 1, então a Bernoulli se encaixa. Use F.binary_cross_entropy(..., reduction="sum") e divida pelo tamanho do lote; reduction="mean" também tiraria a média sobre os pixels e encolheria o termo de reconstrução 784 vezes em relação à KL, o que equivale a fixar \(\beta \approx 784\) escondido.

C — Treine

Treine com Adam, taxa de aprendizado \(10^{-3}\), lotes de 128, por 20 épocas. No fim de cada época, registre o termo de reconstrução e o termo KL no treino (a média ao longo da época) e na validação. Depois:

  1. Reporte a reconstrução no teste, a KL no teste e a soma das duas (o ELBO negativo), em nats por imagem. Uma implementação correta fica em torno de 81 nats de reconstrução e 20 nats de KL. Numa CPU de notebook leva cerca de meio minuto;
  2. Produza a Figura 1: dois painéis, reconstrução \(\times\) época e KL \(\times\) época, cada um com a curva de treino e a de validação.

D — Reconstruções e amostras

  1. Produza a Figura 2: a primeira imagem de teste de cada dígito de 0 a 9 na linha de cima e sua reconstrução na linha de baixo. Reconstrua decodificando \(\boldsymbol{\mu}\) — não amostre \(z\).
  2. Produza a Figura 3: uma grade \(8 \times 8\) de imagens decodificadas de \(z \sim \mathcal{N}(0, I)\), sorteadas depois de torch.manual_seed(0).

E — Análise

  1. Figura 1: a KL sobe nas primeiras épocas enquanto a perda total cai. Por que o otimizador escolheria pagar mais KL?
  2. A Figura 3 parece pior que a Figura 2 — dígitos mais borrados, alguns que não são dígito nenhum. Dê duas razões distintas: uma sobre onde as amostras do prior caem no espaço latente e outra sobre o que o decoder produz para um dado \(z\) (a seção da aula sobre o borrão).
  3. Por que decodificar \(\boldsymbol{\mu}\) e não um \(z\) amostrado na Figura 2?

Exercício 2

Um espaço latente que dá para ver

Com \(d = 16\) o espaço latente não pode ser desenhado. Com \(d = 2\) pode — a um preço que este exercício pede para você medir.

A — Treine um VAE 2-D

Treine o mesmo modelo do Exercício 1, mudando apenas \(d = 2\). Mesmos dados, semente, \(\beta\) e orçamento de treino. Reporte a reconstrução e a KL no teste (espere algo perto de 135 e 7 nats) ao lado dos números de \(d = 16\).

B — O conjunto de teste codificado

Produza a Figura 4: um gráfico de dispersão de \(\boldsymbol{\mu}\) para as 10 000 imagens de teste, colorido por dígito, com legenda.

C — O plano decodificado

Produza a Figura 5: decodifique uma grade \(15 \times 15\) de pontos latentes e disponha as imagens no mesmo arranjo. Não espace a grade linearmente: use \(z = \Phi^{-1}(q)\), em que \(q\) percorre 15 valores igualmente espaçados em \([0.05, 0.95]\) e \(\Phi^{-1}\) é a inversa da CDF de \(\mathcal{N}(0, 1)\) (scipy.stats.norm.ppf). Diga em uma frase por que esse espaçamento dá a cada célula a mesma massa do prior.

D — Interpolação

Escolha duas imagens de teste de dígitos diferentes e reporte os índices. Produza a Figura 6 com duas linhas de 10 imagens cada, para \(t\) de 0 a 1:

  • linha de cima, no espaço dos pixels: \((1 - t)\,\mathbf{x}_a + t\,\mathbf{x}_b\);
  • linha de baixo, no espaço latente, com o modelo \(d = 16\) do Exercício 1: decodifique \((1 - t)\,\boldsymbol{\mu}_a + t\,\boldsymbol{\mu}_b\).

E — Análise

  1. Quais dígitos se sobrepõem na Figura 4? Encontre a mesma transição na Figura 5 e descreva como são as imagens do meio do caminho.
  2. \(d = 2\) reconstrói claramente pior que \(d = 16\). O que dois números por imagem obrigam o modelo a jogar fora? Use a Figura 5 como evidência.
  3. Compare as duas linhas da Figura 6. Qual delas passa por imagens que parecem dígitos e por que a outra não passa?

Resumo dos resultados

Encerre o relatório com esta tabela, preenchida:

# Quantidade Valor
1 Ex. 1 — reconstrução, KL e ELBO negativo no teste (\(d = 16\))
2 Ex. 1 — KL de validação na primeira e na última época
3 Ex. 2 — reconstrução e KL no teste (\(d = 2\))
4 Ex. 2 — os dois índices de teste interpolados

Critérios de Avaliação

O entregável desta atividade é um relatório que inclui:

  1. O código do seu VAE, da perda e do laço de treino, comentado.
  2. As Figuras 1 a 6, numeradas conforme pedido.
  3. Suas respostas às perguntas de análise dos itens 1E e 2E.
  4. A tabela de Resumo dos resultados.

Notas Importantes:

  • A entrega é um site no GitHub Pages apoiado em um repositório público — veja Formato de Entrega para a estrutura obrigatória, o front matter e o checklist;

  • Há uma política estrita contra plágio. Qualquer forma de plágio resultará em nota zero na atividade e pode levar a outras medidas disciplinares conforme as políticas de integridade acadêmica da universidade;

  • O prazo de cada atividade não é estendido — NENHUMA EXCEÇÃO será feita para entregas atrasadas.

  • Colaboração com IA é permitida, mas cada aluno DEVE ENTENDER e ser capaz de explicar todas as partes do código e da análise entregues. Qualquer uso de ferramentas de IA deve ser devidamente citado. PROVAS ORAIS podem ser realizadas.

Critérios de Nota:

Cada linha vale os pontos indicados, atribuídos integralmente, parcialmente (metade) ou não atribuídos: integralmente quando o item está completo e correto; parcialmente quando está implementado mas falta a análise pedida, ou quando a análise não traz o resultado numérico que a sustenta; zero quando ausente ou incorreto.

A aparência das amostras não é avaliada, nem os valores da perda em si. Dados, arquitetura e sementes são fixos, então os números são o que são; o que se avalia é o método, as figuras e o relato honesto do que você obteve.

Exercício 1 — VAE no MNIST (5 pontos):

Pontos Critério O que garante nota cheia
0,5 Dados (A) A divisão e o gerador especificados; o teste não usado antes dos números finais.
2,0 Modelo e perda (B) A arquitetura especificada; reparametrização, BCE somada sobre os pixels e KL em forma fechada escritas à mão e corretas.
1,0 Treino (C) Os dois termos registrados separadamente no treino e na validação, números de teste reportados, Figura 1 correta.
0,5 Reconstruções e amostras (D) Figuras 2 e 3 como especificado — reconstrução a partir de \(\boldsymbol{\mu}\), amostras do prior com a semente dada.
1,0 Análise (E) A subida da KL explicada; duas razões distintas para a Figura 3 parecer pior que a Figura 2; por que \(\boldsymbol{\mu}\) na Figura 2.

Exercício 2 — Espaço latente 2-D (5 pontos):

Pontos Critério O que garante nota cheia
1,0 Modelo 2-D (A) Mesmo modelo e orçamento com \(d = 2\), números reportados ao lado dos de \(d = 16\).
1,0 Teste codificado (B) Figura 4 com todos os pontos de teste e legenda.
1,0 Plano decodificado (C) Figura 5 na grade de \(\Phi^{-1}\), com a frase sobre o porquê.
1,0 Interpolação (D) Figura 6 com as duas linhas, índices reportados, linha latente com o modelo \(d = 16\).
1,0 Análise (E) Sobreposição localizada nas Figuras 4 e 5; o custo de \(d = 2\) explicado; as duas interpolações contrastadas.