Ainsteinx Logo
Ainsteinx
👤
ຍິນດີຕ້ອນຮັບສູ່ Ainsteinx
ເຂົ້າສູ່ລະບົບ

ປ່ຽນພາສາ

ສະກຸນເງິນ

ໜ້າທຳອິດ
ບົດຄວາມ
ບໍລິການ
ບົດ 03 · 6 ເທັກນິກຫຼັກ

Variational Autoencoder (VAE)

ບີບຮູບເປັນຈຸດໃນ latent space ແລ້ວແຕ້ມຮູບໃໝ່ຈາກຈຸດສຸ່ມ.

Autoencoder ມີ encoder ບີບຮູບເປັນ vector ນ້ອຍ (latent) ແລະ decoder ສ້າງຮູບຄືນ. ແຕ່ latent space ຂອງມັນມີຊ່ອງຫວ່າງ ຈຶ່ງສຸ່ມຮູບໃໝ່ໄດ້ບໍ່ດີ.

VAE ແກ້ໂດຍໃຫ້ encoder ອອກເປັນການກະຈາຍ (μ, σ) ແລະ ໃຊ້ KL divergence ດຶງໃຫ້ໃກ້ N(0, I). ຫຼັງຝຶກ ພຽງສຸ່ມ z ຈາກ N(0, I) ແລ້ວ decode ກໍໄດ້ຮູບໃໝ່. ໂຄດຕົວຢ່າງແຕ້ມຕົວເລກ 8×8 ອອກມາເປັນຕົວອັກສອນ.

z = μ + σ · ε, ε ~ N(0, I) ← reparameterization trick loss = reconstruction(x, x̂) + β · KL( N(μ, σ²) ‖ N(0, I) ) KL = −½ Σ (1 + log σ² − μ² − σ²)
Reconstruction lossໃຫ້ຮູບທີ່ສ້າງຄືນ ຄ້າຍກັບຮູບຕົ້ນສະບັບ
KL lossໃຫ້ latent space ຕໍ່ເນື່ອງ ບໍ່ມີຮູ ຈຶ່ງສຸ່ມໄດ້

ສິ່ງທີ່ຄວນຈື່

  • VAE = autoencoder + ຄວາມສຸ່ມ + KL
  • ຄິດໄລ່ vector ໃນ latent space ໄດ້ ເຊັ່ນ ໃບໜ້າ + "ແວ່ນຕາ" = ໃບໜ້າໃສ່ແວ່ນ
generative-ai-ep03-vae.py
import torch, torch.nn as nn
from sklearn.datasets import load_digits

torch.manual_seed(0)
X = torch.tensor(load_digits().data / 16.0, dtype=torch.float32)   # 8x8 digits

class VAE(nn.Module):
    def __init__(self, z=2):
        super().__init__()
        self.enc = nn.Sequential(nn.Linear(64, 128), nn.ReLU(), nn.Linear(128, 2 * z))
        self.dec = nn.Sequential(nn.Linear(z, 128), nn.ReLU(), nn.Linear(128, 64), nn.Sigmoid())

    def forward(self, x):
        mu, logvar = self.enc(x).chunk(2, dim=1)
        z = mu + torch.randn_like(mu) * torch.exp(0.5 * logvar)    # reparameterization trick
        return self.dec(z), mu, logvar

vae = VAE()
opt = torch.optim.Adam(vae.parameters(), lr=1e-3)
for epoch in range(200):
    recon, mu, logvar = vae(X)
    rec = nn.functional.binary_cross_entropy(recon, X, reduction="sum") / len(X)
    kl = -0.5 * torch.sum(1 + logvar - mu ** 2 - logvar.exp()) / len(X)
    loss = rec + kl
    opt.zero_grad(); loss.backward(); opt.step()
    if epoch % 50 == 49:
        print(f"epoch {epoch + 1}  reconstruction {rec.item():.1f}  KL {kl.item():.2f}")

# Generate: decode random points from N(0, I)
with torch.no_grad():
    sample = vae.dec(torch.randn(1, 2)).view(8, 8)
for row in sample:
    print("".join(" .:-=+*#%@"[int(v * 9.99)] for v in row))

ຜົນລັບ

epoch 50  reconstruction 29.1  KL 1.31
epoch 100  reconstruction 27.7  KL 0.97
epoch 150  reconstruction 26.7  KL 1.09
epoch 200  reconstruction 25.5  KL 1.42
..=%#+..
 :%*+#:.
.:#:-#..
..+=+#: 
 .: :#:.
  .  *-.
  +-=#-.
..-%%+..
  • #GenerativeAI
  • #DeepLearning
  • #PythonສຳລັບຄົນLaos
  • #AI
  • #ບອກຕໍ່ຄວາມຮູ້