潜在扩散模型(LDM)论文精读:从像素空间到潜在空间的高效图像生成

潜在扩散模型(LDM)论文精读:从像素空间到潜在空间的高效图像生成

引言

2022年,CompVis团队在论文《High-Resolution Image Synthesis with Latent Diffusion Models》中提出了潜在扩散模型(LDM),解决了传统扩散模型在像素空间训练的巨大计算开销问题。这项工作是Stable Diffusion的前身,开启了高效高分辨率图像生成的新篇章。

核心问题:传统的扩散模型(如DDPM、DDIM)直接在像素空间操作,生成高分辨率图像需要数百到数千步的迭代,每次迭代都在高维空间(如256×256×3≈200K维度)进行,导致:

  • 训练成本高昂(GPU内存占用大)
  • 推理速度慢(实时应用困难)
  • 难以扩展到更高分辨率

LDM的核心创新:将扩散过程从像素空间转移到压缩的潜在空间,通过预训练的自动编码器将图像压缩到低维表示(如32×32×4≈4K维度),在这个空间执行扩散过程,最后解码回像素空间。

主要贡献

  1. 计算效率提升:内存占用减少约3-4倍,推理速度提升2-3倍
  2. 高质量生成:在多个基准测试上达到SOTA或接近SOTA
  3. 灵活的conditioning:支持文本、图像、类别等多种条件输入

1. 背景回顾:扩散模型的计算瓶颈

1.1 扩散模型基础

扩散模型的核心是通过逐步添加噪声将数据分布转化为简单的高斯分布(前向过程),然后学习逆向去噪过程(反向过程):

前向过程(加噪)
$$ x_t = \sqrt{\alpha_t} x_0 + \sqrt{1 - \alpha_t} \epsilon, \quad \epsilon \sim \mathcal{N}(0, I) $$

其中 $\alpha_t$ 是噪声调度参数,$\alpha_t = \prod_{s=1}^t (1 - \beta_s)$,$\beta_t$ 是方差调度。

反向过程(去噪)
模型学习从噪声中恢复原始图像:
$$ p_\theta(x_{t-1}|x_t) = \mathcal{N}(x_{t-1}; \mu_\theta(x_t, t), \Sigma_\theta(x_t, t)) $$

其中 $\mu_\theta$ 由噪声预测网络 $\epsilon_\theta$ 参数化:
$$ \mu_\theta(x_t, t) = \frac{1}{\sqrt{\alpha_t}} \left( x_t - \frac{1 - \alpha_t}{\sqrt{1 - \bar{\alpha}_t}} \epsilon_\theta(x_t, t) \right) $$

1.2 像素空间扩散的计算瓶颈

在像素空间直接操作高分辨率图像时:

  1. 计算复杂度:对于 $H \times W \times C$ 的图像,UNet需要在 $O(H \times W)$ 的空间维度上操作
  2. 内存占用:特征图尺寸随分辨率平方增长
  3. 训练成本:生成512×512图像需要约16GB GPU内存,推理需要数百步
1
2
3
计算复杂度对比:
像素空间: 512×512×3 ≈ 786,432 元素
潜在空间: 32×32×4 ≈ 4,096 元素 (压缩约192倍)

2. LDM核心创新:潜在空间扩散

2.1 整体架构图

LDM的核心创新在于将扩散过程从高维像素空间转移到低维潜在空间。以下是LDM的整体架构图:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
┌─────────────────────────────────────────────────────────────────────┐
│ Latent Diffusion Model (LDM) │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌──────────────────────┐ │
│ │ 输入图像 │ │ 编码器 │ │ 潜在表示(z) │ │
│ │ x ∈ ℝ^{H×W×3} │────▶ E(x) │────▶ z ∈ ℝ^{h×w×d} │ │
│ └─────────────┘ └─────────────┘ └──────────────────────┘ │
│ │ │
│ │ 扩散过程在潜在空间 │
│ ▼ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ 条件UNet: ε_θ(z_t, t, c) │ │
│ │ ┌────────────────────────────────────────────────┐ │ │
│ │ │ 交叉注意力: Attention(Q, K, V) │ │ │
│ │ │ Q = W_Q·φ(z_t) K = W_K·τ(c) V = W_V·τ(c) │ │ │
│ │ └────────────────────────────────────────────────┘ │ │
│ └──────────────────────────────────────────────────────┘ │
│ │ │
│ │ 去噪后的潜在表示 │
│ ▼ │
│ ┌─────────────┐ ┌─────────────┐ ┌──────────────────────┐ │
│ │ 重建图像 │◀───│ 解码器 │◀───│ 去噪潜在表示 │ │
│ │ x̂ ≈ x │ │ D(z) │ │ ẑ ∈ ℝ^{h×w×d} │ │
│ └─────────────┘ └─────────────┘ └──────────────────────┘ │
│ │
│ 条件输入(c): │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ 文本/类别 │───▶│ 条件编码器 │───▶ τ(c) │
│ │ "a cat" │ │ CLIP/Embed│ │
│ └─────────────┘ └─────────────┘ │
└─────────────────────────────────────────────────────────────────────┘

关键维度说明:
- H×W×3: 原始图像尺寸 (如512×512×3 ≈ 786K元素)
- h×w×d: 潜在表示尺寸 (如64×64×4 ≈ 16K元素, 压缩49倍)
- f = H/h: 下采样因子 (通常8-16)

LDM采用两阶段训练策略:

第一阶段:训练自动编码器 $(E, D)$,学习将图像压缩到低维潜在空间:
$$ z = E(x), \quad \hat{x} = D(z) $$

第二阶段:在潜在空间 $z$ 上训练扩散模型 $\epsilon_\theta$,学习去噪过程。

2.2 为什么潜在空间更高效?

  1. 维度降低:将图像从 $H \times W \times 3$ 压缩到 $h \times w \times d$,其中 $h = H/f$, $w = W/f$,$f$ 是下采样因子(通常8-16)
  2. 计算复杂度降低:扩散过程在低维空间进行,UNet参数量减少
  3. 感知压缩:自动编码器学习保留视觉重要信息,丢弃高频细节

数学上,计算复杂度从 $O(HW)$ 降低到 $O(HW/f^2)$,对于 $f=8$,复杂度降低64倍。

3. 架构详解

3.1 自动编码器架构图

自动编码器是LDM的第一阶段,负责将高维图像压缩到低维潜在空间。其架构如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
自动编码器详细架构:
┌─────────────────────────────────────────────────────────────┐
│ 编码器 (Encoder) │
├─────────────────────────────────────────────────────────────┤
│ 输入: x ∈ ℝ^{512×512×3} │
│ │
│ Conv2d(3, 64, 3, stride=2, padding=1) → 256×256×64 │
│ GroupNorm(32, 64) + SiLU() │
│ │
│ Conv2d(64, 128, 3, stride=2, padding=1) → 128×128×128 │
│ GroupNorm(32, 128) + SiLU() │
│ │
│ Conv2d(128, 256, 3, stride=2, padding=1) → 64×64×256 │
│ GroupNorm(32, 256) + SiLU() │
│ │
│ Conv2d(256, 4, 3, padding=1) → 64×64×4 │
│ 输出: z ∈ ℝ^{64×64×4} (下采样8倍) │
└─────────────────────────────────────────────────────────────┘


┌─────────────────────────────────────────────────────────────┐
│ 解码器 (Decoder) │
├─────────────────────────────────────────────────────────────┤
│ 输入: z ∈ ℝ^{64×64×4} │
│ │
│ Conv2d(4, 256, 3, padding=1) → 64×64×256 │
│ GroupNorm(32, 256) + SiLU() │
│ │
│ Upsample(2×) + Conv2d(256, 128, 3) → 128×128×128 │
│ GroupNorm(32, 128) + SiLU() │
│ │
│ Upsample(2×) + Conv2d(128, 64, 3) → 256×256×64 │
│ GroupNorm(32, 64) + SiLU() │
│ │
│ Upsample(2×) + Conv2d(64, 3, 3) → 512×512×3 │
│ 输出: x̂ ∈ ℝ^{512×512×3} (重建图像) │
└─────────────────────────────────────────────────────────────┘

训练目标(复合损失):
$$
\mathcal{L}_{\mathrm{AE}} = \mathcal{L}_{\mathrm{rec}} + \lambda_{\mathrm{perc}}\mathcal{L}_{\mathrm{perc}} + \lambda_{\mathrm{adv}}\mathcal{L}_{\mathrm{adv}}
$$

- $\mathcal{L}_{\mathrm{rec}}$:像素级重建损失(L1或L2),保证像素级准确
- $\mathcal{L}_{\mathrm{perc}}$:感知损失(VGG特征匹配),保证语义级相似
- $\mathcal{L}_{\mathrm{adv}}$:对抗损失,保证重建图像真实感

3.2 潜在空间扩散模型

在潜在空间 $z$ 上定义扩散过程:

前向过程
$$ z_t = \sqrt{\alpha_t} z_0 + \sqrt{1 - \alpha_t} \epsilon, \quad \epsilon \sim \mathcal{N}(0, I) $$

反向过程(参数化为UNet):
$$ p_\theta(z_{t-1}|z_t, c) = \mathcal{N}(z_{t-1}; \mu_\theta(z_t, t, c), \Sigma_\theta(z_t, t, c)) $$

其中 $c$ 是条件信息(文本、类别等)。

训练目标(简化的ELBO):
$$ \mathcal{L}_{\mathrm{LDM}} = \mathbb{E}_{z \sim E(x), \epsilon \sim \mathcal{N}(0,1), t} \left[ \| \epsilon - \epsilon_\theta(z_t, t, c) \|_2^2 \right] $$

3.3 条件机制

LDM支持多种条件输入,通过交叉注意力机制实现:

$$ \mathrm{Attention}(Q, K, V) = \mathrm{softmax}\left(\frac{QK^T}{\sqrt{d}}\right)V $$

其中:

  • $Q = W_Q \cdot \phi(z_t)$(潜在表示投影)
  • $K = W_K \cdot \tau(c)$(条件编码投影)
  • $V = W_V \cdot \tau(c)$(条件值投影)

$\tau(c)$ 是条件编码器(如文本的CLIP、类别的嵌入层)。

3.4 条件UNet架构图

LDM的条件UNet是扩散过程的核心,它在潜在空间执行去噪,同时整合条件信息。以下是详细的架构图:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
条件UNet详细架构 (U-Net with Cross-Attention):
┌─────────────────────────────────────────────────────────────────────┐
│ 条件UNet: ε_θ(z_t, t, c) │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ 输入: z_t ∈ ℝ^{64×64×4}, t ∈ [0, T], c = τ("text prompt") │
│ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ 下采样路径 (Encoder) │ │
│ ├─────────────────────────────────────────────────────────────┤ │
│ │ ResBlock(z_t, t_emb) → [64×64×256] │ │
│ │ ↓ Cross-Attn(z, c) (与条件交互) │ │
│ │ │ │
│ │ Downsample(2×) → ResBlock → [32×32×512] │ │
│ │ ↓ Cross-Attn(z, c) │ │
│ │ │ │
│ │ Downsample(2×) → ResBlock → [16×16×512] │ │
│ │ ↓ Cross-Attn(z, c) │ │
│ │ │ │
│ │ Downsample(2×) → ResBlock → [8×8×512] │ │
│ │ ↓ Cross-Attn(z, c) │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ 瓶颈层 (Bottleneck) │ │
│ ├─────────────────────────────────────────────────────────────┤ │
│ │ ResBlock → [8×8×512] │ │
│ │ ↓ Cross-Attn(z, c) │ │
│ │ ResBlock → [8×8×512] │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ 上采样路径 (Decoder) │ │
│ ├─────────────────────────────────────────────────────────────┤ │
│ │ ResBlock → [8×8×512] │ │
│ │ ↑ Upsample(2×) + Skip(来自编码器) │ │
│ │ │ │
│ │ ResBlock → [16×16×512] │ │
│ │ ↑ Upsample(2×) + Skip(来自编码器) │ │
│ │ ↓ Cross-Attn(z, c) │ │
│ │ │ │
│ │ ResBlock → [32×32×512] │ │
│ │ ↑ Upsample(2×) + Skip(来自编码器) │ │
│ │ ↓ Cross-Attn(z, c) │ │
│ │ │ │
│ │ ResBlock → [64×64×256] │ │
│ │ ↑ Upsample(2×) + Skip(来自编码器) │ │
│ │ ↓ Cross-Attn(z, c) │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │ │
│ Conv2d(256, 4, 3) │
│ ↓ │
│ 输出: ε_pred ∈ ℝ^{64×64×4} │
│ (预测的噪声) │
└─────────────────────────────────────────────────────────────────────┘

关键组件说明:
1. ResBlock: 残差块,包含GroupNorm、SiLU、卷积,融入时间嵌入t_emb
2. Cross-Attn: 交叉注意力层,连接潜在表示z和条件编码c
3. Skip Connection: U-Net跳跃连接,保留多尺度特征
4. Time Embedding: 正弦位置编码,将时间步t映射为向量

交叉注意力层的详细计算:
潜在特征 → 展平 → Q = W_Q·z_flat → Attention(Q, K, V) → 重塑 → 输出
条件编码 → τ(c) → K = W_K·τ(c), V = W_V·τ(c)

4. 关键公式总结

4.1 核心扩散公式

潜在空间前向过程
$$ z_t = \sqrt{\alpha_t} z_0 + \sqrt{1 - \alpha_t} \epsilon $$

噪声预测目标
$$ \mathcal{L} = \mathbb{E}_{z,\epsilon,t,c} \left[ \| \epsilon - \epsilon_\theta(z_t, t, c) \|_2^2 \right] $$

采样过程(DDIM)
$$ z_{t-1} = \sqrt{\alpha_{t-1}} \left( \frac{z_t - \sqrt{1 - \alpha_t} \epsilon_\theta(z_t, t, c)}{\sqrt{\alpha_t}} \right) + \sqrt{1 - \alpha_{t-1}} \epsilon_\theta(z_t, t, c) $$

4.2 条件机制公式

交叉注意力
$$ \mathrm{CrossAttn}(z, c) = \mathrm{softmax}\left(\frac{(W_Q z)(W_K \tau(c))^T}{\sqrt{d}}\right) (W_V \tau(c)) $$

5. 实现要点与关键代码

5.1 自动编码器实现(PyTorch风格)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
import torch
import torch.nn as nn
import torch.nn.functional as F

class VAEEncoder(nn.Module):
"""自动编码器编码器部分"""
def __init__(self, in_channels=3, latent_channels=4, downscale_factor=8):
super().__init__()
# 卷积下采样层
self.conv_layers = nn.Sequential(
nn.Conv2d(in_channels, 64, 3, stride=2, padding=1), # 下采样2倍
nn.GroupNorm(32, 64),
nn.SiLU(),
nn.Conv2d(64, 128, 3, stride=2, padding=1), # 下采样4倍
nn.GroupNorm(32, 128),
nn.SiLU(),
nn.Conv2d(128, 256, 3, stride=2, padding=1), # 下采样8倍
nn.GroupNorm(32, 256),
nn.SiLU(),
)
# 输出层
self.out_conv = nn.Conv2d(256, latent_channels, 3, padding=1)

def forward(self, x):
x = self.conv_layers(x)
return self.out_conv(x)

class VAEDecoder(nn.Module):
"""自动编码器解码器部分"""
def __init__(self, latent_channels=4, out_channels=3, upscale_factor=8):
super().__init__()
# 初始卷积
self.in_conv = nn.Conv2d(latent_channels, 256, 3, padding=1)
# 卷积上采样层
self.conv_layers = nn.Sequential(
nn.Conv2d(256, 256, 3, padding=1),
nn.GroupNorm(32, 256),
nn.SiLU(),
nn.Upsample(scale_factor=2, mode='nearest'), # 上采样2倍
nn.Conv2d(256, 128, 3, padding=1),
nn.GroupNorm(32, 128),
nn.SiLU(),
nn.Upsample(scale_factor=2, mode='nearest'), # 上采样4倍
nn.Conv2d(128, 64, 3, padding=1),
nn.GroupNorm(32, 64),
nn.SiLU(),
nn.Upsample(scale_factor=2, mode='nearest'), # 上采样8倍
)
# 输出层
self.out_conv = nn.Conv2d(64, out_channels, 3, padding=1)

def forward(self, z):
z = self.in_conv(z)
z = self.conv_layers(z)
return self.out_conv(z)

class AutoencoderKL(nn.Module):
"""KL正则化的自动编码器(LDM使用)"""
def __init__(self):
super().__init__()
self.encoder = VAEEncoder()
self.decoder = VAEDecoder()

def encode(self, x):
"""编码图像到潜在空间"""
return self.encoder(x)

def decode(self, z):
"""解码潜在表示回图像"""
return self.decoder(z)

5.2 条件UNet实现(关键部分)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
class CrossAttention(nn.Module):
"""交叉注意力层(条件机制核心)"""
def __init__(self, query_dim, context_dim=None, heads=8, dim_head=64):
super().__init__()
inner_dim = dim_head * heads
context_dim = context_dim if context_dim is not None else query_dim

self.scale = dim_head ** -0.5
self.heads = heads

# 投影层
self.to_q = nn.Linear(query_dim, inner_dim, bias=False)
self.to_k = nn.Linear(context_dim, inner_dim, bias=False)
self.to_v = nn.Linear(context_dim, inner_dim, bias=False)
self.to_out = nn.Linear(inner_dim, query_dim)

def forward(self, x, context=None):
h = self.heads

# 查询投影
q = self.to_q(x)

# 键值投影(使用条件上下文)
context = x if context is None else context
k = self.to_k(context)
v = self.to_v(context)

# 分头并计算注意力
q, k, v = map(lambda t: t.view(*t.shape[:2], h, -1).transpose(1, 2), (q, k, v))

# 注意力计算
sim = torch.einsum('b h i d, b h j d -> b h i j', q, k) * self.scale
attn = sim.softmax(dim=-1)

# 加权聚合
out = torch.einsum('b h i j, b h j d -> b h i d', attn, v)
out = out.transpose(1, 2).reshape(*x.shape[:2], -1)

return self.to_out(out)

class UNetBlock(nn.Module):
"""UNet基础块(带条件)"""
def __init__(self, dim, context_dim=None):
super().__init__()
# 基础卷积层
self.norm1 = nn.GroupNorm(32, dim)
self.conv1 = nn.Conv2d(dim, dim, 3, padding=1)

# 时间嵌入
self.time_emb = nn.Sequential(
nn.SiLU(),
nn.Linear(1280, dim) # 时间嵌入维度
)

# 交叉注意力(条件机制)
self.norm2 = nn.GroupNorm(32, dim)
self.attn = CrossAttention(dim, context_dim)

# 输出层
self.norm3 = nn.GroupNorm(32, dim)
self.conv2 = nn.Conv2d(dim, dim, 3, padding=1)

def forward(self, x, time_emb=None, context=None):
# 残差连接1
h = x
h = self.norm1(h)
h = self.conv1(h)

# 添加时间嵌入
if time_emb is not None:
time_emb = self.time_emb(time_emb)
h = h + time_emb[:, :, None, None]

# 交叉注意力
h = self.norm2(h)
# 将空间特征展平为序列
b, c, hh, ww = h.shape
h_flat = h.view(b, c, -1).transpose(1, 2) # [b, h*w, c]
context_flat = self.attn(h_flat, context) # 交叉注意力
h = context_flat.transpose(1, 2).view(b, c, hh, ww)

# 输出
h = self.norm3(h)
h = self.conv2(h)

return x + h # 残差连接

5.3 训练循环关键部分

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
def train_step_latent_diffusion(autoencoder, diffusion_model, batch, 
text_encoder, optimizer, device):
"""LDM训练步骤"""
images, captions = batch
images = images.to(device)

# 1. 编码图像到潜在空间
with torch.no_grad():
latents = autoencoder.encode(images) # [B, C, H/8, W/8]

# 2. 编码文本条件
text_embeddings = text_encoder(captions) # [B, seq_len, d_model]

# 3. 扩散过程
batch_size = latents.shape[0]
timesteps = torch.randint(0, 1000, (batch_size,), device=device)
noise = torch.randn_like(latents)

# 加噪
noisy_latents = add_noise(latents, noise, timesteps)

# 4. 预测噪声
noise_pred = diffusion_model(noisy_latents, timesteps, text_embeddings)

# 5. 计算损失
loss = F.mse_loss(noise_pred, noise)

# 6. 反向传播
optimizer.zero_grad()
loss.backward()
optimizer.step()

return loss.item()

def add_noise(latents, noise, timesteps, noise_scheduler):
"""添加噪声到潜在表示"""
sqrt_alpha = torch.sqrt(noise_scheduler.alphas_cumprod[timesteps])
sqrt_one_minus_alpha = torch.sqrt(1 - noise_scheduler.alphas_cumprod[timesteps])

# 调整维度用于广播
sqrt_alpha = sqrt_alpha[:, None, None, None]
sqrt_one_minus_alpha = sqrt_one_minus_alpha[:, None, None, None]

return sqrt_alpha * latents + sqrt_one_minus_alpha * noise

6. 训练与推理流程

6.1 两阶段训练策略

第一阶段:自动编码器训练

1
2
3
4
5
6
7
8
9
10
11
12
13
for epoch in range(autoencoder_epochs):
# 1. 编码图像
latents = encoder(images)

# 2. 解码重建
reconstructions = decoder(latents)

# 3. 计算损失(重建+感知+对抗)
loss = reconstruction_loss + λ_perc * perceptual_loss + λ_adv * adversarial_loss

# 4. 反向传播
loss.backward()
optimizer.step()

第二阶段:潜在扩散训练

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 冻结自动编码器
autoencoder.eval()
for param in autoencoder.parameters():
param.requires_grad = False

for epoch in range(diffusion_epochs):
# 1. 编码图像到潜在空间
with torch.no_grad():
latents = autoencoder.encode(images)

# 2. 训练扩散模型(在潜在空间)
loss = diffusion_train_step(latents, conditions)

# 3. 反向传播
loss.backward()
optimizer.step()

6.2 推理(采样)流程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
def sample_latent_diffusion(diffusion_model, autoencoder, 
condition, steps=50, guidance_scale=7.5):
"""从LDM采样图像"""
# 1. 从纯噪声开始
batch_size = condition.shape[0]
latent_shape = (batch_size, 4, 32, 32) # 示例:32×32潜在空间
latents = torch.randn(latent_shape, device=device)

# 2. 逐步去噪(DDIM采样)
for i, t in enumerate(reversed(range(steps))):
# 添加条件信息
noise_pred = diffusion_model(latents, t, condition)

# 分类器自由引导(CFG)
if guidance_scale > 1.0:
# 无条件预测
uncond_pred = diffusion_model(latents, t, None)
# 引导插值
noise_pred = uncond_pred + guidance_scale * (noise_pred - uncond_pred)

# DDIM更新步骤
latents = ddim_step(latents, noise_pred, t, t-1)

# 3. 解码回图像空间
with torch.no_grad():
images = autoencoder.decode(latents)

return images

7. 核心优势与实验结果

7.1 计算效率对比

模型 分辨率 参数量 训练内存 推理速度(步) FID↓
Pixel Diffusion 256×256 400M 16GB 1000 5.2
LDM 256×256 400M 4GB 250 4.8
Pixel Diffusion 512×512 800M OOM - -
LDM 512×512 800M 8GB 500 7.2

7.2 关键优势总结

  1. 效率提升:内存占用减少3-4倍,推理速度提升2-4倍
  2. 质量保持:在ImageNet、LSUN等数据集上达到SOTA或接近SOTA
  3. 灵活扩展:易于扩展到文本到图像、图像修复、超分辨率等任务
  4. 实用性强:成为Stable Diffusion等工业级应用的基础

8. 总结与展望

8.1 LDM的核心贡献

  1. 潜在空间范式:首次系统地在压缩潜在空间进行扩散,解决计算瓶颈
  2. 两阶段训练:解耦表征学习和生成建模,提高训练稳定性
  3. 通用条件框架:统一的交叉注意力机制支持多模态条件输入
  4. 实用化路径:为Stable Diffusion等实际应用铺平道路

8.2 后续发展与研究方向

  1. 更大规模预训练:Stable Diffusion在LAION-5B上的成功验证
  2. 更高效架构:DiT(Diffusion Transformer)等新架构探索
  3. 更快采样:DPM-Solver、LCM等加速方法
  4. 视频与3D生成:扩展到时序和三维数据

8.3 实际应用建议

  1. 入门实践:从Stable Diffusion微调开始,理解LDM工作流程
  2. 研究扩展:探索新的条件机制、更高效的潜在表示
  3. 工业应用:考虑计算约束,选择合适的下采样因子和模型规模

9. 进一步学习资源


关键要点回顾

  1. 核心创新:在自动编码器压缩的潜在空间执行扩散,而非像素空间
  2. 关键公式:潜在空间扩散 $\mathcal{L} = \mathbb{E}[| \epsilon - \epsilon_\theta(z_t, t, c) |^2]$
  3. 条件机制:交叉注意力实现文本/图像等多模态条件
  4. 效率提升:内存减少3-4倍,推理加速2-4倍,支持高分辨率生成

希望本文帮助你深入理解LDM的核心思想与实现。如果你在实践中有任何问题或想法,欢迎在评论区交流讨论!