深度生成模型领域的奠基之作 VAE 变分自编码器 — 学习笔记

发布时间:2026/6/28 1:03:30

深度生成模型领域的奠基之作 VAE 变分自编码器 — 学习笔记 VAE 变分自编码器 — 学习笔记本文档是对 vae_tutorial 项目的 PyTorch 改造版 (vae_pytorch) 的学习指南帮助你理解代码结构、调用关系、模型架构以及如何使用。参考论文 Tutorial on Variational Autoencoders (arXiv:1606.05908) — Carl Doersch论文与代码学习仓库地址原论文官方代码仓库VAE 架构encoder-decoder代码跑出来的实验效果手写数字图像生成学习经历原论文《Auto-encoding variational》完全看不懂来自deepseek的安慰AI 推荐了 arXiv 其他解析该论文的论文借助 AI 完成论文与代码的学习。感谢 AI , 让普通修士也能学习最厉害的功法。下面是 AI 总结。 项目文件结构vae_pytorch/ ├── requirements.txt # 依赖包列表 ├── model.py # 三个模型: VAE, CVAE, Regressor ├── utils.py # 工具函数: 图像拼接 (imtile) ├── train_vae.py # VAE 训练脚本 ├── train_cvae.py # CVAE 训练脚本 ├── train_regressor.py # Regressor 训练脚本 ├── VAE学习笔记.md # 本文档 ├── data/ # MNIST 数据集 (自动下载) ├── snapshots/ # 模型检查点 (训练后生成) ├── vae_out.png # VAE 输出 (训练后生成) ├── cvae.png # CVAE 输出 ├── regressor.png # Regressor 输出 └── groundtruth.png # 原始图像对比 VAE 模型架构详解 VAE (标准变分自编码器)┌─────────────────────────────────────┐ │ 输入: MNIST 28x28 │ │ (784维) │ └──────────────┬──────────────────────┘ │ ┌──────────────▼──────────────────────┐ │ encode1: Linear(784→1000) │ │ ReLU │ └──────────────┬──────────────────────┘ │ ┌──────────────▼──────────────────────┐ │ encode2: Linear(1000→500) │ │ ReLU │ └──────────────┬──────────────────────┘ │ ┌──────────────▼──────────────────────┐ │ encode3: Linear(500→250) │ │ (无激活 → pre-ReLU) │ └──────┬───────────────┬──────────────┘ │ │ ┌────────▼────────┐ ┌─────▼────────────┐ │ ReLU (后) │ │ skip ReLU │ │ encode3neuron │ │ (保留负值) │ └────────┬────────┘ └─────┬────────────┘ │ │ ┌────────▼────────┐ ┌─────▼────────────┐ │ mu: Linear( │ │ logvar: Linear( │ │ 250→30) │ │ 250→30) │ │ (均值) │ │ (对数方差) │ └────────┬────────┘ └─────┬────────────┘ │ │ ▼ ▼ ┌──────────────────────────────┐ │ 重参数化: z μ σ·ε │ │ σ exp(0.5·logvar) │ │ ε ~ N(0, I) │ └──────────────┬───────────────┘ │ ┌──────────────▼──────────────────────┐ │ decode4: Linear(30→250) ReLU │ └──────────────┬──────────────────────┘ │ ┌──────────────▼──────────────────────┐ │ decode3: Linear(250→500) ReLU │ └──────────────┬──────────────────────┘ │ ┌──────────────▼──────────────────────┐ │ decode2: Linear(500→1000) ReLU │ └──────────────┬──────────────────────┘ │ ┌──────────────▼──────────────────────┐ │ decode1: Linear(1000→784) Sigmoid│ │ (输出 logits) │ └─────────────────────────────────────┘损失函数L E z ∼ q ( z ∣ x ) [ − log ⁡ p ( x ∣ z ) ] ⏟ 重建损失 (BCE) K L ( q ( z ∣ x ) ∥ p ( z ) ) ⏟ KL 散度 \mathcal{L} \underbrace{\mathbb{E}_{z \sim q(z|x)}[-\log p(x|z)]}_{\text{重建损失 (BCE)}} \underbrace{KL(q(z|x) \| p(z))}_{\text{KL 散度}}L重建损失(BCE)Ez∼q(z∣x)​[−logp(x∣z)]​​KL散度KL(q(z∣x)∥p(z))​​重建损失:BCEWithLogitsLoss— 等价于 Caffe 的SigmoidCrossEntropyLossKL 散度(解析解因为 q 和 p 都是高斯分布):K L ( N ( μ , σ 2 ) ∥ N ( 0 , 1 ) ) − 1 2 ∑ ( 1 log ⁡ σ 2 − μ 2 − σ 2 ) KL(\mathcal{N}(\mu, \sigma^2) \| \mathcal{N}(0, 1)) -\frac{1}{2} \sum(1 \log\sigma^2 - \mu^2 - \sigma^2)KL(N(μ,σ2)∥N(0,1))−21​∑(1logσ2−μ2−σ2)关键细节mu 用 ReLU 后激活(encode3neuron),logvar 用 ReLU 前激活(encode3)原因: log(sd) 需要能输出负值 (当 sd 1 时)返回 logits 而非概率: 数值稳定性更好 CVAE (条件变分自编码器)CVAE 解决的是条件生成问题: 给定中心列像素 → 生成完整图像。数据预处理 (preprocess)原始 28x28 图像 │ ├── data_left [:, :, 0:13] 左13列 (参与编码目标) ├── data_center [:, :, 13:14] 中间1列 (输入条件) └── data_right [:, :, 14:28] 右14列 (参与编码目标)中心列二值化(模拟带噪声的观测):生成均匀噪声 U(0,1)将噪声与像素值逐元素比较像素 噪声 → 1, 像素 噪声 → 0网络结构条件网络: 编码器: 解码器: 28(中心列) 756(左右) 30(z) │ │ │ ▼ ▼ ▼ 1000 → 500 → 250 1000 → 500 250 ( 跳连) │ │ │ 跳连 │ │ │ ▼ ▼ │ └──► encode2sum 500 → 1000 → 756 │ │ │ ▼ 結──────────► 250 → [mu, logvar]跳连 (Skip Connection)的作用:input2(500维)→ 注入编码器的encode2层: 让编码器知道中心列长什么样input4(250维)→ 注入解码器的decode4层: 让解码器知道要生成什么东西 Regressor (确定性回归基线)与 CVAE完全相同的输入和目标但没有隐变量:中心列(28) → 1000 → 500 → 250 → 250 → 500 → 1000 → 756(输出)对比维度CVAERegressor模型类型生成模型判别模型隐变量✅ 有 (30维 z)❌ 无随机性✅ 可生成多样结果❌ 唯一确定输出损失函数BCE KLBCE 仅重建输出多样性✅ 丰富❌ 过于平滑 代码调用关系图train_vae.py train_cvae.py train_regressor.py │ │ │ ├── model.VAE ├── model.CVAE ├── model.Regressor │ │ │ │ │ │ │ ├── encode() │ ├── preprocess() │ ├── preprocess() │ ├── reparameterize() │ ├── conditioning() │ └── forward() │ ├── decode() │ ├── encode() │ └── forward() │ ├── reparameterize() │ │ ├── decode() ├── utils.imtile │ ├── forward() │ │ └── generate_from_center() └── matplotlib.pyplot │ .imsave() ├── utils.imtile │ └── matplotlib.pyplot .imsave()关键调用路径:# VAE 训练 model(x) → encode(x) → reparameterize(mu, logvar) → decode(z) → loss # CVAE 训练 model(images) → preprocess(images) → conditioning(center_binary) → encode(target, cond_all) → reparameterize(mu, logvar) → decode(z, cond_all) → loss # CVAE 推理 preprocess(images) → generate_from_center(center_binary) → conditioning(center_binary) → reparameterize(mu0, logvar0) # 从先验采样 → decode(z, cond_all) → sigmoid(recon) # Regressor 训练 model(images) → preprocess(images) → forward() → BCE loss 运行指南1. 环境准备conda activate vaecd/home/jack/code/VAE/vae_pytorch pipinstall-rrequirements.txt2. 训练模型命令模型大约时间 (GPU)输出文件python train_vae.py标准 VAE~10 分钟vae_out.pngpython train_cvae.py条件 VAE~10 分钟cvae.png,groundtruth.pngpython train_regressor.py回归基线~10 分钟regressor.png,groundtruth.png3. 查看结果训练完成后会生成以下输出图像:vae_out.png— VAE 生成/重建的 100 张 MNIST 图像拼接为 10×10 网格:┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┐ │ 重建│ 重建│ 重建│ 重建│ 重建│ 重建│ 重建│ 重建│ 重建│ 重建│ ├────┼────┼────┼────┼────┼────┼────┼────┼────┼────┤ │ ... │ │ │ │ │ │ │ │ │ │ ├────┼────┼────┼────┼────┼────┼────┼────┼────┼────┤ │ 10行│... │... │... │... │... │... │... │... │... │ └────┴────┴────┴────┴────┴────┴────┴────┴────┴────┘cvae.png / regressor.png— 每张图由三部分并排组成:┌─────────────────────────────────────────────────────┐ │ [重建左13列] [原始右14列(红色高亮)] [重建右13列] │ │ ↑ 对比 CVAE/Regressor 能否准确重建 │ └─────────────────────────────────────────────────────┘ 实验解读观察 1: VAE vs 普通自编码器VAE 的输出通常比普通自编码器更模糊这是因为:KL 散度强制隐变量接近 N(0,1)限制了编码能力噪声采样使得解码器必须学会鲁棒重建观察 2: CVAE vs Regressor同时对比cvae.png和regressor.png:Regressor的结果往往更光滑但缺少细节CVAE的结果细节更丰富但每次运行结果不同 (因为 z 是随机采样的)这体现了 VAE 的生成多样性— 给定相同条件可以产生不同但都合理的输出观察 3: CVAE 中的跳连CVAE 比普通 VAE 生成效果更好因为:跳连直接将中心列信息注入编解码器编码器不需要猜测中心列长什么样解码器直接利用中心列特征生成更精准的细节 进阶练习改变隐变量维度: 将mu/logvar的30改为10或100观察生成质量调整 KL 权重: 乘以 β (β-VAE)观察重建质量和隐空间结构的权衡替换编码器/解码器: 将全连接层改为卷积层观察对生成质量的影响测试时多次采样: 对同一张输入运行多次 CVAE 生成观察输出的多样性 参考文献Tutorial on Variational Autoencoders (arXiv:1606.05908) — Carl Doersch原始 Caffe 实现 — 本项目的原始代码Auto-Encoding Variational Bayes (arXiv:1312.6114) — Kingma Welling (原始 VAE 论文)β-VAE: Learning Basic Visual Concepts with a Constrained Variational Framework — Higgins et al.

相关新闻