Pular para o conteúdo principal

Desmistificando redes generativas adversárias (GANs)

Entenda o que são redes generativas adversárias sem entrar nos detalhes da matemática e programe uma GAN simples que cria dígitos!
Atualizado 17 de set. de 2026  · 9 min lido

Explorar com IA

ChatGPTClaudePerplexity

Neste tutorial, você vai entender o que são as redes generativas adversárias (GANs) sem entrar nos detalhes da matemática. Depois, vai aprender a programar uma GAN simples capaz de criar dígitos!

Analogia

A maneira mais fácil de entender o que são GANs é por meio de uma analogia simples:

Imagine uma loja que compra certos tipos de vinho de clientes para depois revender.

analogia

No entanto, há clientes mal-intencionados que tentam vender vinho falso para ganhar dinheiro. Nesse cenário, a dona da loja precisa distinguir entre vinhos falsos e autênticos.

analogia

No começo, é provável que o falsificador cometa muitos erros ao tentar vender vinho falso, e a dona da loja conseguirá identificar com facilidade que o vinho não é autêntico. Por causa desses fracassos, o falsificador continuará testando técnicas diferentes para simular vinhos autênticos e, com o tempo, algumas darão certo. Ao descobrir quais técnicas passaram pelo crivo da dona da loja, ele pode aprimorar ainda mais os vinhos falsos com base nessas estratégias.

Ao mesmo tempo, a dona da loja provavelmente receberá feedback de outros lojistas ou especialistas em vinho de que alguns dos rótulos que ela tem não são originais. Isso significa que ela também precisará melhorar a forma de determinar se um vinho é falso ou autêntico. O objetivo do falsificador é criar vinhos indistinguíveis dos autênticos, e o objetivo da dona da loja é identificar com precisão se um vinho é verdadeiro ou não.

Essa disputa de gato e rato é a ideia central por trás das GANs.

Componentes de uma rede generativa adversária

Usando o exemplo acima, chegamos à arquitetura de uma GAN.

gan

Existem dois componentes principais em uma GAN: o gerador e o discriminador. No exemplo, a dona da loja representa a rede discriminadora e geralmente é uma rede neural convolucional (já que GANs são usadas principalmente em tarefas com imagens) que atribui uma probabilidade de a imagem ser real.

O falsificador é a rede geradora, que também costuma ser uma rede neural convolucional (com camadas deconvolucionais). Essa rede recebe um vetor de ruído e gera uma imagem. Durante o treinamento, a rede geradora aprende quais áreas da imagem deve melhorar/alterar para que o discriminador tenha mais dificuldade em diferenciar suas imagens das reais.

A rede geradora vai produzindo imagens cada vez mais parecidas com as reais, enquanto a rede discriminadora tenta apontar as diferenças entre imagens reais e falsas. A meta final é ter uma rede geradora capaz de produzir imagens indistinguíveis das verdadeiras.

Uma rede generativa adversária simples com Keras

Agora que você entendeu o que são GANs e seus principais componentes, vamos começar a programar um exemplo bem simples. Você vai usar o Keras e, se ainda não conhece essa biblioteca Python, vale ler este tutorial antes de continuar. Este tutorial é baseado na GAN desenvolvida aqui.

A primeira coisa a fazer é instalar os seguintes pacotes via pip

  • keras
  • matplotlib
  • tensorflow
  • tqdm

Você usará matplotlib para visualização, tensorflow como backend do Keras e tqdm para exibir uma barra de progresso bacana a cada época (iteração).

O próximo passo é criar um script em Python. Nele, primeiro importe todos os módulos e funções que serão usados. A explicação de cada um virá conforme forem utilizados.

import os
import numpy as np
import matplotlib.pyplot as plt
from tqdm import tqdm


from keras.layers import Input
from keras.models import Model, Sequential
from keras.layers.core import Dense, Dropout
from keras.layers.advanced_activations import LeakyReLU
from keras.datasets import mnist
from keras.optimizers import Adam
from keras import initializers

Agora, defina algumas variáveis:

# Let Keras know that we are using tensorflow as our backend engine
os.environ["KERAS_BACKEND"] = "tensorflow"

# To make sure that we can reproduce the experiment and get the same results
np.random.seed(10)

# The dimension of our random noise vector.
random_dim = 100

Antes de começar a construir o discriminador e o gerador, é preciso coletar e pré-processar os dados. Vamos usar o famoso conjunto MNIST, que traz imagens de dígitos de 0 a 9.

conjunto mnist

def load_minst_data():
    # load the data
    (x_train, y_train), (x_test, y_test) = mnist.load_data()
    # normalize our inputs to be in the range[-1, 1]
    x_train = (x_train.astype(np.float32) - 127.5)/127.5
    # convert x_train with a shape of (60000, 28, 28) to (60000, 784) so we have
    # 784 columns per row
    x_train = x_train.reshape(60000, 784)
    return (x_train, y_train, x_test, y_test)

Observação: a função mnist.load_data() faz parte do Keras e permite importar o conjunto MNIST para seu ambiente com facilidade.

Agora, vamos criar as redes geradora e discriminadora. Usaremos o otimizador Adam em ambas. Tanto no gerador quanto no discriminador, criaremos uma rede neural com três camadas ocultas usando a função de ativação Leaky ReLU. Também adicionaremos camadas de dropout ao discriminador para aumentar sua robustez em imagens não vistas.

# You will use the Adam optimizer
def get_optimizer():
    return Adam(lr=0.0002, beta_1=0.5)

def get_generator(optimizer):
    generator = Sequential()
    generator.add(Dense(256, input_dim=random_dim, kernel_initializer=initializers.RandomNormal(stddev=0.02)))
    generator.add(LeakyReLU(0.2))

    generator.add(Dense(512))
    generator.add(LeakyReLU(0.2))

    generator.add(Dense(1024))
    generator.add(LeakyReLU(0.2))

    generator.add(Dense(784, activation='tanh'))
    generator.compile(loss='binary_crossentropy', optimizer=optimizer)
    return generator

def get_discriminator(optimizer):
    discriminator = Sequential()
    discriminator.add(Dense(1024, input_dim=784, kernel_initializer=initializers.RandomNormal(stddev=0.02)))
    discriminator.add(LeakyReLU(0.2))
    discriminator.add(Dropout(0.3))

    discriminator.add(Dense(512))
    discriminator.add(LeakyReLU(0.2))
    discriminator.add(Dropout(0.3))

    discriminator.add(Dense(256))
    discriminator.add(LeakyReLU(0.2))
    discriminator.add(Dropout(0.3))

    discriminator.add(Dense(1, activation='sigmoid'))
    discriminator.compile(loss='binary_crossentropy', optimizer=optimizer)
    return discriminator

Hora de juntar o gerador e o discriminador!

def get_gan_network(discriminator, random_dim, generator, optimizer):
    # We initially set trainable to False since we only want to train either the
    # generator or discriminator at a time
    discriminator.trainable = False
    # gan input (noise) will be 100-dimensional vectors
    gan_input = Input(shape=(random_dim,))
    # the output of the generator (an image)
    x = generator(gan_input)
    # get the output of the discriminator (probability if the image is real or not)
    gan_output = discriminator(x)
    gan = Model(inputs=gan_input, outputs=gan_output)
    gan.compile(loss='binary_crossentropy', optimizer=optimizer)
    return gan

Para completar, podemos criar uma função que salva as imagens geradas a cada 20 épocas. Como isso não é o foco da lição, você não precisa entender cada detalhe agora.

# Create a wall of generated MNIST images
def plot_generated_images(epoch, generator, examples=100, dim=(10, 10), figsize=(10, 10)):
    noise = np.random.normal(0, 1, size=[examples, random_dim])
    generated_images = generator.predict(noise)
    generated_images = generated_images.reshape(examples, 28, 28)

    plt.figure(figsize=figsize)
    for i in range(generated_images.shape[0]):
        plt.subplot(dim[0], dim[1], i+1)
        plt.imshow(generated_images[i], interpolation='nearest', cmap='gray_r')
        plt.axis('off')
    plt.tight_layout()
    plt.savefig('gan_generated_image_epoch_%d.png' % epoch)

Pronto, você já programou a maior parte da sua rede. Agora é treinar e conferir as imagens que foram criadas.

def train(epochs=1, batch_size=128):
    # Get the training and testing data
    x_train, y_train, x_test, y_test = load_minst_data()
    # Split the training data into batches of size 128
    batch_count = x_train.shape[0] / batch_size

    # Build our GAN netowrk
    adam = get_optimizer()
    generator = get_generator(adam)
    discriminator = get_discriminator(adam)
    gan = get_gan_network(discriminator, random_dim, generator, adam)

    for e in xrange(1, epochs+1):
        print '-'*15, 'Epoch %d' % e, '-'*15
        for _ in tqdm(xrange(batch_count)):
            # Get a random set of input noise and images
            noise = np.random.normal(0, 1, size=[batch_size, random_dim])
            image_batch = x_train[np.random.randint(0, x_train.shape[0], size=batch_size)]

            # Generate fake MNIST images
            generated_images = generator.predict(noise)
            X = np.concatenate([image_batch, generated_images])

            # Labels for generated and real data
            y_dis = np.zeros(2*batch_size)
            # One-sided label smoothing
            y_dis[:batch_size] = 0.9

            # Train discriminator
            discriminator.trainable = True
            discriminator.train_on_batch(X, y_dis)

            # Train generator
            noise = np.random.normal(0, 1, size=[batch_size, random_dim])
            y_gen = np.ones(batch_size)
            discriminator.trainable = False
            gan.train_on_batch(noise, y_gen)

        if e == 1 or e % 20 == 0:
            plot_generated_images(e, generator)

if __name__ == '__main__':
    train(400, 128)

Depois de treinar por 400 épocas, você pode ver as imagens geradas. Nas imagens após a primeira época, ainda não há estrutura clara; após 40 épocas, os dígitos começam a ganhar forma; e, por fim, após 400 épocas, surgem dígitos nítidos — embora alguns ainda fiquem irreconhecíveis.

Resultados após 1 época Resultados após 40 épocas Resultados após 400 épocas
!imagens1 imagens2 imagens3

Esse código leva aproximadamente 2 minutos por época em CPU — e esse é o principal motivo da escolha. Sinta-se à vontade para testar com mais épocas e adicionar mais (e diferentes) camadas tanto no gerador quanto no discriminador. Mas lembre-se: ao usar arquiteturas mais profundas e complexas, o tempo de execução também aumenta se você estiver só com CPU. Mesmo assim, não deixe de experimentar!

Conclusão

Parabéns por chegar até aqui! Você aprendeu os fundamentos das redes generativas adversárias (GANs) de um jeito intuitivo e ainda implementou seu primeiro modelo com a ajuda do Keras. Se quiser se aprofundar em deep learning com Python, confira o curso Deep Learning in Python da DataCamp.

Tópicos
Aprendizagem profunda
Inteligência Artificial
Aprendizado de máquina

Aprofunde seus conhecimentos em Python e deep learning

Curso

Introdução a Deep Learning em Python

4 h
264.6K
Aprenda os fundamentos das redes neurais e como criar modelos de aprendizado profundo usando o Keras 2.0 em Python.
Ver detalhesRight Arrow
Iniciar Curso
Ver maisRight Arrow
Relacionado

blog

O que é um modelo generativo?

Os modelos generativos usam o aprendizado de máquina para descobrir padrões nos dados e gerar novos dados. Saiba mais sobre sua importância e aplicações em IA.
Abid Ali Awan's photo

Abid Ali Awan

11 min

blog

O que são redes neurais?

As NNs são modelos computacionais inspirados no cérebro, usados no aprendizado de máquina para reconhecer padrões e tomar decisões.
Abid Ali Awan's photo

Abid Ali Awan

7 min

Tutorial

Dominando a retropropagação: Um guia abrangente para redes neurais

Mergulhe nos fundamentos da retropropagação em redes neurais com um guia prático para treinar e avaliar um modelo para um cenário de uso de classificação de imagens.
Zoumana Keita 's photo

Zoumana Keita

14 min

Tutorial

Introdução às redes neurais profundas

Compreensão das redes neurais profundas e sua importância no mundo moderno da aprendizagem profunda da inteligência artificial
Bharath K's photo

Bharath K

13 min

Tutorial

Uma introdução às redes neurais convolucionais (CNNs)

Um guia completo para entender as CNNs, seu impacto na análise de imagens e algumas estratégias importantes para combater o overfitting para aplicações robustas de CNNs e aprendizagem profunda.
Zoumana Keita 's photo

Zoumana Keita

14 min

GNN

Tutorial

Uma introdução abrangente às redes neurais de grafos (GNNs)

Saiba tudo sobre Graph Neural Networks, inclusive o que são GNNs, os diferentes tipos de redes neurais de grafos e para que são usadas. Além disso, saiba como criar uma Graph Neural Network com o Pytorch.
Abid Ali Awan's photo

Abid Ali Awan

15 min

Ver MaisVer Mais