Diffusion model 就是在做一件事情:故意把图片加噪声弄模糊,再训练AI学会如何一步步把模糊的图"复原"回去。
训练时:让AI学会"洗图"(预测噪声位置);
推理时:从纯噪声开始,逐步"雕刻"出清晰的图片。
Diffusion model的核心思想可以用一个简单的类比来理解:
想象你有一张干净的画:
- Step 1: 故意弄脏 - 你拿橡皮擦在上面涂抹,一次比一次重,最终变成完全看不清的白噪声
- Step 2: 学会清洗 - 训练一个AI:"如果图片现在这么模糊,应该怎么恢复上一步?"
- Step 3: 逐步复原 - AI从完全模糊的状态开始,一步步去掉噪声,最终变回清晰的画
直接生成太难了!让AI一步到位从"虚无"中生成一张清晰的图,难度极大。但让AI学会"每步只去掉一点点噪声",这个任务就简单多了。
类比:雕塑家从一块大理石开始,每次只凿掉一点点,最终雕刻出作品。而不是直接让AI"凭空变出雕塑"。
前向扩散的目标很简单:把清晰的图 $x_0$ 变成纯噪声 $x_T$。
每一步加一点点高斯噪声
2.1 数学公式
- $x_t$:第 $t$ 步的图片(越来越模糊)
- $\beta_t$:噪声强度调度($t$ 越大,噪声越多,通常从 0.0001 增到 0.02)
- $\epsilon$:随机高斯噪声(就像电视雪花屏,从 $\mathcal{N}(0, I)$ 采样)
- $\sqrt{1-\beta_t}$:保留原信息的比例
通过重参数化技巧,可以直接从 $x_0$ 跳到任意步 $x_t$:
其中 $\bar{\alpha}_t = \prod_{s=1}^t (1 - \beta_s)$,表示累计保留的原始信息比例。
2.2 举例说明
假设我们有一张猫咪图片:
- x_0:清晰的猫咪照片(像素值如 [0.8, 0.2, 0.5, ...])
- x_{250}:猫咪轮廓还在,但细节模糊,像雾里看花
- x_{500}:只能隐约看到有个物体,已经看不出是猫
- x_{1000}:完全看不出是猫,像老电视的雪花屏(纯噪声)
如果 $\beta_t=0.01$,那么每一步保留 99% 的原图信息,添加 1% 的噪声。
数学上:$\bar{\alpha}_{1000} \approx 0$(信息几乎完全扩散),$x_{1000} \approx \epsilon$(纯噪声)。
逆向去噪的目标:让AI学会从 $x_t$ 预测"刚刚加了什么噪声"。
每步预测并去掉噪声
3.1 Loss函数
- $\epsilon$:真实加的噪声(训练时已知)
- $\epsilon_\theta(x_t, t)$:AI预测的噪声(U-Net输出)
- $\|\cdot\|^2$:均方误差(像素级对比)
- 采样:从数据集随机取一张图 $x_0$
- 采样时间步:随机取 $t \in [1, T]$
- 加噪声:用公式生成 $x_t = \sqrt{\bar{\alpha}_t} x_0 + \sqrt{1-\bar{\alpha}_t} \epsilon$
- 预测:让U-Net看 $(x_t, t)$,输出 $\epsilon_\theta(x_t, t)$
- 计算Loss:$\|\epsilon - \epsilon_\theta\|^2$,反向传播更新参数
3.2 举例说明
场景:无条件生成一张猫咪图(先不考虑"告诉AI画什么",那是后面 §5 的内容)
- 起点:随机生成一张纯噪声图 $x_{1000}$(雪花屏)
- 第1000步→999步:
- U-Net看 $x_{1000}$ 和 $t=1000$,预测噪声位置
- 去掉预测的噪声:$x_{999} = x_{1000} - \epsilon_\theta(x_{1000}, 1000)$
- 第999步→998步:
- 图稍微清晰了点,U-Net继续预测并去噪
- 重复1000步:最终从雪花屏变成清晰猫咪
类比:就像雕塑家从一块大理石开始,每次凿掉一点多余的石头,最终雕刻出作品。
❓ 等等,这里没有说"画猫咪",AI怎么知道生成的是猫?
因为训练集里全是真实图片(包括猫)。模型学到了"真实图像的分布",逆向去噪就是沿着分布走——最终落点是真实图像空间里的某个点。至于如何控制生成内容,继续看 §3.5 和 §5。
你可能会问:为什么不直接训练一个模型,输入噪声直接输出清晰图?
答案:一步到位的难度太大了!
❌ 一步生成
纯噪声→清晰图
难度:😱 极难
像让小学生直接写博士论文
✅ 渐进去噪
每步去掉一点点噪声
难度:😊 可行
像让小学生每次只改一个错别字
前面讲了前向加噪、逆向去噪,训练时用的是真实图片……但我想生成一张从没存在过的新图,这两件事有什么关系?
先搞清楚:生成模型在做什么
图像生成的本质是:从一个概率分布中采样。
想象世界上所有猫咪照片构成一个分布,每张猫咪图都是这个分布里的一个点。生成模型要做的事,就是学会这个分布的"形状",然后从里面随机采一个新点出来。
把"所有猫咪图像"想象成一块地形图,猫咪图聚集的地方是山峰,不像猫的图是山谷。
- 传统方法:需要直接描述这个地形的形状(非常复杂)
- Diffusion的思路:不直接描述地形,而是学习"地形的引力场"——知道了任意一点的引力方向,就能从随机位置顺着引力"爬山",最终落在山峰上
去噪 = 学习数据分布的"引力场"
这是 Diffusion 最核心的数学洞察,用人话来说:
训练一个"预测噪声"的网络 ≈ 学习了"如何从任意噪声位置,往真实图像方向走一步"
换句话说:模型在训练时看了无数张真实图片的"各种模糊程度",学会的不只是"去噪"这个动作,而是所有真实图像组成的分布长什么样。
为什么?因为训练时给模型看的 $x_t$ 是从真实图片加噪声来的。所以模型学到的每一步"去噪方向",都指向真实图像分布。
推理时发生了什么(这才是生成!)
训练结束后,你完全不需要任何真实图片。推理时:
这是一个完全随机的点,不对应任何真实图片
模型输出"这个噪声点里有多少噪声",等价于"真实图像方向在哪里"
往真实图像分布的方向靠近了一点点
这个点是训练集里没有的全新图片,但它符合真实图像的规律
类比LLM:你作为LLM背景的人可以这样理解——
- GPT 的训练目标是"预测下一个 token",但推理时它能生成从没存在过的句子
- Diffusion 的训练目标是"预测加了什么噪声",但推理时它能生成从没存在过的图片
两者的共同点:通过预测任务学到了数据分布,采样时就能从分布里生成新内容。
具体过程(以生成猫咪为例):
- 随机噪声 $x_{1000}$:像一团乱码,不像任何东西
- 去噪50步后 $x_{950}$:开始有了一些纹理,但还不清晰
- 去噪500步后 $x_{500}$:隐约有个动物的轮廓
- 去噪900步后 $x_{100}$:能看出是猫,细节逐渐清晰
- 去噪完成 $x_0$:一张从未存在过的、全新的猫咪图片
每次随机采样不同的 $x_T$,就会生成不同的猫咪。这就是生成的随机性来源。
前向扩散的作用:它只在训练时用!
前向扩散(§2)只在训练阶段使用,推理时完全不用它。
- 训练时:用前向扩散给真实图片加噪声,制造训练样本 $(x_t, \epsilon)$
- 推理时:直接随机采样纯噪声,用逆向去噪生成图片
前向扩散是"制造训练数据的工具",不是推理流程的一部分。
- 训练阶段:见过海量真实图片 → 学会了"真实图像分布的形状"(体现为去噪能力)
- 推理起点:随机采样纯噪声(任意起点)
- 推理过程:用学到的分布知识,逐步把噪声"拉向"真实图像分布 → 输出全新图片
明确一下 U-Net 在 Diffusion 里的输入和输出:
📥 输入(两个)
- 含噪图片 $x_t$:一张被加了噪声的图,形状和原图一样(如 64×64×3)
- 时间步 $t$:一个整数,告诉网络"现在噪声有多严重"(如 $t=500$)
📤 输出(一个)
- 预测的噪声 $\hat{\epsilon}$:和输入图片形状完全相同(64×64×3),表示"刚才加的是什么噪声"
用输入减去输出噪声,就能还原上一步的图片
很多人以为 U-Net 直接输出最终清晰图片——不是。它输出的是"噪声"(即加进去的那部分),然后用输入减去噪声才得到去了一步噪的图片。这个去噪过程要重复1000次,最终才得到清晰图。
4.1 结构详解
+ 时间步 t
↑每层都注入时间步
(8×8×512)
形状与输入完全相同
拼接编码器的跳跃连接
x_{t-1} = x_t - ε̂ (一步去噪)
三个核心机制:
- 编码器(下采样):用卷积逐层压缩空间尺寸(64→32→16→8),同时提取语义特征
- 解码器(上采样):逐层恢复空间尺寸,但需要知道细节在哪里
- 跳跃连接:把编码器每层的特征图直接拼接给对应的解码器层——这样解码器既有抽象语义(来自瓶颈),又有精确位置(来自跳跃连接)
4.2 举例:完整走一遍
输入:$x_{500}$(一张模糊的猫咪,噪声很重,隐约能看出轮廓)+ $t=500$
- 编码器第1层(64×64):检测到"有一些模糊的毛发纹理",同时把 $t=500$ 的时间信息加进去(详见4.3节)
- 编码器第2层(32×32):检测到"有一个模糊的圆形轮廓(头部)"
- 瓶颈层(8×8):最抽象的理解:"这大概是一个动物"
- 解码器第2层:用瓶颈层的语义 + 编码器第2层的跳跃连接,推断出"猫耳朵这里有多少噪声"
- 解码器第1层:用更精细的跳跃连接,推断毛发纹理处的噪声分布
- 输出:一张 64×64×3 的"噪声图" $\hat{\epsilon}$,表示"这张图里加了这么多噪声"
去噪计算:$x_{499} = x_{500} - \hat{\epsilon}$,得到稍微清晰一点点的猫咪图
4.3 时间步编码:怎么告诉网络"现在有多模糊"
U-Net 要处理1000种不同程度的噪声图($t$ 从1到1000),同一张图在 $t=100$ 和 $t=900$ 时需要完全不同的去噪策略:
- $t=100$:噪声很少,图片基本清晰 → 要细心保留细节,小幅度去噪
- $t=900$:噪声极多,几乎全是杂乱信号 → 要大胆"猜"出大致内容,忽略细节
但时间步 $t$ 只是一个整数,怎么让神经网络理解它?和 LLM 的位置编码一模一样的思路:正弦编码。
- $t$:时间步整数(1 到 1000)
- $d$:编码维度(如 512 维,和 U-Net 特征维度相同)
- $e(t)$:最终的时间步向量,长度为 $d$,每个分量都是不同频率的正余弦值
这是关键——不是只在输入层加一次,而是在 U-Net 的每一个 ResBlock 里都加进去:
- 把 $t$ 转成 $d$ 维向量 $e(t)$(如 512 维)
- 再过一个小 MLP,得到 scale $\gamma$ 和 shift $\beta$ 各一个向量
- 在每个 ResBlock 内部,对特征图做:
feature = feature × γ + β(相当于 LayerNorm + 条件调制)
效果:每一层都"知道"现在是第几步,从而调整自己的行为。这和 Transformer 中位置编码注入到每层 Attention 是同样的道理。
关键澄清:DDPM 每步要预测的噪声 $\epsilon \sim \mathcal{N}(0, I)$,分布与 $t$ 无关,幅度并没有"越大越小"之分。时间步 $t$ 告诉网络的是当前输入 $x_t$ 的信噪比(SNR),进而影响网络提取特征的策略:
$t = 50$(SNR 高,图片清晰)
$x_{50}$ 已经很清晰,图片结构清晰可见
→ 网络可以看清细节,做精细、局部的噪声预测(如毛发纹理处的微小修正)
$t = 950$(SNR 低,几乎全是噪声)
$x_{950} \approx \epsilon$,几乎看不出任何图像结构
→ 网络几乎没有可用信号,只能依赖全局先验猜测噪声(任务更难,误差更大)
类比 LLM:就像 Transformer 里的位置编码让模型知道"这是第几个 token",时间步编码让 U-Net 知道"当前输入有多'脏'(信噪比多低)",从而调整用什么特征来做预测。
无条件生成
输入随机噪声 → 输出随机图片(不可控,只知道"生成符合训练集的图")
条件生成
输入噪声 + 文本条件 → 输出符合文本描述的图片(可控)
5.0 两种训练,两种数据
不是。它们目标不同、数据不同、架构也不同。
阶段一:无条件去噪(纯图像)
训练数据:只需要图片,无需文字描述
目的:让 U-Net 学会"什么样的像素排列是真实图像"(学图像分布)
结果:能从随机噪声生成图片,但无法控制内容
这是独立完整的成果,有自己用途(无条件生成、图像补全等)
阶段二:条件生成(图文对)
训练数据:需要 (图片, 文字描述) 对,如 LAION-5B(50亿图文对)
目的:让 U-Net 学会"给定文本条件时,朝符合描述的方向去噪"
架构:新增 Cross-Attention 层,不是原来 DDPM U-Net 的结构
实践上的常见做法:先在纯图像上预训练(无条件),让网络学好图像特征表示;再加入 Cross-Attention 层,在图文对上 fine-tune。好处是收敛更快、图像质量更好,因为图像特征不用从零学。
类比 LLM:先在纯文本上预训练(学语言能力),再用对话数据做指令微调(学遵从指令)——前者的特征表示对后者有帮助,但两个阶段目标完全不同。
当然也可以直接用图文对从头训(跳过阶段一),效果相近,只是需要更多数据和算力。
5.1 端到端流程:文本如何变成图像
条件生成不是"在最后加一个文本",而是在每一步去噪时都把文本信息注入进去。整体流程分三步:
用文本编码器(如 CLIP 的 Text Encoder)把 prompt 变成一组向量 $c \in \mathbb{R}^{L \times d}$,其中 $L$ 是 token 数量,$d$ 是向量维度(如 768)。
例:"一只戴着红围巾的猫咪" → [token_1: 一只, token_2: 戴着, token_3: 红围巾, token_4: 的, token_5: 猫咪] → 每个 token 变成 768 维向量
在 U-Net 的每个 ResBlock 里,有一个 Cross-Attention 层。图像特征"问" ($Q$) 文本特征"答" ($K, V$),让图像每个位置都能感知文本描述。
经过 Cross-Attention 调制后,U-Net 预测的噪声 $\hat{\epsilon}$ 会偏向"去掉后更符合文本描述的方向"。重复1000步,最终落在符合 prompt 的图像上。
5.2 CLIP 的角色:文图对齐的翻译器
重要澄清:带条件生成能力的 U-Net(如 Stable Diffusion 里的)不是把 CLIP 插到一个已有 U-Net 上,而是从头训练一个专门包含 Cross-Attention 层的新 U-Net,训练目标就是"给定 $x_t$ + CLIP 文本 embedding $c$,预测 $\epsilon$"。
- CLIP 文本编码器:训练时冻结权重,只做特征提取——把文本变成 embedding 序列 $c$
- U-Net 的 Cross-Attention 投影矩阵($W_Q, W_K, W_V$):从零训练,专门学"如何把 CLIP 的语义向量和图像特征关联"
训练和推理都用同一个冻结的 CLIP,没有训练/推理不一致。
CLIP vs 普通语言模型(如 BERT)
CLIP 是用图文对训练的,"猫咪"的文本向量和猫咪图像的向量在同一对齐空间里。BERT 没有对齐图像空间,直接用效果差很多。
更新:现代模型用 T5/LLM
Imagen 用 T5-XXL,FLUX 用 T5+CLIP 双编码器。纯语言模型对复杂 prompt 的理解更强,但需要更大的 Cross-Attention 层来桥接。
5.3 Cross-Attention:图像"问"文本"答"
Cross-Attention 在 U-Net 里的位置:编码器和解码器的每个 ResBlock 之后都有一个(不只在瓶颈层)。
- $Q = W_Q \cdot z$:由图像特征线性投影而来($z$ 是 U-Net 当前层的特征图,展平后)
- $K = W_K \cdot c$:由文本向量投影而来($c$ 是 CLIP 输出的 token 序列,固定不变)
- $V = W_V \cdot c$:同样来自文本向量
- $d_k$:$K$ 的维度,用于缩放防止点积过大
- 图像每个空间位置(展平为 token)生成一个 Query $Q_i$,相当于"我这里是什么区域,应该有什么内容?"
- 计算 $Q_i$ 和所有文本 token 的 $K_j$ 的相似度 → 得到注意力权重 $\alpha_{ij}$
- 用权重对文本 $V_j$ 加权求和 → 输出"这个图像位置应该关注的文本信息"
- 把这个信息加回图像特征,调制 U-Net 的去噪方向
类比 LLM 里的 Cross-Attention:机器翻译里解码器生成每个词时,会 attend 到编码器的输出——原理完全一样,这里换成"图像生成每个位置时,attend 到文本的 token"。
5.4 完整举例:生成"一只戴着红围巾的猫咪"
输入:$x_{500}$(模糊图)+ $t=500$ + 文本 $c$("一只戴着红围巾的猫咪" 的 CLIP 向量)
Step 1:CLIP 编码文本(只做一次,整个推理过程共享)
- "一只" → $c_1 = [0.1, 0.3, ...]$
- "红围巾" → $c_3 = [0.8, -0.2, ...]$(在 CLIP 空间里,和红色、围巾相关的图像特征相近)
- "猫咪" → $c_5 = [0.5, 0.7, ...]$
Step 2:U-Net 编码器处理 $x_{500}$,某一层的图像特征(局部区域):
- 脖子区域的特征 $z_{\text{neck}}$ → 投影为 $Q_{\text{neck}}$:"这里是脖子/胸口附近,应该有什么?"
- 脸部区域的特征 $z_{\text{face}}$ → 投影为 $Q_{\text{face}}$:"这里是头部,应该有什么?"
Step 3:Cross-Attention 计算
- $Q_{\text{neck}} \cdot K_{\text{红围巾}}$ 相似度高 → $\alpha_{\text{neck, 红围巾}}$ 大 → 脖子位置的输出大量参考"红围巾"的 $V$
- $Q_{\text{face}} \cdot K_{\text{猫咪}}$ 相似度高 → 脸部区域参考"猫咪"的 $V$
Step 4:调制后的 U-Net 输出噪声 $\hat{\epsilon}$
- 预测的噪声在脖子位置会"偏向"去除与红围巾不一致的噪声
- 去噪后:$x_{499}$ 在脖子区域的红色信号比 $x_{500}$ 稍微清晰一点点
重复1000步:每一步都用同样的文本 $c$ 做 Cross-Attention,每步都把图像往"符合描述"的方向推一点。最终 $x_0$ = 一只清晰的、脖子上有红围巾的猫咪。
5.5 一个关键问题:条件在哪一步起作用最大?
早期步骤($t$ 大,如 900→700)
图片还几乎全是噪声,条件主要决定整体构图和语义:这是猫还是狗?有没有围巾?
后期步骤($t$ 小,如 100→0)
图片已经大致成形,条件主要决定细节和纹理:围巾的花纹、毛发的颜色深浅
这也是为什么去噪步数不够(如只做200步)时,图像细节会差——早期定了形,后期精修同样重要。
核心创新:不在像素空间扩散,而是在隐空间扩散。
6.1 核心思想
(64×64×4,隐空间)
全程 64×64×4
(64×64×4)
(512×512×3,像素空间)
去噪的每一步输入和输出都是 64×64×4 的隐向量,永远不会在中间变成图像大小。VAE Decoder 只在最后跑一次,把最终干净的隐向量还原成像素图。
❌ 像素空间扩散(DDPM)
- 每步 U-Net 处理:512×512×3 = 786,432 个值
- ×1000步 = 极大计算量
✅ 隐空间扩散(Stable Diffusion)
- 每步 U-Net 处理:64×64×4 = 16,384 个值(少 48x)
- 省的是每步的计算量,×50步,总省约 960 倍
6.2 隐空间去噪:和 DDPM 完全一样的操作
U-Net 本质上是一个函数:输入一个张量,输出同形状的张量。它不关心输入是"图像像素"还是"隐向量",只做卷积/Attention 运算。
DDPM(像素空间)
x_t (512×512×3)
→ [U-Net]
→ ε̂ (512×512×3)
→ x_{t-1} = x_t - ε̂
LDM(隐空间)
z_t (64×64×4)
→ [U-Net]
→ ε̂ (64×64×4)
→ z_{t-1} = z_t - ε̂
唯一的区别是训练目标变了:DDPM 预测加在像素上的噪声;LDM 预测加在隐向量上的噪声。两者数学上完全等价。
VAE Encoder 把图像压缩成 64×64×4 的浮点数矩阵,每个数字都是图像语义的抽象编码(颜色、纹理、形状信息)。你可以直接对这些浮点数加高斯噪声、做加减运算——它们是普通数字,不需要解码回图像就能操作。
VAE Decoder 只在最后用:1000步去噪结束,得到干净的 $z_0$ 后,才调用 Decoder 还原成像素图,给人看。
6.3 数字对比
| 方法 | 每步数据量 | 步数 | U-Net 总计算量(相对) |
|---|---|---|---|
| DDPM(像素空间) | 786,432 值 | 1000步 | 1x(基准) |
| Stable Diffusion(隐空间) | 16,384 值(少48x) | 50步(少20x) | 约 1/960x |
节省来自两处:① 每步数据量小 48x;② 去噪步数可以少(隐空间更平滑,50步已足够)。VAE Encoder/Decoder 只各跑一次,开销相比 U-Net 几乎忽略不计。
问题:普通的条件生成,模型会"偷懒"——只依赖图像自身特征,部分忽略文本条件,生成的图与 prompt 不够贴合。
解决方案:用同一个模型同时学条件和无条件去噪,推理时把条件方向"放大"。
7.1 怎么训练:一个模型,随机 Drop 条件
"同时训练条件和无条件"听起来像两个模型,实际上是同一个模型,训练技巧如下:
- 训练时,随机有 10%~20% 的概率把文本条件 $c$ 替换成空($\emptyset$,即 null token)
- 其余时候正常传入文本条件
这样同一个模型在有条件和无条件两种情况下都被训练到,权重是共享的。
推理时:用这一个模型跑两次——一次传条件 $c$,一次传空 $\emptyset$,分别得到两个噪声预测,再做加权组合。
7.2 公式与直觉
- $\epsilon_\theta(x_t, c)$:条件去噪预测(传入文本 $c$)
- $\epsilon_\theta(x_t, \emptyset)$:无条件去噪预测(传入空条件)
- $\epsilon_\theta(x_t, c) - \epsilon_\theta(x_t, \emptyset)$:条件带来的"额外噪声方向"
- $s$:引导强度(通常 7.5~15,越大越听话于 prompt)
去噪 = 从图里"抠掉"噪声,抠掉什么,剩下的就是什么。
- $\epsilon_\theta(x_t, c)$(红猫条件)预测的噪声:抠掉后,剩下红猫信号
- $\epsilon_\theta(x_t, \emptyset)$(无条件)预测的噪声:抠掉后,剩下普通猫信号
- 差值 = 让图"变红"需要额外多抠的那部分噪声方向
- 乘以 $s > 1$:放大这个方向,抠掉更多"红色对应的噪声"→ 剩下的红色信号更强→ 图更红
换个说法:CFG 在"条件方向"上做了线性外推(extrapolation),$s=1$ 是正常条件,$s>1$ 是往条件方向"过冲"。
7.3 举例:生成"一只红色的猫"
第 $t=500$ 步,同一个模型跑两次:
无条件预测 $\epsilon_\theta(x_t, \emptyset)$
传入空 token,模型"自由发挥"
→ 预测的噪声只管把图变成"像真实图片"的方向(可能是橙猫、灰猫、任何猫)
条件预测 $\epsilon_\theta(x_t, c)$
传入"红色的猫"
→ 预测的噪声在无条件基础上,额外去掉了"不是红色"对应的噪声成分
CFG 组合:
$\tilde{\epsilon}$ = 无条件噪声 + 7.5 × (条件噪声 − 无条件噪声)
= 无条件噪声 + 7.5 × (那个"让图变红"的方向)
→ 相当于在"红猫方向"上走了 7.5 倍的步长,最终图里红色信号被大幅放大
你的理解完全对:"噪声里不要红了,那生成的图片就是很红了"——抠掉更多"非红"噪声,剩下的红色信号就更强。
- s = 1:等于纯粹条件模型,不放大
- s = 7.5:Stable Diffusion 默认值,平衡质量和多样性
- s = 15+:非常听话于 prompt,但可能过度饱和、颜色失真
8.1 为什么从 U-Net 换成 Transformer(DiT)
你说得对——CV 领域现在基本是 Transformer 天下(ViT、Swin 等)。那为什么早期 Diffusion 还在用 U-Net 这种卷积范式?
U-Net(卷积)为什么曾经是主流
- 医学图像分割领域早已验证,成熟稳定
- 跳跃连接天然保留局部细节,适合像素级任务
- 卷积的归纳偏置(平移等变性)对图像有效
- 早期(2020-2022)算力不足,Transformer 太贵
U-Net 的问题
- Attention 只在局部感受野内有效,全局建模弱
- Cross-Attention 是"后插"的,与卷积特征的融合不够自然
- 扩展性差:想扩大模型规模,卷积层结构难以统一 scale
- 视频/3D 场景下时序建模更笨重
DiT(Peebles & Xie, 2022)的核心想法:把 U-Net 完全换成 Transformer。
- 输入处理:把含噪图片(或隐向量)切成 patch,每个 patch 当成一个 token(和 ViT 一样)
- 时间步和条件注入:用 adaLN-Zero(自适应 LayerNorm)把 $t$ 和文本 embedding 调制进每个 Transformer block,替代 U-Net 的 ResBlock + Cross-Attention
- 没有跳跃连接:Transformer 靠 Self-Attention 的全局建模来保留细节,不需要编码器-解码器结构
- 可扩展性极强:直接 scale 层数/头数,性能随参数量稳定提升(scaling law 成立)
结论:现代主流文生图/文生视频模型(SD3、FLUX、Sora)全部基于 DiT 或 DiT 变体,U-Net 架构基本退出主流。
8.2 现代文生图:SD3 / FLUX / DALL-E 3
| 模型 | 年份 | 骨干网络 | 文本编码器 | 核心创新 |
|---|---|---|---|---|
| DDPM | 2020 | U-Net(像素空间) | 无条件 | 奠定数学框架 |
| Stable Diffusion v1 | 2022 | U-Net(隐空间) | CLIP ViT-L | 开源 LDM,社区生态 |
| DALL-E 3 | 2023 | U-Net(隐空间) | T5-XXL + CLIP | 重新标注训练数据,prompt 遵从度大幅提升 |
| SD3 | 2024 | DiT(MMDiT) | T5-XXL + CLIP×2 | 文本 token 和图像 token 在同一 Transformer 里做双流 Attention |
| FLUX.1 | 2024 | DiT(Flow Matching) | T5-XXL + CLIP-L | Flow Matching 替代 DDPM 训练目标,更快收敛;12B 参数开源 |
SD3(Stable Diffusion 3)的核心架构是 MMDiT(Multimodal DiT),和之前 U-Net 架构最大的区别:
- 旧方案(U-Net + Cross-Attention):图像特征做 Self-Attention,再 Cross-Attend 到固定的文本 embedding——文本是"旁观者",不随图像更新
- MMDiT:图像 token 和文本 token 拼在一起进同一个 Transformer block,文本和图像可以相互 Attend——文字和图像信息双向融合,文本理解大幅增强
8.2.1 文生图代表:FLUX 做了什么
FLUX(Black Forest Labs,2024)是目前开源文生图里效果最强的模型之一,12B 参数。它的技术选择几乎代表了当前主流的最佳实践:
DDPM 的核心问题是:噪声调度(noise schedule)定义的扩散路径是曲折的——加噪/去噪都沿着一条弯弯曲曲的概率轨迹走,需要很多步(通常 20~100 步)才能收敛到高质量图像。
Flow Matching 的思路:用"直线路径"替换"曲线路径"。
| 对比维度 | DDPM | Flow Matching(FLUX/SD3 采用) |
|---|---|---|
| 路径形状 | 曲线(马尔可夫链噪声过程) | 直线插值:$x_t = (1-t)\,x_0 + t\,\epsilon$ |
| 训练目标 | 预测每步噪声 $\epsilon$ | 预测"速度"向量场 $v = \epsilon - x_0$(直线方向) |
| 采样步数 | 通常 20~100 步 | 4~8 步即可(直线更好近似) |
| 理论基础 | 随机微分方程(SDE) | 常微分方程(ODE),路径确定、可逆 |
直觉:DDPM 像走迷宫(每步只走一小步,路径弯曲);Flow Matching 像走直线(知道起点和终点,直接连线,速度快得多)。
FLUX 和 SD3 一样采用 MMDiT 双流架构,但做了进一步优化:
原始图像经 VAE 压缩到 16× 下采样的隐空间(如 $1024×1024$ → $64×64×16$),再切成 $2×2$ patch → 每张图变成 $32×32=1024$ 个 image token
T5-XXL(4096维)负责语义理解(长文本、复杂关系);CLIP(768维)负责视觉-语言对齐。两者 concat 后得到 text token 序列
前半段:image token 和 text token 各自有独立的参数,但在 attention 时拼在一起——图文信息双向流动,各自保留独立表示。后半段:图文 token 合并成一条序列,共享参数做 Full Attention,深度融合
把时间步 $t$ 和全局 CLIP embedding 用 MLP 映射成缩放/偏移参数,注入每个 Transformer block 的 LayerNorm 中——替代 U-Net 里的 ResBlock 时间嵌入
- 文本理解:T5-XXL(110亿参数的语言模型)vs CLIP-ViT-L(4亿参数)——SD1.x 靠 CLIP,写复杂 prompt 经常"读不懂";FLUX 的 T5 能理解长句、多属性、空间关系
- 全局一致性:双流 MMDiT 的 Full Attention 让每个图像 token 都能看到所有文字 token,文本与图像区域精准绑定;SD1.x 的 Cross-Attention 是"逐层插入",信息流不完整
- 细节质量:Flow Matching 路径更平滑,梯度估计更准确,手指/文字等细节错误大幅减少
8.3 现代文生视频:从 U-Net 到 3D DiT
视频生成的难点:除了空间维度(H×W),还有时间维度(T 帧),需要同时建模空间一致性(每帧的图像质量)和时序一致性(帧间运动流畅)。
- 卷积的感受野是局部的,帧间的长距离时序依赖很难捕捉
- 原始 U-Net 没有时间维度,需要额外加 temporal attention 层,结构复杂
- U-Net 的跳跃连接在 3D(T×H×W)上显存开销极大
现代文生视频的主流范式:3D DiT + 隐空间
用 3D VAE(含时间维度的 VAE)把视频从像素空间 $(T \times H \times W \times 3)$ 压缩到隐空间 $(T' \times H' \times W' \times C)$,大幅降低计算量
把 3D 隐向量切成时空 patch(如 $2 \times 2 \times 2$ 的小块),每块是一个 token——空间和时间都被统一成 token 序列
Transformer 在所有时空 token 上做 Full Attention(或分解的 Spatial + Temporal Attention),同时建模帧内空间关系和帧间时序关系
和图像生成一样:文本 token(T5 / LLM 编码)通过 Cross-Attention 或双流 Attention 注入,每步去噪都受文本引导
| 模型 | 机构 | 年份 | 架构 | 核心特点 |
|---|---|---|---|---|
| Sora | OpenAI | 2024 | 3D DiT(spacetime patches) | 统一图像/视频为 patch token,可变时长/分辨率,60秒高质量视频 |
| CogVideoX | 智谱 | 2024 | 3D DiT + Expert Transformer | 开源;3D VAE + Expert AdaLN;视频文本双流融合 |
| HunyuanVideo | 腾讯 | 2024 | 3D DiT(双流+单流混合) | 开源;13B参数;图像/视频统一训练;full attention |
| Wan2.1 | 阿里 | 2025 | 3D DiT + Flow Matching | 开源;14B;支持文生视频/图生视频;中文 prompt 友好 |
把视频看成"时空 patch 的序列",和 LLM 把文本看成"token 序列"是同一个范式——生成视频 = 在 token 序列上做扩散,而不是逐帧生成。这样模型天然能建模帧间一致性,也能任意扩展时长和分辨率。
类比 LLM:GPT 不是"逐词独立生成",而是在整个 token 序列上建模上下文。Sora 也不是"逐帧独立生成",而是在整个时空 token 序列上建模一致性。
8.3.1 文生视频代表:Wan2.1 做了什么
Wan2.1(阿里,2025)是目前开源文生视频里效果最强的模型,14B 参数。其架构设计是 3D DiT + Flow Matching 路线的集大成者,也是目前工业界可落地的最佳开源方案之一。
Wan2.1 用因果 3D VAE压缩视频:空间下采样 8×(如 $480×832$ → $60×104$),时间下采样 4×(如 81 帧 → 21 帧),通道扩展到 16 维。"因果"意味着每帧只能看到过去的帧,和自回归 LLM 的 causal mask 思路类似,保证视频可以流式生成
把 3D 隐向量按 $2×2×1$(空间×空间×时间)切成 patch,每个 patch 是一个 token。$81$ 帧 $480×832$ 的视频最终变成约 $13000$ 个 token——数量远多于图像(一张 $1024×1024$ 约 $4096$ token),这也是为什么视频模型显存开销极大
Wan2.1 专门使用支持中英双语的 umt5-xxl 作为文本编码器,max_length=512,输出 text token 序列通过 Cross-Attention 注入每个 DiT block。这也是 Wan2.1 对中文 prompt 特别友好的核心原因
骨干是标准 Transformer(40层,hidden_dim=5120),在所有时空 token 上做 Full Self-Attention——每个 patch token 能"看到"所有帧的所有 patch,天然建模帧间一致性。训练目标用 Flow Matching(直线路径),推理只需 50 步左右即可得到高质量视频
以 Wan2.1 生成 81帧 480P 视频为例:
- 图像 token 数:约 13000 个(每次推理)
- Full Attention 的计算量:$O(N^2)$,即 $13000^2 \approx 1.7 \times 10^8$ 次 attention 运算/层
- 40 层 × 50 步 = 大量计算,这就是为什么生成一个视频需要 24GB+ 显存和数分钟时间
一些模型(如早期 AnimateDiff)会把 Attention 分解成 Spatial Attention(只在同一帧内)+ Temporal Attention(只在同一位置的不同帧间),牺牲全局建模能力来换速度。Wan2.1/HunyuanVideo 选择了 Full Attention,效果更好但更贵。
- 图生视频(I2V):把第一帧图像作为条件注入,生成以该图像为起点的视频——图像 token 和 noise token 一起输入 DiT
- 视频续写:给定视频前几秒,续生后续内容——已有帧作为 context token,新帧从噪声中去噪
- 可变分辨率/时长:因为是 token-based,不需要固定输入尺寸,只需在 position embedding 里编码时空坐标即可支持任意分辨率和时长
8.4 架构总结
像素空间,纯卷积
隐空间 + Cross-Attn
图像 patch → token
时空 patch → 视频
🎨 文生图
输入文本描述,输出对应图片
应用:艺术创作、游戏原画、广告设计
🖼️ 图生图
输入参考图+文本,输出风格转换后的图片
应用:照片转油画、白天转夜晚
🔧 Inpainting
图片+遮罩+文本,AI重新生成遮罩区域
应用:去除路人、修复破损照片
场景:照片里有路人抢镜
- 用画笔遮住路人区域
- 输入文本:"蓝天白云下的草地"
- AI自动填充该区域,完美融合背景
| 对比维度 | Diffusion | GAN | VAE |
|---|---|---|---|
| 生成质量 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐ |
| 训练稳定性 | ⭐⭐⭐⭐⭐ | ⭐⭐ | ⭐⭐⭐⭐ |
| 生成多样性 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐⭐ |
| 生成速度 | ⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
| 可控性 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐ |
生成速度慢:需要逐步去噪(通常50-1000步)
- Stable Diffusion生成一张图:1-5秒
- GAN生成一张图:0.1秒以内
解决方案:DDIM(减少到20-50步)、Consistency Models(1-2步)
11.1 为什么Diffusion能成功?
📐 理论扎实
有完善的概率论和统计物理支撑
🏋️ 训练稳定
不像GAN有模式崩溃问题
🎛️ 可控性强
文本、图像、姿态等多种条件可控
11.2 学习路线
阅读DDPM论文 + 跑通minimist代码 + 理解U-Net架构
微调Stable Diffusion(用LoRA) + 尝试ControlNet控制生成
研读Score-based models + 理解SDE/ODE形式化 + 探索采样优化
11.3 推荐资源
- DDPM (2020): arxiv.org/abs/2006.11239
- Stable Diffusion (2022): arxiv.org/abs/2112.10752
- CFG (2022): arxiv.org/abs/2207.12598