Skip to content

Introdução às Redes Generativas Adversárias (GANs): Construa seus Primeiros Modelos

    gans

    Você já imaginou ensinar uma máquina a criar novas imagens, músicas ou textos? Parece coisa de ficção científica, mas com as Redes Generativas Adversárias (GANs), isso é possível! Neste tutorial, vamos explorar o fascinante mundo das GANs e aprender como construir nossos próprios modelos.

    O que são Redes Generativas Adversárias (GANs)?

    As GANs são um tipo especial de rede neural que pode criar coisas incríveis! Elas têm dois amigos principais: o Gerador, que é um mago criativo, e o Discriminador, que é um perito em descobrir segredos. Juntos, eles competem para criar imagens, músicas e textos que parecem reais, mesmo que sejam totalmente inventados!

    Preparando os Dados de Treinamento

    Vamos começar preparando os dados de treinamento. Neste exemplo, vamos usar o famoso conjunto de dados MNIST, que contém imagens de dígitos escritos à mão. Para carregar os dados, utilizaremos o PyTorch.

    # Importando as bibliotecas necessárias
    import torch
    import torch.nn as nn
    import torchvision
    import torchvision.transforms as transforms
    
    # Definindo transformações para os dados
    transform = transforms.Compose([
        transforms.ToTensor(),
        transforms.Normalize((0.5,), (0.5,))
    ])
    
    # Carregando o conjunto de treinamento do MNIST
    train_set = torchvision.datasets.MNIST(root='./data', train=True, download=True, transform=transform)
    
    # Criando um data loader para o conjunto de treinamento
    batch_size = 32
    train_loader = torch.utils.data.DataLoader(train_set, batch_size=batch_size, shuffle=True)
    

    Implementando o Discriminador

    Nosso primeiro desafio é construir o discriminador. Imagine-o como um especialista que analisa as imagens e diz se são reais ou não. Com a ajuda do PyTorch, criamos um modelo inteligente para fazer esse trabalho.

    class Discriminador(nn.Module):
        def __init__(self):
            super().__init__()
            self.model = nn.Sequential(
                nn.Linear(784, 1024),
                nn.ReLU(),
                nn.Dropout(0.3),
                nn.Linear(1024, 512),
                nn.ReLU(),
                nn.Dropout(0.3),
                nn.Linear(512, 256),
                nn.ReLU(),
                nn.Dropout(0.3),
                nn.Linear(256, 1),
                nn.Sigmoid()
            )
            
        def forward(self, x):
            x = x.view(x.size(0), 784)
            output = self.model(x)
            return output
    
    # Criando uma instância do discriminador e enviando para o dispositivo de treinamento (CPU ou GPU)
    dispositivo = torch.device("cuda" if torch.cuda.is_available() else "cpu")
    discriminador = Discriminador().to(device=dispositivo)
    

    Implementando o Gerador

    Agora é a hora de trazer nosso gerador para a ação! Ele é o artista do grupo, capaz de criar imagens incríveis a partir de dados aleatórios. Vou te mostrar como construir um modelo gerador poderoso usando o PyTorch.

    class Gerador(nn.Module):
        def __init__(self):
            super().__init__()
            self.model = nn.Sequential(
                nn.Linear(100, 256),
                nn.ReLU(),
                nn.Linear(256, 512),
                nn.ReLU(),
                nn.Linear(512, 1024),
                nn.ReLU(),
                nn.Linear(1024, 784),
                nn.Tanh()
            )
            
        def forward(self, x):
            output = self.model(x)
            output = output.view(x.size(0), 1, 28, 28)
            return output
    
    # Criando uma instância do gerador e enviando para o dispositivo de treinamento
    gerador = Gerador().to(device=dispositivo)
    

    Treinando os Modelos

    Agora que temos o discriminador e o gerador prontos, vamos começar o treinamento! Ao longo do processo, eles competem para melhorar suas habilidades. Você ficará impressionado com o quão rápido esses modelos se tornam verdadeiros mestres na criação de imagens realistas.

    # Definindo hiperparâmetros de treinamento
    lr = 0.001
    num_epochs = 300
    criterion = nn.BCELoss()
    optimizer_discriminador = torch.optim.Adam(discriminador.parameters(), lr=lr)
    optimizer_gerador = torch.optim.Adam(gerador.parameters(), lr=lr)
    
    # Treinando os modelos
    for epoch in range(num_epochs):
        for n, (real_samples, _) in enumerate(train_loader):
            # Data para treinar o discriminador
            real_samples = real_samples.to(device=dispositivo)
            real_samples_labels = torch.ones((batch_size, 1)).to(device=dispositivo)
            latent_space_samples = torch.randn((batch_size, 100)).to(device=dispositivo)
            generated_samples = gerador(latent_space_samples)
            generated_samples_labels = torch.zeros((batch_size, 1)).to(device=dispositivo)
            all_samples = torch.cat((real_samples, generated_samples))
            all_samples_labels = torch.cat((real_samples_labels, generated_samples_labels))
    
            # Treinando o discriminador
            discriminador.zero_grad()
            output_discriminador = discriminador(all_samples)
            loss_discriminador = criterion(output_discriminador, all_samples_labels)
            loss_discriminador.backward()
            optimizer_discriminador.step()
    
            # Data para treinar o gerador
            latent_space_samples = torch.randn((batch_size, 100)).to(device=dispositivo)
    
            # Treinando o gerador
            gerador.zero_grad()
            generated_samples = gerador(latent_space_samples)
            output_discriminador_gerado = discriminador(generated_samples)
            loss_gerador = criterion(output_discriminador_gerado, real_samples_labels)
            loss_gerador.backward()
            optimizer_gerador.step()
    
            # Mostrando a perda a cada 10 epochs
            if epoch % 10 == 0 and n == len(train_loader) - 1:
                print(f"Epoch: {epoch} Perda Discriminador: {loss_discriminador}")
                print(f"Epoch: {epoch} Perda Gerador: {loss_gerador}")
    

    Verificando as Amostras Geradas pelas GANs

    Para isso, vamos alimentar algumas amostras aleatórias do espaço latente no gerador e plotar as imagens geradas.

    import matplotlib.pyplot as plt
    
    # Configurando o gerador para o modo de avaliação (sem atualizar os gradientes)
    gerador.eval()
    
    # Gerando amostras
    amostras_latentes = torch.randn(16, 100).to(device=dispositivo)
    amostras_geradas = gerador(amostras_latentes).cpu().detach()
    
    # Plotando as amostras geradas
    fig, axes = plt.subplots(4, 4, figsize=(8, 8))
    for i in range(16):
        ax = axes[i // 4, i % 4]
        ax.imshow(amostras_geradas[i].reshape(28, 28), cmap='gray_r')
        ax.axis('off')
    
    plt.show()
    

    Com o código acima, você deve ver uma matriz de 16 imagens geradas pelo modelo. Essas imagens serão semelhantes aos dígitos escritos à mão do conjunto de treinamento MNIST, mas elas não são cópias exatas, pois foram criadas pelo gerador.

    Conclusão

    Parabéns! Você acabou de dar seus primeiros passos no mundo das Redes Generativas Adversárias (GANs). As GANs são uma área empolgante da inteligência artificial que tem sido usada para uma ampla variedade de aplicações, desde geração de imagens até síntese de músicas e muito mais.

    Com a implementação das GANs, você aprendeu:

    • GANs são redes neurais especiais que podem criar dados realistas
    • O discriminador é o especialista em dizer o que é real e o que é falso
    • O gerador é o artista que cria dados a partir de números aleatórios
    • Os modelos competem entre si para melhorar suas habilidades
    • Você pode criar coisas mágicas com as GANs, basta usar sua imaginação!

    Agora é com você! Explore e crie suas próprias GANs para surpreender o mundo com sua magia tecnológica. Divirta-se!

    Referências Adicionais

    Leave a Reply

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