Table of Contents

Laboratorul 07. GAN în Generarea Procedurală

O rețea Generative Adversarial Network (GAN) este o clasă de modele de machine learning utilizată pentru sarcini generative, cum ar fi generarea de imagini, muzică, text sau alte tipuri de date. GAN-urile sunt cunoscute în special pentru capacitatea lor de a genera date foarte realiste (cum ar fi imagini fotorealiste) prin învățarea dintr-un set de date de antrenament.

Componentele unei Rețele GAN

Un GAN este format din două rețele neurale: generatorul și discriminatorul. Aceste rețele funcționează împreună într-un scenariu asemănător unui joc, în care Generatorul încearcă să producă date false care arată ca date reale, iar Discriminatorul încearcă să facă distincția între datele reale și cele false.

  1. Generatorul este responsabil pentru crearea de date sintetice (de exemplu, o imagine, muzică, teren etc.) din zgomot aleatoriu (spațiu latent). Este nevoie de un vector aleatoriu ca intrare și generează o ieșire care imită distribuția datelor țintă (de exemplu, generarea unei imagini a unei fețe care arată ca cele din setul de date de antrenament). Generatorul primește de obicei un vector de zgomot aleator ca input, care este trecut prin mai multe straturi (de obicei straturi complet conectate, straturi convoluționale sau alte tipuri) pentru a produce un output care seamănă cu date reale. Acesta învață să producă rezultate mai realiste de-a lungul timpului încercând să-l „păcălească” pe Discriminator să creadă că datele generate sunt reale.
  2. Discriminatorul etse responsabil să facă distincția între datele reale (din setul de antrenament) și datele false (generate de Generator). Acesta calculează o probabilitate care indică dacă datele de intrare sunt reale sau false. În timp, învață să devină mai bun în identificarea datelor false pe care le produce Generatorul.

Cum funcționează un GAN

Generatorul și Discriminatorul sunt antrenate simultan, dar cu obiective diferite:

Pași în procesul de antrenare:

  1. Generatorul produce date false, pornind de la un vector latent aleatoriu (de obicei eșantionat dintr-o distribuție normală)
  2. Discriminatorul primește atât date reale, cât și false (de la generator) și încearcă să le clasifice dacă sunt reale sau false.
  3. Loss Function:
    • Discriminatorul este recompensat pentru identificarea corectă a datelor reale ca fiind reale și a datelor false ca fiind false.
    • Generatorul este recompensat atunci când datele sale false sunt clasificate ca fiind reale de către Discriminator.
  4. Backpropagation: Ambele rețele (Generator și Discriminator) sunt actualizate prin backpropagation. Ponderile Discriminatorului sunt actualizate pentru a-și îmbunătăți capacitatea de a distinge datele reale de cele false, în timp ce ponderile Generatorului sunt actualizate pentru a face datele false mai realiste și mai greu de distins de datele reale.
  5. Repetarea ciclului

În timp, Generatorul devine foarte bun la producerea de date care sunt aproape imposibil de distins de datele reale, în timp ce Discriminatorul devine din ce în ce mai bun în a distinge datele reale de cele false.

Concepte Cheie

Spațiul Latent (Latent Space)

Spațiul latent este spațiul vectorilor aleatorii de intrare pentru Generator. Fiecare punct din spațiul latent va produce un teren diferit. Dacă folim vectori latenți apropiați, vom obține terenuri similare, iar dacă folosim vectori latenți îndepărtați, terenurile generate vor fi foarte diferite.

# Două vectori latenți diferiți
noise1 = torch.randn(1, 100)  # Vector aleator 1
noise2 = torch.randn(1, 100)  # Vector aleator 2

# Vor produce terenuri diferite
terrain1 = generator(noise1)
terrain2 = generator(noise2)

Seed-uri pentru Reproducibilitate

Un seed este un număr care inițializează generatorul de numere aleatorii. Pentru a obține vectori latenți aleatori diferiți, este necesar să setăm seed-uri diferite.

def generate_terrain_with_seed(generator, seed):
    generator.eval() # Mod de evaluare
    
    with torch.no_grad(): # Nu calculăm gradienți
        # Setăm seed-ul
        torch.manual_seed(seed)
        
        # Generăm zgomot
        noise = torch.randn(1, 100)
        
        # Generăm terenul
        terrain = generator(noise)
    
    return terrain[0]

Interpolare în Spațiul Latent

Prin interpolarea putem crea o tranziție graduală între doi vectori latenți.

def interpolate_latent_vectors(generator, noise_start, noise_end, steps=10):
    generator.eval()
    
    with torch.no_grad():
        for i in range(steps):
            # Calculăm alpha (0 → 1)
            alpha = i / (steps - 1)
            
            # Interpolare liniară
            noise_interpolated = (1 - alpha) * noise_start + alpha * noise_end
            
            # Generăm terenul
            terrain = generator(noise_interpolated)

Layers

Într-un GAN, straturile din rețelele generatoare și discriminatoare îndeplinesc roluri specifice în generarea și distingerea datelor reale de cele false.

Generator Layers

Discriminator Layers

Implementarea unui Generator GAN în PyTorch

class Generator(nn.Module):
    def __init__(self):
        super(Generator, self).__init__()
        self.model = nn.Sequential(
            nn.Linear(100, 256),  # First linear layer (input: 100 -> 256)
            nn.ReLU(),            # Activation function
            nn.Linear(256, 512),  # Second linear layer (256 -> 512)
            nn.ReLU(),            # Activation function
            nn.Linear(512, 1024), # Third linear layer (512 -> 1024)
            nn.ReLU(),            # Activation function
            nn.Linear(1024, 64*64),  # Final layer (1024 -> 64x64 terrain)
            nn.Tanh()             # Activation function for output (-1 to 1)
        )

    def forward(self, x):
        return self.model(x).view(-1, 64, 64)

Tasks

  1. Generați 5 hărți aleatorii de teren folosind o rețea Generator:
    • Inițializați un Generator
    • Generați 5 terenuri diferite folosind vectori latenți aleatorii
    • Vizualizați cele 5 terenuri într-o grilă
    • Salvați imaginea rezultată
  2. Bonus. Interpolați doi vectori latenți:
    • Generați doi vectori latenți aleatorii (A și B)
    • Interpolați între ei în 10 pași
    • Vizualizați tranziția de la A la B
    • Salvați imaginea rezultată