Memahami Cara Kerja Generator dan Discriminator pada model GAN Generativ Adversarial Network. Bisa kita analogikan Pemalsu Uang vs Polisi. Bayangkan: Generator = Pemalsu uang. Dia mencoba membuat uang palsu yang sedekat mungkin dengan uang asli; Discriminator = Polisi, Dia bertugas mengecek apakah uang itu asli atau palsu.
Permainan ini berulang terus:
-
Awalnya, pemalsu uang jelek banget bikin uang palsu.
-
Polisi gampang banget mendeteksi kalau uang itu palsu.
-
Tapi lama-kelamaan, pemalsu jadi makin pintar, belajar dari kesalahan.
-
Polisi juga belajar jadi makin jago membedakan yang asli dan palsu.
-
Akhirnya, uang palsu bisa sangat mirip uang asli — bahkan polisi pun bisa tertipu.
Sekarang Kita Lihat Secara Teknis
1. Generator (G)
Contents
-
Input: Noise (vektor acak), misalnya 100 angka acak dari distribusi normal.
-
Output: Data palsu yang mirip data asli, misalnya gambar angka tulisan tangan seperti MNIST.
Tugas Generator:
Belajar cara menghasilkan data yang terlihat seperti data nyata agar Discriminator mengira itu asli.
import torch.nn as nn
class Generator(nn.Module):
def __init__(self, noise_dim=100, img_dim=28*28):
super(Generator, self).__init__()
self.model = nn.Sequential(
nn.Linear(noise_dim, 256),
nn.ReLU(True),
nn.Linear(256, img_dim),
nn.Tanh() # hasil di antara [-1, 1]
)
def forward(self, z):
return self.model(z)
Contoh input-output Generator:
# Input noise z = torch.randn(1, 100) # 1 sample, 100-dim noise vector # Output gambar palsu fake_image = Generator(z) # output-nya mirip gambar 28x28
2. Discriminator (D)
-
Input: Data, bisa data asli dari dataset, atau data palsu dari Generator.
-
Output: Nilai antara 0 dan 1, yang menunjukkan “seberapa asli” data itu menurut Discriminator.
Tugas Discriminator:
Belajar membedakan data asli (label = 1) dan palsu (label = 0).
class Discriminator(nn.Module):
def __init__(self, img_dim=28*28):
super(Discriminator, self).__init__()
self.model = nn.Sequential(
nn.Linear(img_dim, 256),
nn.LeakyReLU(0.2),
nn.Linear(256, 1),
nn.Sigmoid()
)
def forward(self, x):
return self.model(x)
Contoh input-output Discriminator:
# Cek gambar asli output_real = Discriminator(real_image) # harus mendekati 1 # Cek gambar palsu output_fake = Discriminator(fake_image) # harus mendekati 0
Tujuan Pelatihan GAN
-
Discriminator dilatih agar:
-
Menghasilkan
1untuk data asli. -
Menghasilkan
0untuk data palsu dari Generator.
-
-
Generator dilatih agar:
-
Menghasilkan data palsu yang membuat Discriminator salah tebak (menghasilkan
1untuk data palsu).
-
Siklus Latihan (Training Loop)
Setiap langkah pelatihan biasanya seperti ini:
-
Generator bikin data palsu dari noise.
-
Discriminator diberi data asli dan data palsu → belajar membedakan.
-
Generator melihat hasil dari Discriminator → belajar membuat data yang lebih meyakinkan.
Mereka saling “mendorong” performa satu sama lain.
Contoh Kasus
Misalnya kita latih GAN untuk membuat gambar angka (0–9):
-
Generator belajar membuat gambar angka palsu.
-
Discriminator belajar membedakan gambar angka asli dari palsu.
-
Generator belajar memperbaiki kesalahan dari Discriminator.
-
Hasil akhirnya: Generator bisa menghasilkan gambar angka yang sangat mirip tulisan tangan manusia.
mari kita coba dengan dataset MNIST
import torch
import torch.optim as optim
from torchvision.datasets import MNIST
from torchvision import transforms
from torch.utils.data import DataLoader
# Hyperparameter
batch_size = 64
lr = 0.0002
epochs = 50
noise_dim = 100
img_dim = 28*28
# Data
transform = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize((0.5,), (0.5,))
])
dataset = MNIST(root='./data', download=False, transform=transform)
loader = DataLoader(dataset, batch_size=batch_size, shuffle=True)
lanjut
# Model & Optimizer
G = Generator(noise_dim, img_dim).to("cpu")
D = Discriminator(img_dim).to("cpu")
criterion = nn.BCELoss()
optim_G = optim.Adam(G.parameters(), lr=lr)
optim_D = optim.Adam(D.parameters(), lr=lr)
mari kita lanjut training
# Training Loop
epochs = 2000
for epoch in range(1000, epochs):
for real, _ in loader:
gambar_real = real.view(-1, img_dim).to("cpu") # dijadikan vektor
batch_size = real.size(0)
# Label real = 1, fake = 0
real_labels = torch.ones(batch_size, 1).to("cpu")
fake_labels = torch.zeros(batch_size, 1).to("cpu")
# generator
z = torch.randn(batch_size, noise_dim).to("cpu")
gambar_fake = G(z) # Menghasilkan data palsu yang menyerupai data asli
# ---------------------
# Train Discriminator
# ---------------------
D_real = D(gambar_real)
D_fake = D(gambar_fake.detach())
loss_D = criterion(D_real, real_labels) + criterion(D_fake, fake_labels)
optim_D.zero_grad()
loss_D.backward()
optim_D.step()
# ---------------------
# Train Generator
# ---------------------
output = D(gambar_fake)
loss_G = criterion(output, real_labels) # we want D to think fake is real
optim_G.zero_grad()
loss_G.backward()
optim_G.step()
if epoch % 10==0:
print(f"Epoch {epoch+1}/{epochs}, Loss D: {loss_D.item()}, Loss G: {loss_G.item()}")
untuk inferensi
import torchvision.utils as vutils
import matplotlib.pyplot as plt
# Set Generator ke eval mode (opsional tapi disarankan)
G.eval()
# Buat 16 vektor noise random
z = torch.randn(16, noise_dim).to("cpu")
# Hasilkan gambar dari noise
fake_images = G(z)
# Jika bentuk output datar (flatten), reshape jadi gambar 28x28
fake_images = fake_images.view(-1, 1, 28, 28)
# Convert dari range [-1, 1] ke [0, 1] supaya bisa ditampilkan
fake_images = (fake_images + 1) / 2
grid = vutils.make_grid(fake_images.cpu(), nrow=4, padding=2, normalize=False)
plt.figure(figsize=(6,6))
plt.imshow(grid.permute(1, 2, 0)) # Convert CHW to HWC
plt.axis('off')
plt.title("Gambar Hasil Generator")
plt.show()
