နားလည်ထားရမယ့် အချက်
Generative adversarial network (GAN) တစ်ခုမှာ network နှစ်ခုကို တစ်ပြိုင်နက် train လုပ်ပါတယ်။ Generator က random noise vector ကို ယူပြီး 'fake' ပုံအဖြစ် ပြောင်းလဲပေးပြီး၊ discriminator ကတော့ training set ထဲက real ပုံနဲ့ generator ရဲ့ fake ပုံကို ခွဲခြားဖို့ ကြိုးစားပါတယ်။ ဒီနှစ်ခုကို minimax game တစ်ခုအနေနဲ့ ယှဉ်ပြိုင် train လုပ်ကြပါတယ် — generator ရဲ့ gradient signal က discriminator ကို ဘယ်လောက်ကောင်းကောင်း လှည့်ဖြားနိုင်လဲဆိုတာကနေ လာပြီး၊ discriminator ရဲ့ signal ကတော့ ခွဲခြားနိုင်စွမ်းကနေ လာပါတယ်။ Iteration တွေကြာလာတာနဲ့အမျှ generator က realistic ပုံပိုမို ထုတ်လုပ်နိုင်လာပြီး discriminator ကလည်း fake ကို ပိုမိုကောင်းစွာ ဖော်ထုတ်နိုင်လာပါတယ်၊ အကောင်းဆုံးအခြေအနေမှာတော့ generator ရဲ့ output က real data နဲ့ ခွဲခြားမရအောင် ကောင်းလာပါတယ်။
လက်တွေ့ scenario နဲ့ ချိတ်ကြည့်မယ်
Tutorial Platform မှာ course thumbnail အဖြစ် upload လုပ်တဲ့ ပုံတွေထဲက ဘယ်ပုံတွေက genuine screenshot/diagram ဖြစ်ပြီး ဘယ်ပုံတွေက AI-generated synthetic ပုံဖြစ်လဲဆိုတာ ခွဲခြားဖို့ policy compliance အတွက် လိုအပ်ပါတယ်။ Trust & Safety team က GAN ရဲ့ discriminator ပုံစံ classifier တစ်ခုကို adversarially train လုပ်ပြီး upload တစ်ခုစီကို 'authentic-looking' score ပေးကာ suspiciously synthetic ပုံများကို manual review queue ထဲပို့ပါတယ် — generator ကိုယ်တိုင်ကတော့ deployment မှာ မလိုအပ်တော့ဘဲ training-time adversary အနေနဲ့သာ အသုံးဝင်ပါတယ်။
အတူတူ စမ်းရေးကြည့်မယ်
import torch
import torch.nn as nn
torch.manual_seed(0)
class Generator(nn.Module):
def __init__(self, noise_dim=16, image_size=32):
super().__init__()
self.image_size = image_size
self.net = nn.Sequential(
nn.Linear(noise_dim, 64),
nn.ReLU(),
nn.Linear(64, 3 * image_size * image_size),
nn.Tanh(), # output pixels squashed to [-1, 1]
)
def forward(self, noise):
out = self.net(noise)
return out.view(-1, 3, self.image_size, self.image_size)
class Discriminator(nn.Module):
def __init__(self, image_size=32):
super().__init__()
self.net = nn.Sequential(
nn.Flatten(),
nn.Linear(3 * image_size * image_size, 64),
nn.ReLU(),
nn.Linear(64, 1),
nn.Sigmoid(), # score in [0, 1]: probability the image is "real"
)
def forward(self, image):
return self.net(image)
generator = Generator()
discriminator = Discriminator()
batch_size = 4
noise = torch.randn(batch_size, 16) # random noise vectors
print("Noise shape:", noise.shape)
fake_images = generator(noise) # noise -> generator -> fake image
print("Fake image batch shape:", fake_images.shape)
scores = discriminator(fake_images) # fake image -> discriminator -> real/fake score
print("Discriminator score shape:", scores.shape)
print("Discriminator scores:", scores.squeeze(1))
Noise shape: torch.Size([4, 16]) ကို print ထုတ်ပါတယ်။ Fake image batch shape: torch.Size([4, 3, 32, 32]) — noise vector လေးခုကနေ RGB ပုံလေးခု ဖန်တီးထားတာကို ပြသပါတယ်။ Discriminator score shape: torch.Size([4, 1]) ပြီးနောက် squeeze လုပ်ထားတဲ့ Discriminator scores: tensor([...]) မှာ 0.0 နဲ့ 1.0 ကြားက float လေးခု ပါဝင်ပါတယ် (Sigmoid output ဖြစ်လို့)။ Model တွေက train မလုပ်ရသေးတဲ့အတွက် ဒီ score တွေက 0.5 ဝန်းကျင်က random-ish value များသာ ဖြစ်နိုင်ပြီး တကယ့် 'realistic' ပုံဖြစ်မဖြစ်ကို ခန့်မှန်းလို့ မရသေးပါဘူး။၅ မိနစ် စမ်းကြည့်
Code ကို ပြင်ပြီး 'real' ပုံအနေနဲ့ torch.rand(batch_size, 3, 32, 32) ကို ဖန်တီးကာ discriminator ကနေ ဖြတ်ပါ (torch.rand ရဲ့ value range က [0,1] ဖြစ်လို့ Generator ရဲ့ Tanh output range [-1,1] နဲ့ ကွာခြားမှုကို သတိပြုပါ)။ Fake images နဲ့ pretend-real images နှစ်မျိုးလုံးရဲ့ discriminator score distribution ကို print ထုတ်ပြီး နှိုင်းယှဉ်ကြည့်ပါ။
သတိလေးတစ်ချက်
Generator ရဲ့ output က Tanh activation ကြောင့် [-1, 1] range ထဲမှာ ရှိပါတယ်၊ ဒါကို image pixel value အဖြစ် disk ပေါ်ထုတ်ပြသခင် [0, 1] သို့မဟုတ် [0, 255] ဆီ rescale လုပ်ဖို့ မေ့ကျန်ရင် ပုံက washed-out ဖြစ်နေရင် ဒါမှမဟုတ် color ပြောင်းပြန်ဖြစ်နေတာ တွေ့ရနိုင်ပါတယ်။
Untrained network နှစ်ခုက discriminator score ကို 0.5 ဝန်းကျင် ပြသတာကို 'generator က discriminator ကို လှည့်ဖြားနေပြီ' လို့ အလွယ်တကူ အနှစ်ချုပ်ချမိတတ်ပါတယ်၊ ဒါပေမယ့် training မစခင် random weight တွေမှာ score ဟာ content ကို ဆန်းစစ်ထားလို့ မဟုတ်ဘဲ near-random score အနေနဲ့သာ ရှိနေတာကို သတိပြုသင့်ပါတယ်။
Wikipedia — Generative adversarial network — Computer Vision