النماذج التوليدية: VAE وGAN
“تعلّم شكل البيانات — ثم أخذ عينات من واقع جديد من التوزيع المتعلَّم”
من الترميز التلقائي إلى VAE (ELBO وحيلة إعادة المعاملات) إلى GAN (التدريب التنافسي وDCGAN وحلول انهيار النمط).
المتطلبات الأساسية
المفاهيم المغطاة
∑الصيغ الرئيسية
ELBO (VAE)
مصطلح إعادة البناء − تباين KL (يُنظِّم الفضاء الكامن) — الهدف المُعظَّم في تدريب VAE
إعادة المعاملة
يسمح للتدرجات بالتدفق عبر عملية أخذ العينات — الحيلة الضرورية للانتشار الخلفي في VAEs
هدف GAN
يُخدِع المولِّد المُمييِّز؛ يكشف المُمييِّز المزيفات — لعبة minimax تعارضية
▶محاكاة تفاعلية
⬡هندسة النموذج
من التصنيف إلى التوليد
جميع النماذج السابقة تمييزية: P(y|x). النماذج التوليدية تتعلم P(x) — التوزيع الكامل للبيانات. بمجرد تعلم التوزيع، يمكنك أخذ عينات من نقاط جديدة، والاستيفاء بين الأمثلة، وكشف الشذوذات. هكذا يعمل Stable Diffusion وGPT وDALL-E في جوهرها.
VAE: الضغط الاحتمالي
تضغط المشفرات التلقائية البيانات إلى رمز كامن ثم تعيد بناءها. لكن الفضاء الكامن منفصل — الصور المتشابهة ليست قريبة من بعضها. تُصلح VAEs هذا بترميز التوزيعات (μ، σ) بدلاً من النقاط، وتعاقب الانحراف عن N(0,I) عبر تباين KL. هذا يُجبر على فضاء كامن سلس ومستمر.
خدعة إعادة التحديد z = μ + σ⊙ε هي الفكرة الأساسية التي تجعل تدريب VAE ممكناً. بدونها، أخذ العينات عملية غير قابلة للتفاضل — لا يمكن تدفق أي تدرجات.
ELBO: الحد الأدنى لأدلة البيانات
نريد تعظيم log p(x). هذا غير قابل للحساب مباشرةً. بدلاً من ذلك، نُعظّم ELBO: جودة إعادة البناء (كم نُفكك جيداً) ناقص تباين KL من التوزيع المسبق. تُضيف β-VAE وزناً β لمصطلح KL للتمثيلات المفككة.
تدريب GAN: اللعبة العدائية
المولد G يأخذ ضوضاء z ~ N(0,I) ويُنتج عينات مزيفة G(z). المميّز D يحاول التمييز بين العينات الحقيقية والمزيفة. يلعبان لعبة minimax: D يُعظّم log D(حقيقي) + log(1 - D(G(z)))؛ G يُصغّر log(1 - D(G(z))). عند توازن Nash، يُنتج G عينات لا تُميَّز عن البيانات الحقيقية.
انهيار الأنماط: يجد المولد نقطة واحدة (أو قليلاً) تخدع المميّز دائماً. الحل: Wasserstein GAN (WGAN-GP) مع غرامة التدرج، أو التطبيع الطيفي.
تنفيذ DCGAN
import torch import torch.nn as nn class Generator(nn.Module): def __init__(self, latent_dim=class="tok-num">100, img_channels=class="tok-num">3): super().__init__() self.net = nn.Sequential( class="tok-comment"># Project and reshape noise nn.Linear(latent_dim, class="tok-num">512 * class="tok-num">4 * class="tok-num">4), nn.Unflatten(class="tok-num">1, (class="tok-num">512, class="tok-num">4, class="tok-num">4)), class="tok-comment"># Upsample blocks *self._block(class="tok-num">512, class="tok-num">256), *self._block(class="tok-num">256, class="tok-num">128), *self._block(class="tok-num">128, class="tok-num">64), *self._block(class="tok-num">64, class="tok-num">32), nn.ConvTranspose2d(class="tok-num">32, img_channels, class="tok-num">4, class="tok-num">2, class="tok-num">1), nn.Tanh() ) def _block(self, in_c, out_c): return [nn.ConvTranspose2d(in_c, out_c, class="tok-num">4, class="tok-num">2, class="tok-num">1, bias=False), nn.BatchNorm2d(out_c), nn.ReLU(True)] def forward(self, z): return self.net(z) class="tok-comment"># WGAN-GP training (more stable than vanilla GAN) def gradient_penalty(D, real, fake, device): alpha = torch.rand(real.size(class="tok-num">0), class="tok-num">1, class="tok-num">1, class="tok-num">1).to(device) interpolated = alpha * real + (class="tok-num">1 - alpha) * fake interpolated.requires_grad_(True) d_interp = D(interpolated) gradients = torch.autograd.grad(d_interp, interpolated, grad_outputs=torch.ones_like(d_interp), create_graph=True)[class="tok-num">0] return ((gradients.norm(class="tok-num">2, dim=class="tok-num">1) - class="tok-num">1) ** class="tok-num">2).mean()
?اختبار المعرفة
يتم حفظ التقدم في متصفحك — لا حاجة لحساب.