GANs
Visão geral
Redes Adversariais Generativas (Generative Adversarial Networks, GANs) são uma família de modelos generativos (generative models) que aprendem a produzir amostras realistas (mais notoriamente imagens) por meio de treinamento adversarial (adversarial training): duas redes neurais (neural networks) competem em um jogo. GANs são conhecidas por produzir detalhes nítidos e de alta frequência em comparação com muitos modelos baseados em verossimilhança (likelihood-based models), mas também são notórias pela instabilidade de treinamento (training instability), incluindo colapso de modos (mode collapse) e dinâmicas oscilatórias/não convergentes.
Dentro de Modelagem Generativa, as GANs são frequentemente contrastadas com:
- VAEs, que otimizam um limite inferior variacional e tendem a produzir amostras mais suaves
- Modelos de Difusão, que são mais lentos para amostrar, mas são muito estáveis de treinar e dominam muitos benchmarks de geração de imagens hoje
- Modelos Autorregressivos, que modelam dados sequencialmente e podem fornecer verossimilhanças exatas/tratáveis em muitos cenários
- Modelos de Fluxo, que usam transformações invertíveis para verossimilhança exata, frequentemente com restrições arquiteturais
As GANs continuam importantes para tarefas como tradução imagem-para-imagem, super-resolução, edição e cenários em que nitidez e controlabilidade importam.
Ideia central: um jogo de dois jogadores
Uma GAN padrão tem:
- Um gerador (generator) (G(z)): mapeia ruído aleatório (z \sim p(z)) (por exemplo, Gaussiano) para uma amostra sintética (x_{\text{fake}}).
- Um discriminador (discriminator) (D(x)): retorna a probabilidade (ou pontuação) de (x) ser real (dos dados de treinamento) em vez de gerado.
O treinamento é formulado como um jogo minimax:
[ \min_G \max_D \ \mathbb{E}{x \sim p{\text{data}}}[\log D(x)] ;+; \mathbb{E}_{z \sim p(z)}[\log(1 - D(G(z)))] ]
Intuição:
- O discriminador aprende a distinguir real vs. falso.
- O gerador aprende a enganar o discriminador.
Essa configuração “adversarial” resulta em um procedimento de amostragem aprendido: após o treinamento, você pode gerar novas amostras sorteando (z) e computando (G(z)).
O que o discriminador está realmente fazendo?
Para um gerador fixo, o discriminador ótimo é:
[ D^*(x) = \frac{p_{\text{data}}(x)}{p_{\text{data}}(x) + p_G(x)} ]
Substituir (D^*) no objetivo mostra que (no cenário idealizado) o gerador minimiza uma divergência relacionada à divergência de Jensen–Shannon (Jensen–Shannon divergence, JSD) entre (p_{\text{data}}) e (p_G). Em outras palavras, o treinamento de GAN empurra a distribuição gerada em direção à distribuição dos dados.
Na prática, porém, redes profundas (deep networks), dados finitos e otimização imperfeita criam os problemas de instabilidade pelos quais as GANs são conhecidas.
O objetivo prático de treinamento (perda não saturante)
A perda minimax original do gerador pode sofrer com gradientes que desaparecem (vanishing gradients) quando o discriminador fica bom demais no início do treinamento. Uma alternativa amplamente usada é a perda do gerador não saturante (non-saturating generator loss):
- Perda do discriminador: [ \mathcal{L}D = -\mathbb{E}{x \sim p_{\text{data}}}[\log D(x)] - \mathbb{E}_{z}[\log(1 - D(G(z)))] ]
- Perda do gerador: [ \mathcal{L}G = -\mathbb{E}{z}[\log D(G(z))] ]
Essa modificação mantém os gradientes do gerador mais saudáveis quando (D(G(z))) é pequeno.
A otimização de GAN normalmente é feita com passos alternados de Descida do Gradiente (mais precisamente, otimizadores baseados em gradiente como Adam), usando Retropropagação através de ambas as redes.
Padrões canônicos de arquitetura
Embora as GANs possam ser construídas a partir de muitas Redes Neurais, vários motivos arquiteturais se repetem:
GANs convolucionais no estilo DCGAN (DCGAN-style convolutional GANs)
DCGAN popularizou escolhas de design convolucional estáveis para GANs de imagem:
- Camadas convolucionais / convolucionais transpostas
- BatchNorm (frequentemente no gerador; com cautela no discriminador)
- LeakyReLU no discriminador, ReLU no gerador (saída tanh)
Esses padrões continuam sendo uma linha de base útil para tarefas de imagem de pequeno a médio porte.
GANs condicionais (conditional GANs, cGANs)
GANs condicionais (conditional GANs, cGANs) incorporam informação de condicionamento (y) (rótulo de classe, embedding de texto (text embedding), mapa de segmentação):
[ G(z, y) \rightarrow x,\quad D(x, y) \rightarrow \text{real/fake} ]
Isso permite geração controlada como “gerar um dígito 7” ou “gerar um rosto com determinados atributos”.
Técnicas comuns de condicionamento:
- Concatenar (y) com (z)
- BatchNorm condicional / normalização adaptativa
- discriminadores por projeção (projection discriminators) (fortes para GANs condicionais por classe)
GANs de tradução imagem-para-imagem
GANs se destacam quando combinadas com perdas de reconstrução/consistência (reconstruction/consistency losses):
- Pix2Pix: tradução pareada (por exemplo, contornos → foto)
- CycleGAN: tradução não pareada usando consistência cíclica (cycle-consistency) (por exemplo, cavalos ↔ zebras)
Elas combinam uma perda adversarial (realismo) com perdas específicas da tarefa (preservação de conteúdo).
Geradores baseados em estilo
StyleGAN introduziu um gerador baseado em estilo em que uma rede de mapeamento (mapping network) produz “estilos” que modulam características em múltiplas escalas (frequentemente via normalização adaptativa de instância (Adaptive Instance Normalization, AdaIN) ou modulação relacionada). Isso possibilita:
- Síntese de alta qualidade
- Interpolações suaves no latente
- Controle mais desentrelaçado (até certo ponto)
Sistemas modernos “semelhantes a GAN” frequentemente incorporam regularização (regularization), normalização (normalization) e truques arquiteturais inspirados por StyleGAN e BigGAN.
Por que as GANs podem parecer tão boas
Uma forma útil de pensar sobre GANs é que o discriminador aprende uma função de perda treinável (trainable loss function) que penaliza amostras irreais. Diferentemente de objetivos de verossimilhança explícitos, o treinamento adversarial pode recompensar fortemente texturas nítidas e detalhadas, razão pela qual amostras de GAN podem parecer menos “borradas” do que amostras iniciais de VAE.
No entanto, essa força vem acoplada à fraqueza central: a função de perda está se movendo (porque o discriminador está aprendendo), e o jogo pode se tornar instável.
Problemas comuns de instabilidade (e por que acontecem)
O treinamento de GAN é uma forma de otimização de jogo não convexa e não côncava (non-convex, non-concave game optimization), não uma minimização padrão. Muitas patologias surgem.
Colapso de modos (mode collapse)
Colapso de modos acontece quando o gerador produz diversidade limitada — mapeando muitos valores de (z) para as mesmas (ou muito similares) saídas.
Sintomas:
- Amostras repetidas ou quase duplicadas
- Classes/variedades ausentes nos dados (por exemplo, gerar apenas “um tipo” de rosto)
Por que acontece (informalmente):
- O gerador encontra um pequeno conjunto de saídas que enganam de forma confiável o discriminador atual.
- O discriminador pode não fornecer gradientes que incentivem cobrir todos os modos dos dados.
- A dinâmica do jogo pode recompensar “exploração oportunista” em vez de “exploração ampla”.
Gradientes que desaparecem ou explodem (vanishing or exploding gradients)
- Se o discriminador fica forte demais rápido demais, o gerador pode receber gradientes fracos (especialmente com a perda minimax original).
- Arquiteturas mal escaladas ou taxas de aprendizado agressivas podem causar atualizações explosivas e divergência.
Oscilações e não convergência (oscillations and non-convergence)
Como o treinamento de GAN é um jogo, as atualizações podem “perseguir” umas às outras:
- (D) melhora → (G) se adapta → (D) se adapta, etc.
- Em vez de convergir, o treinamento pode ciclar ou oscilar.
Esse é um desafio conhecido em otimização de jogos: frequentemente são necessárias técnicas além de passos alternados ingênuos de gradiente.
Sensibilidade a hiperparâmetros e arquitetura
O desempenho de GAN pode ser altamente sensível a:
- Taxas de aprendizado e betas do otimizador
- Razão de atualização (k) (quantos passos do discriminador por passo do gerador)
- Escolhas de normalização (BatchNorm, InstanceNorm, normalização espectral)
- Estratégia de aumento de dados
- Inicialização e semente aleatória
A avaliação pode ser enganosa
GANs podem gerar amostras impressionantes “escolhidas a dedo” e ainda assim ter:
- Baixa diversidade
- Memorização dos dados de treinamento
- Artefatos que métricas podem não capturar
Isso torna a avaliação e a depuração particularmente difíceis.
Técnicas de estabilização e melhores práticas
Ao longo do tempo, a comunidade desenvolveu muitas técnicas para melhorar a confiabilidade do treinamento de GAN.
1) Objetivos melhores: GAN de Wasserstein (Wasserstein GAN, WGAN)
WGAN substitui o objetivo tipo JSD por uma aproximação da distância Wasserstein-1 (Wasserstein-1 distance) (distância do transportador de terra (Earth Mover’s Distance)), que fornece gradientes mais suaves quando as distribuições estão distantes.
Requisito chave: o crítico (discriminador) deve ser 1-Lipschitz.
A WGAN inicial impunha isso via recorte de pesos (weight clipping) (frequentemente subótimo). Uma grande melhoria é:
- WGAN-GP: adiciona uma penalidade de gradiente (gradient penalty) impondo Lipschitz de forma suave: [ \lambda \mathbb{E}{\hat{x}} \left(|\nabla{\hat{x}} D(\hat{x})|_2 - 1\right)^2 ]
Perdas no estilo WGAN costumam ser mais estáveis, especialmente no início do treinamento.
2) Normalização espectral (spectral normalization)
Normalização espectral (spectral normalization) restringe a norma espectral de cada camada, ajudando a impor comportamento Lipschitz e estabilizando o treinamento do discriminador. Ela é amplamente usada porque é:
- Eficaz
- Fácil de implementar
- Em geral menos “temperamental” do que penalidades de gradiente
3) Regra de Atualização em Duas Escalas de Tempo (Two Time-Scale Update Rule, TTUR)
Use diferentes taxas de aprendizado para gerador e discriminador (frequentemente ( \eta_D > \eta_G )), o que pode melhorar propriedades de convergência na prática.
4) Truques de regularização
Escolhas práticas comuns:
- penalidades de gradiente R1/R2 (R1/R2 gradient penalties) (regularizam gradientes do discriminador em amostras reais ou falsas)
- suavização de rótulos (label smoothing) (usar alvos como 0,9 em vez de 1,0 para real)
- ruído de instância (instance noise) (adicionar ruído às entradas do discriminador no início)
- dropout (dropout) (às vezes ajuda, mas também pode desestabilizar — use com cautela)
5) Heurísticas arquiteturais e de treinamento
- Use média móvel exponencial (Exponential Moving Average, EMA) dos pesos do gerador para avaliação/amostragem
- Evite um discriminador poderoso demais em relação ao gerador
- Garanta capacidade suficiente do modelo e normalização equilibrada
- Use pré-processamento forte e consistente e verificações de qualidade do conjunto de dados
6) Aumento de dados para GANs
Com poucos dados, o sobreajuste do discriminador é uma causa importante de colapso. Técnicas como DiffAugment (DiffAugment) e aumento adaptativo (adaptive augmentation) (por exemplo, ADA no StyleGAN2-ADA) podem melhorar dramaticamente a estabilidade ao regularizar o discriminador.
Exemplo prático: treinando uma GAN simples (pseudocódigo tipo PyTorch)
Abaixo está um loop de treinamento mínimo e legível para uma GAN vanilla com perda não saturante. Projetos reais adicionam precisão mista, EMA, aumento, logging, checkpointing, etc.
# Pseudocode-ish PyTorch example (not copy-paste complete)
G = Generator().to(device)
D = Discriminator().to(device)
opt_G = torch.optim.Adam(G.parameters(), lr=2e-4, betas=(0.5, 0.999))
opt_D = torch.optim.Adam(D.parameters(), lr=2e-4, betas=(0.5, 0.999))
bce = torch.nn.BCEWithLogitsLoss() # if D outputs logits
for real, _ in dataloader:
real = real.to(device)
batch_size = real.size(0)
# -----------------------
# 1) Update Discriminator
# -----------------------
z = torch.randn(batch_size, z_dim, device=device)
fake = G(z).detach()
logits_real = D(real)
logits_fake = D(fake)
y_real = torch.ones_like(logits_real)
y_fake = torch.zeros_like(logits_fake)
loss_D = bce(logits_real, y_real) + bce(logits_fake, y_fake)
opt_D.zero_grad()
loss_D.backward()
opt_D.step()
# -------------------
# 2) Update Generator
# -------------------
z = torch.randn(batch_size, z_dim, device=device)
fake = G(z)
logits_fake = D(fake)
# Non-saturating generator loss: maximize log D(fake)
loss_G = bce(logits_fake, torch.ones_like(logits_fake))
opt_G.zero_grad()
loss_G.backward()
opt_G.step()
Melhorias práticas comuns que você adicionaria em seguida:
- Atualizar o discriminador múltiplas vezes por passo do gerador (ou vice-versa)
- Normalização espectral em (D)
- EMA para (G)
- Aumento de dados (especialmente para conjuntos pequenos)
- Trocar para perda hinge (hinge loss) ou WGAN-GP dependendo do domínio
Como GANs são avaliadas
GANs não têm uma métrica única perfeita. Escolhas comuns:
- Distância de Inception de Fréchet (Fréchet Inception Distance, FID): compara distribuições de características de imagens reais vs. geradas (quanto menor, melhor). Amplamente usada, mas sensível ao pré-processamento e à contagem de amostras.
- Pontuação Inception (Inception Score, IS): mede classificabilidade e diversidade usando um classificador pré-treinado (frequentemente menos confiável do que a FID).
- Precisão/Revocação para modelos generativos (Precision/Recall for generative models): tenta separar “qualidade” (precisão) de “diversidade” (revocação).
- avaliação humana (human evaluation): ainda importante, especialmente para realismo perceptual e artefatos.
Melhor prática: usar múltiplas métricas + inspeção qualitativa + verificações de diversidade (por exemplo, análise de vizinhos mais próximos (nearest-neighbor analysis) para detectar memorização).
Aplicações práticas
GANs são especialmente fortes quando você quer realismo de alta frequência ou um prior adversarial aprendido.
Síntese e edição de imagens
- Síntese de rostos/imagens de alta fidelidade (família StyleGAN)
- Edição no espaço latente (espaço latente (latent space)) (manipulação de atributos, interpolação)
- Bootstrap de datasets e geração de dados sintéticos (com cautela quanto a vieses e privacidade)
Super-resolução e restauração
- super-resolução de uma única imagem (single-image super-resolution) (por exemplo, SRGAN e sucessores)
- Remoção de ruído, deblurring, remoção de artefatos
- inpainting (inpainting) (preencher regiões ausentes com conteúdo plausível)
Perdas de GAN frequentemente melhoram a nitidez perceptual versus perdas puras por pixel (MSE/PSNR), embora possam alucinar detalhes (hallucinate details) — indesejável em contextos científicos/médicos a menos que cuidadosamente validado.
Tradução imagem-para-imagem
- Tradução pareada (Pix2Pix): mapeia entradas para saídas com realismo adversarial
- Tradução não pareada (CycleGAN): adaptação de domínio (domain adaptation) sem pares alinhados
Casos de uso: transferência de estilo, mudança de estação, mapa ↔ foto aérea, adaptação de sintético para real.
Vídeo, áudio e além
- Predição e aprimoramento de vídeo (difícil devido à consistência temporal)
- Geração de fala/áudio (historicamente; hoje frequentemente superada por métodos de difusão/autorregressivos)
- GANs com consciência 3D (geram imagens consistentes com uma representação subjacente de cena 3D)
GANs em contexto: quando escolhê-las
GANs costumam ser uma boa escolha quando:
- Você precisa de amostragem rápida (um forward pass através de (G))
- Você se importa muito com nitidez perceptual
- Você pode investir em truques de estabilização e ajuste cuidadoso
- Você está fazendo tradução ou geração regularizada adversarialmente
Você pode preferir outras famílias quando:
- Você precisa de treinamento estável e ferramental forte baseado em verossimilhança → considere Modelos de Difusão ou Modelos de Fluxo
- Você quer inferência estruturada de variáveis latentes e reconstruções → considere VAEs
- Você precisa de verossimilhanças tratáveis ou estrutura sequencial → considere Modelos Autorregressivos
Na prática moderna, modelos de difusão dominam a geração de imagens de uso geral, mas GANs permanecem altamente relevantes para pipelines especializados e para tarefas em que perdas adversariais produzem melhores resultados perceptuais.
Resumo
GANs aprendem a gerar dados realistas treinando um gerador e um discriminador em um jogo adversarial. Essa configuração pode produzir amostras excepcionalmente nítidas e convincentes, mas introduz instabilidade: colapso de modos, oscilações e sensibilidade a hiperparâmetros são comuns. Um grande conjunto de técnicas — WGAN/WGAN-GP, normalização espectral, regularização, regras de atualização cuidadosas e aumento de dados — torna as GANs significativamente mais confiáveis. Entender tanto a base teórica em jogos quanto o kit prático de estabilização é essencial para usar GANs de forma eficaz em sistemas reais.