Les Xarxes Generatives Adversàries (GANs) són un tipus de model d'aprenentatge automàtic que consisteix en dues xarxes neuronals que competeixen entre si: una xarxa generadora i una xarxa discriminadora. Aquestes xarxes s'entrenen conjuntament en un procés adversarial, on la xarxa generadora intenta crear dades falses que semblin reals, mentre que la xarxa discriminadora intenta distingir entre dades reals i falses.

Objectius d'Aprenentatge

  • Comprendre la teoria darrere de les GANs.
  • Aprendre a construir i entrenar una GAN bàsica amb PyTorch.
  • Explorar aplicacions pràctiques de les GANs.

Contingut

  1. Teoria de les GANs

1.1. Components de les GANs

  • Generador (G): Crea dades falses a partir d'un soroll aleatori.
  • Discriminador (D): Avalua si les dades són reals o falses.

1.2. Procés d'Entrenament

  • Objectiu del Generador: Enganyar el discriminador perquè classifiqui les dades generades com a reals.
  • Objectiu del Discriminador: Distingir correctament entre dades reals i generades.

1.3. Funció de Pèrdua

  • Pèrdua del Discriminador: \[ \mathcal{L}D = -\mathbb{E}{x \sim p_{\text{data}}(x)}[\log D(x)] - \mathbb{E}_{z \sim p_z(z)}[\log (1 - D(G(z)))] \]
  • Pèrdua del Generador: \[ \mathcal{L}G = -\mathbb{E}{z \sim p_z(z)}[\log D(G(z))] \]

  1. Construcció d'una GAN amb PyTorch

2.1. Importació de Llibreries Necessàries

import torch
import torch.nn as nn
import torch.optim as optim
import torchvision.datasets as dsets
import torchvision.transforms as transforms
from torch.utils.data import DataLoader

2.2. Definició del Generador

class Generador(nn.Module):
    def __init__(self, input_size, hidden_size, output_size):
        super(Generador, self).__init__()
        self.main = nn.Sequential(
            nn.Linear(input_size, hidden_size),
            nn.ReLU(True),
            nn.Linear(hidden_size, hidden_size),
            nn.ReLU(True),
            nn.Linear(hidden_size, output_size),
            nn.Tanh()
        )

    def forward(self, x):
        return self.main(x)

2.3. Definició del Discriminador

class Discriminador(nn.Module):
    def __init__(self, input_size, hidden_size, output_size):
        super(Discriminador, self).__init__()
        self.main = nn.Sequential(
            nn.Linear(input_size, hidden_size),
            nn.ReLU(True),
            nn.Linear(hidden_size, hidden_size),
            nn.ReLU(True),
            nn.Linear(hidden_size, output_size),
            nn.Sigmoid()
        )

    def forward(self, x):
        return self.main(x)

2.4. Inicialització de Models i Optimitzadors

input_size = 100
hidden_size = 256
output_size = 784  # Per a imatges de 28x28

G = Generador(input_size, hidden_size, output_size)
D = Discriminador(output_size, hidden_size, 1)

criterion = nn.BCELoss()
optimizerD = optim.Adam(D.parameters(), lr=0.0002)
optimizerG = optim.Adam(G.parameters(), lr=0.0002)

2.5. Entrenament de la GAN

num_epochs = 100
batch_size = 100
transform = transforms.Compose([
    transforms.ToTensor(),
    transforms.Normalize(mean=(0.5,), std=(0.5,))
])

mnist = dsets.MNIST(root='./data', train=True, transform=transform, download=True)
data_loader = DataLoader(dataset=mnist, batch_size=batch_size, shuffle=True)

for epoch in range(num_epochs):
    for i, (images, _) in enumerate(data_loader):
        # Entrenament del Discriminador
        D.zero_grad()
        real_images = images.view(-1, 28*28)
        real_labels = torch.ones(batch_size, 1)
        fake_labels = torch.zeros(batch_size, 1)

        outputs = D(real_images)
        d_loss_real = criterion(outputs, real_labels)
        d_loss_real.backward()

        z = torch.randn(batch_size, input_size)
        fake_images = G(z)
        outputs = D(fake_images.detach())
        d_loss_fake = criterion(outputs, fake_labels)
        d_loss_fake.backward()
        optimizerD.step()

        # Entrenament del Generador
        G.zero_grad()
        outputs = D(fake_images)
        g_loss = criterion(outputs, real_labels)
        g_loss.backward()
        optimizerG.step()

        if (i+1) % 200 == 0:
            print(f'Epoch [{epoch+1}/{num_epochs}], Step [{i+1}/{len(data_loader)}], d_loss: {d_loss_real.item()+d_loss_fake.item():.4f}, g_loss: {g_loss.item():.4f}')

  1. Aplicacions Pràctiques de les GANs

  • Generació d'Imatges: Crear imatges realistes a partir de soroll aleatori.
  • Augmentació de Dades: Generar dades sintètiques per millorar l'entrenament de models.
  • Superresolució d'Imatges: Millorar la resolució d'imatges de baixa qualitat.
  • Traducció d'Imatges: Convertir imatges d'un domini a un altre (per exemple, de fotos a pintures).

  1. Exercicis Pràctics

Exercici 1: Modificar la Xarxa Generadora

  • Objectiu: Afegir més capes al generador i observar com afecta la qualitat de les imatges generades.
  • Solució:
class Generador(nn.Module):
    def __init__(self, input_size, hidden_size, output_size):
        super(Generador, self).__init__()
        self.main = nn.Sequential(
            nn.Linear(input_size, hidden_size),
            nn.ReLU(True),
            nn.Linear(hidden_size, hidden_size),
            nn.ReLU(True),
            nn.Linear(hidden_size, hidden_size),
            nn.ReLU(True),
            nn.Linear(hidden_size, output_size),
            nn.Tanh()
        )

    def forward(self, x):
        return self.main(x)

Exercici 2: Utilitzar un Dataset Diferent

  • Objectiu: Entrenar la GAN amb un dataset diferent, com CIFAR-10.
  • Solució:
transform = transforms.Compose([
    transforms.Resize(32),
    transforms.ToTensor(),
    transforms.Normalize(mean=(0.5, 0.5, 0.5), std=(0.5, 0.5, 0.5))
])

cifar10 = dsets.CIFAR10(root='./data', train=True, transform=transform, download=True)
data_loader = DataLoader(dataset=cifar10, batch_size=batch_size, shuffle=True)

  1. Errors Comuns i Consells

  • Mode Collapse: El generador produeix una varietat limitada de mostres. Solució: Ajustar els hiperparàmetres o utilitzar tècniques com el gradient penalty.
  • Entrenament Desbalancejat: El discriminador o el generador aprenen massa ràpidament. Solució: Ajustar les taxes d'aprenentatge o entrenar el discriminador més sovint.

Conclusió

Les GANs són una eina poderosa per a la generació de dades sintètiques i tenen aplicacions en una àmplia varietat de camps. Amb PyTorch, és possible construir i entrenar GANs de manera eficient, permetent als desenvolupadors explorar noves fronteres en l'aprenentatge automàtic.

© Copyright 2024. Tots els drets reservats