扩散模型为什么用 U-Net?时间步 t 是怎么注入网络的?
简化版
扩散模型的去噪网络传统上用 U-Net,因为去噪任务的输入输出同尺寸(都是图像/潜图),而 U-Net 的「编码器下采样 + 解码器上采样 + 跳跃连接」结构天然适合这种密集预测:下采样抓全局语义,跳连保住高频细节,输出和输入对齐。时间步 t 则通过正弦位置编码 → MLP → 时间嵌入,再加到 U-Net 每个残差块的特征里(或用它生成缩放/偏移去调制特征),让网络知道「当前噪声有多大、该去多少噪」。文本条件另走交叉注意力注入。
详细版
为什么是 U-Net
- 输入输出同形:去噪要从
x_t预测同尺寸的噪声ε,是典型的「图到图」密集预测,U-Net 正为此设计。 - 多尺度感受野:下采样让深层看到全局结构(物体、布局),上采样逐步恢复分辨率。
- 跳跃连接:把编码器每个尺度的特征直接接到解码器对应尺度,保留高频细节,避免下采样丢失的纹理无法恢复——这对生成清晰图像至关重要。
U-Net 里的关键模块
- 残差块(ResBlock):卷积 + 归一化 + 残差,主力特征提取;时间嵌入在这里注入。
- 自注意力块:在中低分辨率层加入,让空间位置间做全局交互(卷积只有局部感受野,注意力补全局)。
- 交叉注意力块:注入文本条件(文生图)。
- 下采样/上采样:改变分辨率。
时间步注入三步
1) t → 正弦位置编码 → 得到高维向量
2) → 小 MLP → 时间嵌入 t_emb
3) 在每个 ResBlock 内:把 t_emb 加到特征上(或生成 scale/shift 调制)
为什么每个块都要注入 t
不同噪声水平下,网络该做的事很不一样(高噪声步管大结构,低噪声步修细节)。让每一层都知道 t,网络才能按噪声水平自适应地调整行为。
完整版教学
一、先想清楚去噪网络的”任务形状”
扩散网络的输入是带噪图 x_t(H×W×C),输出是同样大小的噪声预测 ε(H×W×C)。这是一个输入输出同分辨率的密集预测任务——每个像素都要有输出。这类任务(分割、去噪、超分)的黄金结构就是 U-Net。所以「为什么用 U-Net」的第一层答案是:任务形状决定的。
二、U-Net 三大件各自解决什么
① 下采样编码器——获取全局语义 卷积的感受野是局部的。只有逐级下采样(分辨率减半、通道加倍),深层神经元才能「看到」足够大的区域,理解整体结构(这是猫还是狗、物体在哪)。没有下采样,网络只见树木不见森林。
② 上采样解码器——恢复分辨率 预测的噪声必须和输入同尺寸,所以要把下采样压缩的特征一步步上采样回原分辨率。
③ 跳跃连接——挽救高频细节(U-Net 的精髓) 下采样是有损的:边缘、纹理这些高频信息压没了,光靠上采样补不回来。跳连把编码器每个尺度的高分辨率特征直接横跨接到解码器同尺度,等于给解码器「作弊小抄」,让它既有深层语义又有浅层细节。去噪高度依赖细节还原,所以跳连对扩散尤其关键。
记忆图景:U 的左半边「看懂整体」,右半边「重建细节」,中间横线(跳连)「把细节抄过去」。
三、为什么还要往 U-Net 里塞注意力
纯卷积 U-Net 只有局部感受野,难以建模「相距很远的两个区域要协调一致」(比如画面左右两只眼睛要对称、风格要统一)。于是在中低分辨率层插入自注意力,让所有空间位置两两交互,补上全局一致性。放在低分辨率是因为注意力是 O(N²) 复杂度,高分辨率算不起。文生图再加交叉注意力注入文本。这也解释了扩散模型后来能顺势演化到「纯 Transformer(DiT)」——注意力早就是 U-Net 里的重要成分了。
四、时间步嵌入:把”第几步”翻译成网络听得懂的信号
网络必须知道当前处于哪个噪声水平,否则无法给出正确的去噪量。t 是个整数(1…1000),直接喂没意义,要先编码:
第一步,正弦位置编码:和 Transformer 位置编码同理,用不同频率的 sin/cos 把标量 t 映射成一个高维向量。好处是连续、平滑、不同 t 可区分,且对相近的 t 给出相近的编码。
第二步,MLP 投影:过一两层带激活的全连接,得到时间嵌入 t_emb,维度对齐特征通道。
第三步,注入每个 ResBlock:常见两种方式——
- 相加:把
t_emb(广播到空间维)直接加到特征图上。 - 调制(FiLM/scale-shift):用
t_emb生成一组(γ, β),对归一化后的特征做γ·feature + β。这种自适应调制通常比单纯相加更强,SD/DiT 都在用。
为什么要注入到每一层:去噪在不同 t 的策略天差地别——t 大时噪声铺天盖地,网络该专注「恢复大致结构」;t 小时图已接近清晰,该专注「精修细节」。只有让每个残差块都感知 t,网络才能在不同噪声水平下切换行为模式。
五、把一次前向串起来
输入: x_t (带噪潜图), t (时间步), c (文本)
1. t → 正弦编码 → MLP → t_emb
2. c → 文本编码器 → 文本嵌入
3. x_t 进入 U-Net:
编码器: [ResBlock(注入 t_emb) → (自注意力/交叉注意力) → 下采样] × N
中间块: ResBlock + 自注意力 + 交叉注意力
解码器: [上采样 → 拼接跳连特征 → ResBlock(注入 t_emb) → 注意力] × N
4. 输出: 预测噪声 ε_θ(x_t, t, c)
六、面试拆解算例
扩散题最好用一次加噪和去噪的小推演讲清楚。假设训练图像像素归一化后是 x0,第 500 个时间步的噪声强度很高,模型看到的是混合样本 xt,目标通常是预测噪声 epsilon。如果预测噪声误差很小,就能从 xt 反推出更接近干净图像的估计;如果误差在早期步骤积累,后面细节会一起漂。
xt = sqrt(alpha_bar_t) * x0 + sqrt(1 - alpha_bar_t) * epsilon
model(xt, t, condition) -> predicted_epsilon
x0_hat = (xt - sqrt(1 - alpha_bar_t) * predicted_epsilon) / sqrt(alpha_bar_t)
| 维度 | 训练阶段 | 采样阶段 | 面试要点 |
|---|---|---|---|
| 输入 | 干净图 + 随机噪声 | 随机噪声或潜变量 | 起点不同 |
| 目标 | 学会预测噪声/速度 | 逐步还原样本 | 目标一致 |
| 条件 | 文本、边缘、姿态等 | CFG/ControlNet 引导 | 控制方向 |
| 代价 | 大量图像训练 | 多步迭代推理 | 速度质量权衡 |
干净图 x0 -> 加噪 xt -> 模型估计噪声 -> 反推 x0_hat -> 下一步更清晰
| | | |
训练目标 时间步 t 条件控制 误差累积
所以回答「扩散模型为什么用 U-Net?时间步 t 是怎么注入网络的?」时,不要停在“从噪声生成图片”。要说明训练时为什么要加噪、模型到底预测什么、采样器怎样反推、条件信号如何改变方向,以及少步采样为什么会牺牲一部分稳定性。
七、常见误区与追问
- 误区:U-Net 输出的是去噪后的图。 输出的是噪声预测 ε(或 x₀/v),图像由采样公式反解。
- 误区:时间步只在入口注入一次。 应注入每个残差块,让全网感知噪声水平。
- 追问:跳跃连接为什么重要? 保留高频细节,去噪/生成清晰度强依赖它。
- 追问:注意力为什么放在低分辨率层? 注意力 O(N²),高分辨率计算爆炸;低分辨率语义已足够做全局交互。
- 追问:一定要用 U-Net 吗? 不是。近年 DiT(Diffusion Transformer) 用纯 Transformer 替代 U-Net,扩展性更好,是 SD3、Sora 的方向;但 U-Net 仍是理解扩散网络结构的基础。
- 追问:时间步编码和 Transformer 位置编码是一回事吗? 数学形式一样(正弦编码),但语义不同:一个编码「去噪步/噪声水平」,一个编码「序列位置」。
八、加强记忆
U-Net 记「同尺寸任务、三大件、注意力补全局」:去噪是输入输出同分辨率的密集预测,U-Net 用”下采样抓语义 + 上采样复原 + 跳连保细节”完美契合,再在低分辨率层加自注意力补全局一致、加交叉注意力注入文本。 时间步记「正弦编码 → MLP → 每个 ResBlock 调制」,核心原因是不同噪声水平要用不同去噪策略,所以全网都得知道 t。抓住「跳连保细节」和「t 逐层注入」两点,扩散网络的结构就通了——顺带也理解了它为何能平滑演化成纯注意力的 DiT。