TL;DR
扩散模型(Diffusion Model)是当前最先进的图像生成技术,通过学习逐步去噪的过程来生成高质量图像。本指南深入讲解扩散模型的核心思想、前向扩散(加噪)与反向去噪过程、DDPM和DDIM算法原理、Stable Diffusion架构解析,并对比GAN和VAE的优劣。同时涵盖文生图、图生图、Inpainting等实际应用,提供Diffusers库的代码示例。
引言
2022年,Stable Diffusion的开源发布引爆了AI图像生成领域,让每个人都能在消费级显卡上生成令人惊叹的图像。扩散模型凭借其出色的生成质量和训练稳定性,已经超越GAN成为图像生成的主流技术。
在本指南中,你将学到:
- 扩散模型的核心思想:为什么"加噪再去噪"能生成图像
- 前向扩散过程的数学原理
- 反向去噪过程如何学习生成
- DDPM与DDIM算法的区别与联系
- Stable Diffusion的完整架构解析
- 扩散模型与GAN、VAE的对比
- 文生图、图生图、Inpainting的实现原理
- 使用Diffusers库的实战代码
什么是扩散模型
扩散模型是一类基于概率的生成模型,其核心思想来源于非平衡热力学:通过定义一个逐步添加噪声的前向过程,然后学习逆转这个过程来生成数据。
核心直觉
想象你有一张清晰的照片,不断往上面撒沙子(添加噪声),最终照片会完全被沙子覆盖,变成一堆随机的沙粒。扩散模型的训练目标就是学会"扫沙子"——给定任意程度的噪声图像,预测并去除噪声,逐步恢复原始图像。
一旦模型学会了去噪,生成新图像就变得简单:从纯随机噪声开始,反复应用去噪过程,最终得到一张全新的、从未见过的图像。
前向扩散过程
前向扩散过程是一个固定的马尔可夫链,逐步向数据添加高斯噪声。
数学定义
给定原始数据 x₀,前向过程定义为一个高斯分布:
q(x_t | x_{t-1}) = N(x_t; √(1-β_t) * x_{t-1}, β_t * I)
其中 β_t 是预定义的噪声调度(noise schedule),控制每一步添加多少噪声。
噪声调度策略
关键性质:一步加噪
扩散模型的一个重要性质是可以直接从 x₀ 计算任意时刻 x_t:
q(x_t | x_0) = N(x_t; √(ᾱ_t) * x_0, (1-ᾱ_t) * I)
其中 ᾱ_t = ∏(1-β_s),是累积噪声系数。
这意味着训练时不需要逐步加噪,可以直接采样任意时刻的噪声图像:
def forward_diffusion(x0, t, noise_schedule):
alpha_bar = noise_schedule.alpha_bar[t]
noise = torch.randn_like(x0)
xt = torch.sqrt(alpha_bar) * x0 + torch.sqrt(1 - alpha_bar) * noise
return xt, noise
反向去噪过程
反向过程是扩散模型的核心,通过神经网络学习从噪声恢复数据。
去噪网络
反向过程同样是一个马尔可夫链,但转移概率需要学习:
p_θ(x_{t-1} | x_t) = N(x_{t-1}; μ_θ(x_t, t), Σ_θ(x_t, t))
神经网络 ε_θ 被训练来预测添加的噪声,然后通过以下公式计算均值:
μ_θ(x_t, t) = (1/√α_t) * (x_t - (β_t/√(1-ᾱ_t)) * ε_θ(x_t, t))
训练目标
扩散模型的训练目标简洁优雅——最小化预测噪声与真实噪声的均方误差:
L = E[||ε - ε_θ(x_t, t)||²]
即预测噪声与真实噪声的 MSE 损失。
def training_step(model, x0, noise_schedule):
t = torch.randint(0, T, (batch_size,))
noise = torch.randn_like(x0)
xt = forward_diffusion(x0, t, noise_schedule)
predicted_noise = model(xt, t)
loss = F.mse_loss(predicted_noise, noise)
return loss
采样过程
DDPM算法详解
DDPM(Denoising Diffusion Probabilistic Models)是2020年提出的开创性工作,奠定了现代扩散模型的基础。
DDPM采样算法
@torch.no_grad()
def ddpm_sample(model, shape, noise_schedule, device):
x = torch.randn(shape, device=device)
for t in reversed(range(noise_schedule.T)):
t_tensor = torch.full((shape[0],), t, device=device)
predicted_noise = model(x, t_tensor)
alpha = noise_schedule.alpha[t]
alpha_bar = noise_schedule.alpha_bar[t]
beta = noise_schedule.beta[t]
mean = (1 / torch.sqrt(alpha)) * (
x - (beta / torch.sqrt(1 - alpha_bar)) * predicted_noise
)
if t > 0:
noise = torch.randn_like(x)
sigma = torch.sqrt(beta)
x = mean + sigma * noise
else:
x = mean
return x
DDPM的局限性
DDPM虽然生成质量优秀,但采样速度慢是其主要缺点:
- 需要1000步迭代才能生成一张图像
- 每一步都需要完整的神经网络前向传播
- 生成一张512×512图像可能需要数十秒
DDIM算法详解
DDIM(Denoising Diffusion Implicit Models)通过重新推导采样过程,实现了加速采样。
DDIM的核心改进
DDIM发现反向过程不必是马尔可夫的,可以定义一个确定性的采样过程:
x_{t-1} = √(ᾱ_{t-1}) * ((x_t - √(1-ᾱ_t) * ε_θ(x_t,t)) / √(ᾱ_t)) + √(1-ᾱ_{t-1}) * ε_θ(x_t,t)
DDIM采样算法
@torch.no_grad()
def ddim_sample(model, shape, noise_schedule, device, steps=50, eta=0.0):
x = torch.randn(shape, device=device)
timesteps = torch.linspace(noise_schedule.T - 1, 0, steps).long()
for i, t in enumerate(timesteps):
t_tensor = torch.full((shape[0],), t, device=device)
predicted_noise = model(x, t_tensor)
alpha_bar_t = noise_schedule.alpha_bar[t]
alpha_bar_prev = noise_schedule.alpha_bar[timesteps[i + 1]] if i < len(timesteps) - 1 else 1.0
x0_pred = (x - torch.sqrt(1 - alpha_bar_t) * predicted_noise) / torch.sqrt(alpha_bar_t)
sigma = eta * torch.sqrt((1 - alpha_bar_prev) / (1 - alpha_bar_t)) * torch.sqrt(1 - alpha_bar_t / alpha_bar_prev)
dir_xt = torch.sqrt(1 - alpha_bar_prev - sigma ** 2) * predicted_noise
noise = torch.randn_like(x) if i < len(timesteps) - 1 else 0
x = torch.sqrt(alpha_bar_prev) * x0_pred + dir_xt + sigma * noise
return x
DDPM vs DDIM对比
| 特性 | DDPM | DDIM |
|---|---|---|
| 采样步数 | 1000步 | 10-50步 |
| 采样速度 | 慢 | 快10-100倍 |
| 随机性 | 随机采样 | 可确定性采样 |
| 生成质量 | 优秀 | 接近DDPM |
| 插值能力 | 困难 | 支持潜在空间插值 |
Stable Diffusion架构解析
Stable Diffusion是目前最流行的开源扩散模型,其架构设计极具创新性。
整体架构
潜在空间扩散
Stable Diffusion的关键创新是在潜在空间而非像素空间进行扩散:
- VAE编码器:将512×512图像压缩到64×64的潜在空间
- 潜在扩散:在压缩后的空间进行扩散过程
- VAE解码器:将去噪后的潜在向量解码回图像
这种设计将计算量减少了约64倍,使得在消费级GPU上运行成为可能。
U-Net结构
class UNetBlock(nn.Module):
def __init__(self, in_channels, out_channels, time_emb_dim, context_dim):
super().__init__()
self.conv1 = nn.Conv2d(in_channels, out_channels, 3, padding=1)
self.conv2 = nn.Conv2d(out_channels, out_channels, 3, padding=1)
self.time_mlp = nn.Linear(time_emb_dim, out_channels)
self.cross_attn = CrossAttention(out_channels, context_dim)
self.self_attn = SelfAttention(out_channels)
def forward(self, x, t_emb, context):
h = self.conv1(x)
h = h + self.time_mlp(t_emb)[:, :, None, None]
h = self.self_attn(h)
h = self.cross_attn(h, context)
h = self.conv2(h)
return h
条件生成机制
Stable Diffusion通过Cross Attention实现文本条件控制:
- CLIP编码:将文本转换为77×768的嵌入序列
- Cross Attention:U-Net的每一层都与文本嵌入进行交叉注意力
- Classifier-Free Guidance:同时预测有条件和无条件的噪声,增强控制效果
def classifier_free_guidance(model, x, t, text_emb, guidance_scale=7.5):
uncond_emb = model.get_unconditional_embedding()
noise_uncond = model(x, t, uncond_emb)
noise_cond = model(x, t, text_emb)
noise_pred = noise_uncond + guidance_scale * (noise_cond - noise_uncond)
return noise_pred
扩散模型 vs GAN vs VAE
三种生成模型对比
详细对比表
| 特性 | GAN | VAE | 扩散模型 |
|---|---|---|---|
| 生成质量 | 高 | 中等 | 最高 |
| 训练稳定性 | 低 | 高 | 高 |
| 采样速度 | 快(单次前向) | 快(单次前向) | 慢(多步迭代) |
| 模式覆盖 | 可能模式崩溃 | 完整覆盖 | 完整覆盖 |
| 似然估计 | 无法计算 | 可计算下界 | 可计算 |
| 条件生成 | 需要额外设计 | 自然支持 | 自然支持 |
| 插值能力 | 有限 | 优秀 | 优秀 |
选择建议
- 追求实时生成:选择GAN(如StyleGAN)
- 需要潜在空间操作:选择VAE
- 追求最高质量:选择扩散模型
- 综合考虑:Stable Diffusion(VAE + 扩散模型)
应用场景
文生图(Text-to-Image)
文生图是扩散模型最广泛的应用:
from diffusers import StableDiffusionPipeline
pipe = StableDiffusionPipeline.from_pretrained(
"stabilityai/stable-diffusion-2-1",
torch_dtype=torch.float16
).to("cuda")
prompt = "a beautiful sunset over mountains, digital art, highly detailed"
image = pipe(prompt, num_inference_steps=50, guidance_scale=7.5).images[0]
image.save("sunset.png")
图生图(Image-to-Image)
基于参考图像生成新图像:
from diffusers import StableDiffusionImg2ImgPipeline
from PIL import Image
pipe = StableDiffusionImg2ImgPipeline.from_pretrained(
"stabilityai/stable-diffusion-2-1",
torch_dtype=torch.float16
).to("cuda")
init_image = Image.open("input.png").convert("RGB")
prompt = "a fantasy castle, oil painting style"
image = pipe(
prompt=prompt,
image=init_image,
strength=0.75,
guidance_scale=7.5
).images[0]
图像修复(Inpainting)
修复或替换图像的指定区域:
from diffusers import StableDiffusionInpaintPipeline
pipe = StableDiffusionInpaintPipeline.from_pretrained(
"stabilityai/stable-diffusion-2-inpainting",
torch_dtype=torch.float16
).to("cuda")
image = Image.open("image.png")
mask = Image.open("mask.png")
result = pipe(
prompt="a cute cat sitting",
image=image,
mask_image=mask,
num_inference_steps=50
).images[0]
ControlNet条件控制
使用边缘、姿态等额外条件精确控制生成:
from diffusers import StableDiffusionControlNetPipeline, ControlNetModel
controlnet = ControlNetModel.from_pretrained(
"lllyasviel/control_v11p_sd15_canny",
torch_dtype=torch.float16
)
pipe = StableDiffusionControlNetPipeline.from_pretrained(
"runwayml/stable-diffusion-v1-5",
controlnet=controlnet,
torch_dtype=torch.float16
).to("cuda")
canny_image = get_canny_edges(input_image)
result = pipe(prompt, image=canny_image).images[0]
实践指南
环境配置
pip install diffusers transformers accelerate torch
pip install xformers # 可选,用于内存优化
内存优化技巧
pipe.enable_attention_slicing()
pipe.enable_vae_slicing()
pipe.enable_model_cpu_offload()
pipe.enable_xformers_memory_efficient_attention()
生成质量优化
- 提示词工程:使用详细、具体的描述
- 负面提示词:排除不想要的元素
- 调整guidance_scale:通常7-12效果较好
- 增加采样步数:更多步数通常质量更好
result = pipe(
prompt="masterpiece, best quality, detailed face, " + user_prompt,
negative_prompt="low quality, blurry, distorted, deformed",
num_inference_steps=50,
guidance_scale=7.5,
width=768,
height=768
).images[0]
工具推荐
在使用扩散模型进行AI图像生成时,以下工具可以提升工作效率:
- JSON格式化工具 - 格式化模型配置和API响应数据
- Base64编解码 - 处理图像数据的编码转换
- 文本对比工具 - 比较不同提示词的效果
- PNG转JPG - 转换生成图像的格式
- 图像压缩工具 - 优化生成图像的文件大小
总结
扩散模型的核心要点:
- 核心思想:通过学习逆转噪声添加过程来生成数据,"加噪再去噪"的优雅设计
- 前向过程:固定的马尔可夫链,逐步添加高斯噪声直到数据变成纯噪声
- 反向过程:神经网络学习预测噪声,逐步去噪恢复数据
- DDPM vs DDIM:DDPM质量优秀但慢,DDIM通过确定性采样加速10-100倍
- Stable Diffusion:在潜在空间扩散,结合VAE和Cross Attention实现高效文生图
- 对比优势:相比GAN训练更稳定,相比VAE生成质量更高
- 丰富应用:文生图、图生图、Inpainting、ControlNet等多种应用场景
扩散模型代表了生成式AI的重要突破,理解其原理对于掌握AI图像生成技术至关重要。
常见问题
扩散模型为什么能生成高质量图像?
扩散模型的高质量源于其训练目标的简洁性和稳定性。与GAN的对抗训练不同,扩散模型只需要学习预测噪声这一简单任务,避免了模式崩溃问题。同时,多步去噪过程允许模型逐步细化图像细节,每一步都在改进生成质量。此外,扩散模型能够完整覆盖数据分布,不会遗漏某些模式。
DDPM和DDIM应该选择哪个?
这取决于你的需求。如果追求最高生成质量且时间充裕,选择DDPM(1000步)。如果需要快速生成或实时应用,选择DDIM(20-50步),质量损失很小。DDIM还支持确定性采样,相同的噪声输入会产生相同的输出,这在某些应用场景(如图像编辑)中很有用。实际使用中,DDIM 50步通常是质量和速度的最佳平衡点。
Stable Diffusion需要什么样的硬件配置?
基础运行需要至少8GB显存的GPU(如RTX 3060)。推荐配置是12GB以上显存(如RTX 3080/4070)以获得更好体验。通过启用半精度(float16)、attention slicing、VAE slicing等优化,6GB显存也可以运行。CPU运行也可行但速度很慢,生成一张图可能需要几分钟。Apple Silicon Mac可以使用MPS后端,M1/M2芯片性能可接受。
如何提升扩散模型的生成效果?
提升效果的关键技巧包括:1)编写详细具体的提示词,包含风格、质量、细节描述;2)使用负面提示词排除不想要的元素;3)调整guidance_scale,通常7-12效果较好;4)增加采样步数到50-100步;5)使用高质量的基础模型或微调模型;6)尝试不同的采样器(如DPM++ 2M Karras);7)使用ControlNet等条件控制技术精确引导生成。
扩散模型的训练成本高吗?
训练成本取决于模型规模和数据量。从头训练Stable Diffusion级别的模型需要数千GPU小时,成本可达数十万美元。但微调(fine-tuning)成本低得多:LoRA微调只需要几小时和几GB显存;DreamBooth个性化训练也只需要20-30张图片和几小时训练时间。对于大多数应用,使用预训练模型+微调是最经济的选择。
扩散模型生成的图像有版权问题吗?
这是一个复杂的法律问题,目前各国法规不一。主要考虑:1)模型训练数据可能包含版权作品,存在潜在侵权风险;2)AI生成内容的版权归属不明确,部分国家不承认AI作品的版权;3)如果生成内容与已有作品过于相似,可能构成侵权。建议商业使用时:选择使用合规数据训练的模型(如Adobe Firefly);避免刻意模仿特定艺术家风格;保留生成过程记录;必要时咨询法律专业人士。