生成式模型底层原理通关笔记

📅 2026/7/27 22:25:39
生成式模型底层原理通关笔记
生成式模型底层原理通关笔记引言从数据分布到生成新样本生成式模型的核心目标是从训练数据中学习潜在的概率分布 (p_{\text{data}}(x))然后通过采样生成与训练数据类似的新样本。与判别式模型如分类器不同生成式模型关注的是“数据是如何生成的”。本文将深入剖析几种主流生成式模型如变分自编码器、生成对抗网络和扩散模型的底层原理并通过可运行的代码示例帮助你快速上手。## 变分自编码器VAE原理与实战### 1. 核心思想VAE 通过编码器将输入数据 (x) 映射到隐变量 (z) 的后验分布 (q_\phi(z|x))再通过解码器从 (z) 重构 (x)。其损失函数包含两部分-重构损失衡量生成数据与原始数据的差异如 MSE 或交叉熵。-KL 散度约束后验分布 (q_\phi(z|x)) 接近先验分布 (p(z))通常为标准正态分布。### 2. 重参数化技巧为了反向传播隐变量采样需要可微分(z \mu \sigma \odot \epsilon)其中 (\epsilon \sim \mathcal{N}(0, I))。### 3. 代码示例基于 PyTorch 的 VAEpythonimport torchimport torch.nn as nnimport torch.optim as optimfrom torch.utils.data import DataLoaderfrom torchvision import datasets, transforms# 定义 VAE 模型class VAE(nn.Module): def __init__(self, input_dim784, hidden_dim256, latent_dim20): super(VAE, self).__init__() # 编码器 self.encoder nn.Sequential( nn.Linear(input_dim, hidden_dim), nn.ReLU(), nn.Linear(hidden_dim, hidden_dim), nn.ReLU(), ) self.fc_mu nn.Linear(hidden_dim, latent_dim) # 均值 self.fc_logvar nn.Linear(hidden_dim, latent_dim) # 对数方差 # 解码器 self.decoder nn.Sequential( nn.Linear(latent_dim, hidden_dim), nn.ReLU(), nn.Linear(hidden_dim, hidden_dim), nn.ReLU(), nn.Linear(hidden_dim, input_dim), nn.Sigmoid() # 输出概率值0-1 ) def encode(self, x): h self.encoder(x.view(x.size(0), -1)) mu self.fc_mu(h) logvar self.fc_logvar(h) return mu, logvar def reparameterize(self, mu, logvar): std torch.exp(0.5 * logvar) eps torch.randn_like(std) # 标准正态噪声 return mu eps * std def decode(self, z): return self.decoder(z) def forward(self, x): mu, logvar self.encode(x) z self.reparameterize(mu, logvar) recon_x self.decode(z) return recon_x, mu, logvar# 损失函数重构损失 KL 散度def vae_loss(recon_x, x, mu, logvar): # 二值交叉熵损失适用于 MNIST 像素值 0/1 recon_loss nn.functional.binary_cross_entropy(recon_x, x.view(-1, 784), reductionsum) # KL 散度D_KL(N(mu, sigma^2) || N(0, 1)) kl_loss -0.5 * torch.sum(1 logvar - mu.pow(2) - logvar.exp()) return recon_loss kl_loss# 训练代码简化版def train_vae(model, dataloader, epochs10): optimizer optim.Adam(model.parameters(), lr1e-3) for epoch in range(epochs): for batch_idx, (data, _) in enumerate(dataloader): optimizer.zero_grad() recon_batch, mu, logvar model(data) loss vae_loss(recon_batch, data, mu, logvar) loss.backward() optimizer.step() print(fEpoch {epoch}: Loss {loss.item():.2f})# 示例运行需先下载 MNIST 数据集if __name__ __main__: transform transforms.Compose([transforms.ToTensor()]) mnist datasets.MNIST(./data, trainTrue, downloadTrue, transformtransform) loader DataLoader(mnist, batch_size64, shuffleTrue) vae VAE() train_vae(vae, loader)注释上述代码实现了完整的 VAE 训练流程。重参数化技巧通过reparameterize方法实现确保梯度可以流经随机采样层。训练后可通过解码随机采样的 (z \sim \mathcal{N}(0, I)) 生成新图像。—## 生成对抗网络GAN原理与实战### 1. 核心思想GAN 包含生成器 (G) 和判别器 (D) 两个网络-生成器将随机噪声 (z) 映射到数据空间尝试欺骗判别器。-判别器区分真实样本和生成样本。-极小极大博弈(\min_G \max_D V(D,G) \mathbb{E}{x \sim p{\text{data}}}[\log D(x)] \mathbb{E}{z \sim p_z}[\log(1-D(G(z)))])### 2. 训练技巧- 交替更新先训练判别器 (k) 步再训练生成器 1 步。- 使用标签平滑或梯度惩罚WGAN-GP防止模式坍塌。### 3. 代码示例简易 GAN基于 MNISTpythonimport torchimport torch.nn as nnimport torch.optim as optimfrom torch.utils.data import DataLoaderfrom torchvision import datasets, transforms# 生成器从 100 维噪声生成 784 维图像class Generator(nn.Module): def __init__(self, noise_dim100, hidden_dim256): super(Generator, self).__init__() self.model nn.Sequential( nn.Linear(noise_dim, hidden_dim), nn.ReLU(), nn.Linear(hidden_dim, hidden_dim * 2), nn.ReLU(), nn.Linear(hidden_dim * 2, 784), nn.Tanh() # 输出范围 [-1, 1] ) def forward(self, z): return self.model(z)# 判别器区分真实/伪造图像class Discriminator(nn.Module): def __init__(self, input_dim784, hidden_dim256): super(Discriminator, self).__init__() self.model nn.Sequential( nn.Linear(input_dim, hidden_dim), nn.LeakyReLU(0.2), # 避免死亡 ReLU nn.Linear(hidden_dim, hidden_dim // 2), nn.LeakyReLU(0.2), nn.Linear(hidden_dim // 2, 1), nn.Sigmoid() ) def forward(self, x): return self.model(x.view(x.size(0), -1))# 训练函数def train_gan(generator, discriminator, dataloader, epochs50, noise_dim100): g_optim optim.Adam(generator.parameters(), lr2e-4, betas(0.5, 0.999)) d_optim optim.Adam(discriminator.parameters(), lr2e-4, betas(0.5, 0.999)) criterion nn.BCELoss() # 二值交叉熵 for epoch in range(epochs): for real_imgs, _ in dataloader: batch_size real_imgs.size(0) real_labels torch.ones(batch_size, 1) # 真实标签为 1 fake_labels torch.zeros(batch_size, 1) # 伪造标签为 0 # 训练判别器最大化 log(D(real)) log(1-D(fake)) d_optim.zero_grad() real_pred discriminator(real_imgs) d_real_loss criterion(real_pred, real_labels) noise torch.randn(batch_size, noise_dim) fake_imgs generator(noise) fake_pred discriminator(fake_imgs.detach()) # 阻止梯度流入生成器 d_fake_loss criterion(fake_pred, fake_labels) d_loss d_real_loss d_fake_loss d_loss.backward() d_optim.step() # 训练生成器最小化 log(1-D(fake)) 等价于最大化 log(D(fake)) g_optim.zero_grad() noise torch.randn(batch_size, noise_dim) fake_imgs generator(noise) fake_pred discriminator(fake_imgs) g_loss criterion(fake_pred, real_labels) # 让判别器误认为伪造样本为真 g_loss.backward() g_optim.step() print(fEpoch {epoch}: D Loss {d_loss.item():.4f}, G Loss {g_loss.item():.4f})# 示例运行需先下载 MNIST 数据集if __name__ __main__: transform transforms.Compose([transforms.ToTensor(), transforms.Normalize([0.5], [0.5])]) mnist datasets.MNIST(./data, trainTrue, downloadTrue, transformtransform) loader DataLoader(mnist, batch_size64, shuffleTrue) gen Generator() disc Discriminator() train_gan(gen, disc, loader)注释此代码实现了标准 GAN 训练。注意生成器使用Tanh输出与数据归一化到[-1,1]匹配。判别器使用LeakyReLU防止梯度消失。训练后通过gen(torch.randn(1, 100))即可生成新图像。—## 扩散模型Diffusion Model原理简介### 1. 前向扩散过程逐步向数据添加高斯噪声直到变成纯噪声(q(x_t | x{t-1}) \mathcal{N}(x_t; \sqrt{1-\beta_t} x_{t-1}, \beta_t I))。### 2. 反向去噪过程学习神经网络 (\epsilon_\theta(x_t, t)) 预测添加的噪声然后逐步去噪(x_{t-1} \frac{1}{\sqrt{\alpha_t}} \left( x_t - \frac{\beta_t}{\sqrt{1-\bar{\alpha}t}} \epsilon\theta(x_t, t) \right))。### 3. 训练目标最小化预测噪声与真实噪声的 MSE(\mathbb{E}{t, x_0, \epsilon} \left[ | \epsilon - \epsilon\theta(x_t, t) |^2 \right])。### 4. 代码片段噪声预测网络简化版pythonclass DiffusionModel(nn.Module): def __init__(self, T1000): super().__init__() # 定义噪声调度表beta 从 1e-4 到 0.02 线性增加 self.betas torch.linspace(1e-4, 0.02, T) self.alphas 1 - self.betas self.alpha_bars torch.cumprod(self.alphas, dim0) self.T T # 简单的 U-Net 结构此处省略复杂实现 self.net nn.Sequential( nn.Linear(784 1, 256), # 输入图像 时间步 t nn.ReLU(), nn.Linear(256, 256), nn.ReLU(), nn.Linear(256, 784) ) def forward(self, x_t, t): # 将时间步 t 归一化到 [0,1] t_embed t / self.T # 拼接图像和时间嵌入 x torch.cat([x_t, t_embed.unsqueeze(1).expand(-1, 784)], dim1) return self.net(x) def sample(self, n1): # 从纯噪声开始反向去噪 x torch.randn(n, 784) for t in reversed(range(self.T)): t_tensor torch.full((n,), t, dtypetorch.float) eps_pred self.net(x, t_tensor) # 简化去噪公式实际需考虑方差调度 x (x - self.betas[t] / torch.sqrt(1 - self.alpha_bars[t]) * eps_pred) / torch.sqrt(self.alphas[t]) return x注释此代码仅展示扩散模型的核心思想。实际实现需使用 U-Net 等复杂结构并包含方差调度。扩散模型通过迭代去噪生成高质量样本是目前最先进的生成模型之一如 DALL-E 2、Stable Diffusion。—## 总结本文从基础原理出发通过代码示例演示了三种主流生成式模型的实现-VAE通过隐变量和变分推断生成多样化样本适合连续数据。-GAN通过对抗训练生成逼真样本训练需平衡生成器和判别器。-扩散模型通过逐步去噪生成高保真样本计算成本较高但效果最佳。实战要点- VAE 的 KL 散度需与重构损失平衡避免后验坍塌。- GAN 训练需注意模式坍塌可使用 WGAN-GP 或标签平滑改进。- 扩散模型的高质量生成依赖于噪声调度设计和大量采样步骤。生成式模型的核心在于对数据分布的建模与采样。理解这些底层原理后你可以灵活应用于图像生成、文本生成、药物分子设计等领域。建议读者运行代码并调整超参数观察生成样本的变化深入体会模型的工作原理。