大模型教我成为大模型算法工程师之day17: 扩散模型 (Diffusion Models)
摘要:扩散模型(Diffusion Models)是AIGC革命的核心技术,通过模拟物理扩散过程实现高质量图像生成。相比GAN和VAE,它突破了生成领域的"不可能三角",兼具高质量、多样性和训练稳定性。DDPM模型通过前向加噪和逆向去噪过程,以回归任务训练U-Net预测噪声。Stable Diffusion创新性地引入潜在空间(Latent Space),将扩散过程压缩到64x
Day 17: 扩散模型 (Diffusion Models)
摘要:2022年被称为 “AIGC 元年”,Midjourney 和 Stable Diffusion 的横空出世彻底改变了创意产业。而这背后的功臣,就是扩散模型。它不再像 GAN 那样搞“左右互搏”,也不像 VAE 那样搞“生硬压缩”,而是模仿物理热力学中的“扩散”过程,慢慢把一张图毁掉,再学会慢慢把它复原。
1. 为什么需要扩散模型?
在 Diffusion 出现之前,生成领域存在一个“不可能三角”:
- GAN:采样快,质量高,但多样性差(Mode Collapse),训练极难。
- VAE:多样性好,训练稳,但质量差(模糊)。
- Flow:数学推导完美,但计算成本极高。
Diffusion Models 打破了这个诅咒:它生成质量极高(超越 GAN),多样性极好(覆盖整个分布),训练非常稳定(只是慢了一点)。
2. DDPM 原理:从加噪到去噪
DDPM (Denoising Diffusion Probabilistic Models) 的核心思想非常简单:毁掉一幅画很容易,复原它很难,但如果我们把复原过程拆解成 1000 小步,每一步就变得简单了。
2.1 前向过程 (Forward Process) —— 加噪
这是一个固定的过程(不需要训练)。
- 我们将一张清晰图片 x0x_0x0,在 TTT 步(例如 T=1000)内,每一步都加入一点点高斯噪声。
- 最终 xTx_TxT 会变成一张纯粹的标准正态分布噪声。
- 数学特性:由于高斯分布的优良性质,我们可以直接算出任意时刻 ttt 的加噪图片 xtx_txt,而不需要一步步循环算。
2.2 逆向过程 (Reverse Process) —— 去噪
这是一个需要训练的过程。
- 如果能从纯噪声 xTx_TxT 逐步推回 x0x_0x0,我们就学会了生成图片。
- 核心任务:训练一个神经网络(通常是 U-Net),让它根据当前的噪点图 xtx_txt 和时间步 ttt,预测这一步加了多少噪声 ϵ\epsilonϵ。
- 去噪公式:xt−1≈xt−PredictedNoisex_{t-1} \approx x_t - \text{PredictedNoise}xt−1≈xt−PredictedNoise(实际公式包含系数和方差项)。
2.3 训练目标
非常简单!就是让网络预测的噪声 ϵθ(xt,t)\epsilon_\theta(x_t, t)ϵθ(xt,t) 和真实加入的噪声 ϵ\epsilonϵ 越像越好。
Loss=∣∣ϵ−ϵθ(xt,t)∣∣2 Loss = ||\epsilon - \epsilon_\theta(x_t, t)||^2 Loss=∣∣ϵ−ϵθ(xt,t)∣∣2
本质上就是一个回归问题:给你一张带噪图,请算出上面的噪点长什么样。
3. 加速采样:DDIM 与 DPM-Solver
DDPM 的最大缺点是慢。生成一张图需要像倒放录像带一样走完 1000 步。
- DDIM (Denoising Diffusion Implicit Models):
- 发现去噪过程其实不需要严格遵循马尔可夫链。
- 通过改变采样公式,可以跳步走。比如从 1000 步跳到 900 步,再跳到 800 步。
- 结果:只需要 50 步甚至更少就能生成高质量图片,速度提升 20 倍。
- DPM-Solver:
- 把扩散过程看作微分方程(ODE)求解。
- 使用高阶数值求解器,能进一步把步数压缩到 10-20 步。
4. Stable Diffusion:潜在扩散模型 (Latent Diffusion)
虽然 DDIM 变快了,但在像素空间(Pixel Space)上直接跑 Diffusion 还是很贵。一张 512x512 的图有 26万个像素,显存遭不住。
Stable Diffusion (LDM) 的天才之处在于:降维打击。
4.1 核心架构:VAE + U-Net + CLIP
它由三个部分组成:
- VAE (变分自编码器):
- 作用:把巨大的“像素空间”压缩到微小的“潜在空间 (Latent Space)”。
- 例如:把 512x512x3 的图片压缩成 64x64x4 的 Latent 向量。数据量减少了 48 倍!
- 所有的扩散、去噪过程,都在这个 64x64 的小图上进行。
- U-Net (噪声预测器):
- 在 Latent 空间里干活,预测噪声。
- 引入了 Cross-Attention (交叉注意力) 机制,为了听懂提示词。
- CLIP Text Encoder (提示词理解):
- 把用户的 Prompt(如 “A cute cat”)变成向量,通过 Cross-Attention 注入到 U-Net 中。
- 这让 Diffusion 变成了可控生成的 Text-to-Image 模型。
4.2 生成流程
- 用户输入 “A cyberpunk city”。
- CLIP 把它变成 Text Embeddings。
- 随机生成一个 64x64 的纯噪声 Latent。
- U-Net 在 Text Embeddings 的指引下,对 Latent 逐步去噪(比如 50 步)。
- VAE Decoder 把去噪后的 Latent 放大回 512x512 的高清大图。
5. 代码实践:DDPM 核心逻辑
这里展示最核心的训练 Loss 计算(伪代码)。
import torch
import torch.nn as nn
class DDPM(nn.Module):
def __init__(self, unet, timesteps=1000):
super().__init__()
self.unet = unet
self.timesteps = timesteps
# 预计算 alpha, beta 等参数...
def forward(self, x0):
# 1. 随机采样一个时间步 t
t = torch.randint(0, self.timesteps, (x0.shape[0],), device=x0.device)
# 2. 生成随机噪声 epsilon
noise = torch.randn_like(x0)
# 3. 计算加噪后的图片 xt (基于重参数化技巧,直接一步算出)
# xt = sqrt(alpha_bar) * x0 + sqrt(1 - alpha_bar) * noise
xt = self.q_sample(x0, t, noise)
# 4. 让 U-Net 预测噪声
predicted_noise = self.unet(xt, t)
# 5. 计算 Loss (MSE)
loss = nn.functional.mse_loss(predicted_noise, noise)
return loss
def sample(self, n_samples):
# 逆向采样过程
xt = torch.randn(n_samples, c, h, w) # 从纯噪声开始
for t in reversed(range(self.timesteps)):
predicted_noise = self.unet(xt, t)
# xt_prev = (xt - coeff * predicted_noise) / sqrt(alpha) + sigma * z
xt = self.p_sample(xt, t, predicted_noise)
return xt
6. 总结
- DDPM:用慢工出细活的“去噪”思路,换来了生成质量的巅峰。
- DDIM:让扩散模型从“这东西没法用”变成了“稍微等等就能用”。
- Stable Diffusion:通过 Latent Space 和 CLIP 的引入,真正把 AI 绘画带入了寻常百姓家(消费级显卡也能跑)。
思考:为什么 Stable Diffusion 生成手指总是容易画崩?
- 一方面是因为训练数据(Laion-5B)里手部细节往往不清晰或占比太小。
- 另一方面,VAE 的压缩过程是有损的,手部这种高频细节信息可能在压缩到 64x64 时丢失了。
更多推荐

所有评论(0)