【扩散模型系列·第一篇】扩散模型是什么:从加噪到去噪的直觉,以及为什么它能打败 GAN

作者:技术博主 | 更新时间:2026-05-20 | 阅读时长:约 20 分钟
系列:扩散模型从零到实战(共 8 篇)
环境:Python 3.12 + PyTorch 2.x + diffusers
标签扩散模型 DDPM 生成模型 深度学习 AI绘画 Stable Diffusion 去噪


在这里插入图片描述

🔥 写给谁看:用过 Stable Diffusion 生成过图片,但不知道它到底在干什么?听说过"扩散模型"但看论文一头雾水?本篇从最直观的物理直觉出发,不急着写公式,先把"扩散模型到底在做什么"讲清楚——加噪声容易,学会去噪声,就能生成任何东西。


系列规划

篇次 主题 状态
第一篇(本篇) 扩散模型是什么:从加噪到去噪的直觉
第二篇 数学基础:前向过程与马尔可夫链 即将发布
第三篇 反向过程:学习去噪 即将发布
第四篇 U-Net 架构:去噪网络的设计 即将发布
第五篇 DDIM:加速采样 即将发布
第六篇 条件生成:文本引导与 CFG 即将发布
第七篇 Stable Diffusion:潜在扩散模型 即将发布
第八篇 实战与前沿:LoRA、DreamBooth、FLUX 即将发布

目录


一、从一个物理现象说起

往一杯清水里滴一滴墨水。

最开始,墨水浓缩在一个点,信息极其丰富——清晰的轮廓、浓度分布、精确的位置。随着时间流逝,墨水慢慢扩散,颜色逐渐均匀,最终整杯水变成均匀的淡蓝色。

这个过程不可逆——你无法把均匀的蓝水"逆扩散"回一滴精确的墨滴。

扩散模型的核心问题就是:如果一个神经网络学会了这个"逆向扩散"过程,它能做什么?

答案是:它能从纯噪声(均匀的蓝水)中生成任意一张逼真的图像(精确的墨滴)

import torch
import numpy as np

# ── 直觉演示:图像的"前向扩散"(加噪声)过程 ────────────────

def add_noise(image: torch.Tensor, noise_level: float) -> torch.Tensor:
    """
    模拟前向扩散:往图像里掺入高斯噪声
    noise_level=0.0:原图不变
    noise_level=1.0:变成纯噪声
    """
    noise = torch.randn_like(image)
    # 扩散模型的混合方式:信号 + 噪声,两者的"功率"加起来=1
    noisy = (1 - noise_level) ** 0.5 * image + noise_level ** 0.5 * noise
    return noisy.clamp(-1, 1)


# 模拟一个简单图像(中心有亮点,像素级"墨滴")
x0 = torch.zeros(1, 1, 8, 8)
x0[0, 0, 3:5, 3:5] = 1.0

print("前向扩散过程:信号逐渐被噪声淹没")
print(f"{'噪声比例 t':^14} {'信号系数 √(1-t)':^18} {'噪声系数 √t':^16} {'信噪比 (dB)':^14}")
print("─" * 66)

for t in [0.0, 0.1, 0.3, 0.5, 0.7, 0.9, 1.0]:
    signal_coef = (1 - t) ** 0.5
    noise_coef  = t ** 0.5
    snr_db = 10 * np.log10((1 - t) / (t + 1e-9))
    print(f"  {t:^14.1f} {signal_coef:^18.4f} {noise_coef:^16.4f} {snr_db:^14.1f}")

print("\n→ t=1 时信号系数=0,原始图像信息完全消失,只剩纯高斯噪声")
print("→ 扩散模型要学的就是:从右往左读这张表(反向去噪)")

二、扩散模型的核心思想:两个过程

2.1 前向过程与反向过程

前向过程(人为定义,不需要学习):
  x₀ ──加噪──→ x₁ ──加噪──→ x₂ ──→ ... ──→ xₜ ──→ ... ──→ x_T
  原图          轻微噪声      更多噪声                          纯高斯噪声

反向过程(神经网络来学习):
  x_T ──去噪──→ ... ──→ xₜ ──→ ... ──→ x₁ ──去噪──→ x₀
  纯高斯噪声                                            生成的新图像

关键:两个过程的步数 T 完全相同(DDPM 取 T=1000)

训练阶段:给网络看大量真实图片,告诉它"这张图在第 t 步加了什么噪声",让它学会预测噪声

推理阶段:从纯随机噪声 x T ∼ N ( 0 , I ) x_T \sim \mathcal{N}(0, I) xTN(0,I) 出发,用训练好的网络一步步去除噪声,得到一张全新的逼真图像。

# 核心思想用伪代码表达

# ── 训练:教网络认识噪声 ─────────────────────────────────────
def train_one_step(denoising_net, real_image):
    t       = torch.randint(1, T + 1, (1,))   # 随机选时间步
    epsilon = torch.randn_like(real_image)     # 生成真实噪声 ε

    # 前向过程:直接从 x₀ 跳到 xₜ(关键技巧,下一篇详解)
    sqrt_ab    = sqrt_alphas_cumprod[t]        # √ᾱₜ(信号系数)
    sqrt_1mab  = sqrt_one_minus_alphas_cumprod[t]  # √(1-ᾱₜ)(噪声系数)
    xt = sqrt_ab * real_image + sqrt_1mab * epsilon   # xₜ = √ᾱₜ x₀ + √(1-ᾱₜ) ε

    # 让网络预测 xₜ 里的噪声是什么
    predicted_epsilon = denoising_net(xt, t)

    # 损失:预测的噪声 vs 真实的噪声(简单的 MSE!)
    loss = F.mse_loss(predicted_epsilon, epsilon)
    return loss

# ── 推理:从噪声一步步生成图像 ──────────────────────────────
def sample_image(denoising_net):
    x = torch.randn(1, C, H, W)           # 从纯噪声开始,x_T

    for t in reversed(range(1, T + 1)):   # t: T → T-1 → ... → 1
        t_tensor          = torch.tensor([t])
        predicted_noise   = denoising_net(x, t_tensor)  # 预测当前噪声
        x                 = one_step_denoise(x, predicted_noise, t)  # 去一点噪声

    return x                              # 生成完毕

2.2 为什么预测噪声而不是预测图像

直觉上,直接让网络预测"干净的图像 x 0 x_0 x0"更符合直觉,但预测噪声有三个优势:

① 目标分布简单:噪声 ϵ ∼ N ( 0 , I ) \epsilon \sim \mathcal{N}(0, I) ϵN(0,I) 是各向同性高斯分布,结构极其简单,而真实图像的分布极其复杂。

② 任务对称:训练时我们知道加了什么噪声(标准答案已知),这比"猜目标图像应该是什么"更确定。

③ 尺度均衡:高噪声时(t 大),预测 x 0 x_0 x0 相当于"长程预测",误差极大;预测 ϵ \epsilon ϵ 的量级不随 t 变化。


三、与 GAN、VAE 的对比:为什么扩散模型赢了

3.1 三驾马车的直觉对比

┌──────────────────────────────────────────────────────────────┐
│ GAN(生成对抗网络,2014)                                      │
│ 两个网络博弈:生成器骗判别器,判别器识别生成器               │
│ 优点:速度快(一次前向),已有高质量结果                       │
│ 缺点:训练极不稳定,模式崩溃(只生成少数几种图),            │
│       难以控制,调参痛苦                                       │
└──────────────────────────────────────────────────────────────┘

┌──────────────────────────────────────────────────────────────┐
│ VAE(变分自编码器,2013)                                      │
│ 编码器压缩图像到潜空间,解码器从潜空间重建图像               │
│ 优点:训练稳定,潜空间连续可插值                               │
│ 缺点:生成图像模糊(重建损失惩罚像素偏差,倾向于取平均)      │
└──────────────────────────────────────────────────────────────┘

┌──────────────────────────────────────────────────────────────┐
│ 扩散模型(DDPM,2020)                                         │
│ 渐进式去噪:纯噪声经过 T 步变成清晰图像                       │
│ 优点:质量极高,多样性好,训练稳定,理论严格                   │
│ 缺点:原始采样慢(1000步),后续 DDIM/一致性模型已大幅改善    │
└──────────────────────────────────────────────────────────────┘
# 三种模型推理代码对比(伪代码,感受"工作量"差异)

# GAN:一步完成,极快
def gan_generate(generator):
    z = torch.randn(1, 512)          # 随机噪声
    image = generator(z)             # 一次前向,完成
    return image                     # 耗时:~1ms

# VAE:采样 + 解码,也很快
def vae_generate(decoder):
    z = torch.randn(1, 256)          # 从标准正态采样
    image = decoder(z)               # 一次解码,完成
    return image                     # 耗时:~5ms

# 扩散模型:T 步迭代,慢但质量高
def diffusion_generate(denoiser, T=1000):
    x = torch.randn(1, 3, 512, 512)  # 从纯噪声开始

    for t in reversed(range(1, T+1)):    # 1000 步迭代!
        noise = denoiser(x, t)
        x     = remove_noise_one_step(x, noise, t)

    return x   # 耗时:原始 ~30s,DDIM 50步 ~1.5s,一致性模型 1步 ~0.1s

# FID 分数对比(ImageNet 256×256,越低越好)
fid_scores = {
    "BigGAN(GAN)":           6.95,
    "NVAE(VAE)":             51.67,
    "DDPM 原版(1000步)":      3.17,
    "ADM + 引导(改进版)":     4.59,
    "Stable Diffusion(LDM)":  1.59,
}

print("主流生成模型 FID 对比(越低 = 质量越好):")
print(f"{'模型':^30} {'FID ↓':^10}")
print("─" * 42)
for model, fid in sorted(fid_scores.items(), key=lambda x: x[1]):
    bar = "█" * int((10 - min(fid, 10)) * 2)
    print(f"  {model:28s}  {fid:6.2f}  {bar}")

3.2 扩散模型为什么能赢

2020 年:DDPM 论文发布,FID 超越当时所有 GAN(震惊学界)
2021 年:改进版 ADM + 分类器引导,质量进一步提升
2021 年底:DALL·E(OpenAI),文生图成为现实
2022 年:Stable Diffusion 开源,扩散模型彻底普及

扩散模型胜出的核心原因(技术角度):

① 训练目标简单清晰
   MSE 损失,没有 GAN 的对抗不稳定
   不存在"模式崩溃"问题

② 多样性天然保证
   每次采样加入随机性(从 N(0,I) 出发),
   不会像 GAN 那样只生成固定的几种图

③ 条件生成无缝集成
   文本/图像/语义都能通过注意力机制注入
   classifier-free guidance 让控制力极强

④ 数学理论严格
   变分下界(ELBO)提供了清晰的优化目标
   可以从概率论角度严格推导

四、DDPM:奠基之作的关键设计

DDPM(Denoising Diffusion Probabilistic Models)由 Ho et al. 于 2020 年在 NeurIPS 发表,是现代扩散模型的基石。

4.1 三个核心组件

import torch
import numpy as np

# ── 组件1:噪声调度(Noise Schedule)──────────────────────────
# 定义每步加多少噪声:β_t 从小到大,图像越来越"乱"
T = 1000

# 线性调度(DDPM 原版)
betas_linear = torch.linspace(1e-4, 0.02, T)

# 余弦调度(improved DDPM,低噪声阶段更平滑,效果更好)
def cosine_beta_schedule(T: int, s: float = 0.008) -> torch.Tensor:
    t      = torch.linspace(0, T, T + 1)
    f      = torch.cos((t / T + s) / (1 + s) * torch.pi / 2) ** 2
    alphas = f / f[0]
    betas  = 1 - alphas[1:] / alphas[:-1]
    return betas.clamp(1e-4, 0.9999)

betas_cosine = cosine_beta_schedule(T)

# 预计算关键统计量(训练推理都会用到)
def precompute_schedule(betas: torch.Tensor) -> dict:
    alphas          = 1.0 - betas                     # αₜ = 1 - βₜ
    alphas_cumprod  = torch.cumprod(alphas, dim=0)    # ᾱₜ = ∏ αₛ
    return {
        "betas":                         betas,
        "alphas":                        alphas,
        "alphas_cumprod":                alphas_cumprod,
        "sqrt_alphas_cumprod":           alphas_cumprod.sqrt(),
        "sqrt_one_minus_alphas_cumprod": (1 - alphas_cumprod).sqrt(),
    }

sched = precompute_schedule(betas_linear)

# 展示噪声调度的关键时间步
print("DDPM 线性噪声调度的关键统计量:")
print(f"{'时间步 t':^10} {'ᾱₜ(信号²)':^14} {'√ᾱₜ(信号)':^14} {'√(1-ᾱₜ)(噪声)':^18}")
print("─" * 60)
for t in [1, 100, 250, 500, 750, 900, 999]:
    ab  = sched["alphas_cumprod"][t].item()
    sab = sched["sqrt_alphas_cumprod"][t].item()
    snb = sched["sqrt_one_minus_alphas_cumprod"][t].item()
    print(f"  {t:^10} {ab:^14.4f} {sab:^14.4f} {snb:^18.4f}")


# ── 组件2:前向加噪(解析公式,一步到位)──────────────────────
# 关键结论:不需要逐步加噪,可以从 x₀ 直接跳到任意 xₜ
# xₜ = √ᾱₜ · x₀  +  √(1-ᾱₜ) · ε,   ε ~ N(0, I)
# 这是训练高效的根本原因!

def q_sample(x0: torch.Tensor, t: torch.Tensor,
             sqrt_ab: torch.Tensor, sqrt_1mab: torch.Tensor):
    """前向过程:直接从 x₀ 得到 xₜ"""
    epsilon  = torch.randn_like(x0)
    # 提取第 t 个时间步的系数(广播到图像形状)
    sab  = sqrt_ab[t - 1].view(-1, 1, 1, 1)
    smab = sqrt_1mab[t - 1].view(-1, 1, 1, 1)
    xt   = sab * x0 + smab * epsilon
    return xt, epsilon   # 同时返回 xₜ 和真实噪声(训练需要)


# ── 组件3:训练损失(简化的 MSE)──────────────────────────────
# Ho 等人发现直接预测噪声 ε 比预测均值效果更好
# Loss = || ε  −  ε_θ(xₜ, t) ||²
# 其中 ε 是真实加的噪声,ε_θ 是网络预测的噪声

def compute_loss(denoiser, x0, t, sched):
    xt, epsilon        = q_sample(x0, t, sched["sqrt_alphas_cumprod"],
                                  sched["sqrt_one_minus_alphas_cumprod"])
    predicted_epsilon  = denoiser(xt, t)              # 网络预测
    loss               = torch.nn.functional.mse_loss(predicted_epsilon, epsilon)
    return loss

4.2 两个算法

Algorithm 1:训练(Training)

repeat:
  x₀ ← 从训练集随机采样一张图
  t  ← 从 {1,...,T} 均匀随机采样
  ε  ← N(0, I)  随机生成噪声
  执行梯度下降:最小化 ||ε − ε_θ(√ᾱₜ x₀ + √(1−ᾱₜ) ε, t)||²
until 模型收敛

Algorithm 2:采样(Sampling / 图像生成)

xₜ ← N(0, I)            从纯噪声开始
for t = T, T−1, ..., 1:
  z ← N(0,I)  if t>1  else  z=0
  εθ ← ε_θ(xₜ, t)      网络预测噪声
  xₜ₋₁ ← (xₜ − βₜ/√(1-ᾱₜ) · εθ) / √αₜ  +  √βₜ · z
return x₀

五、直觉理解:为什么去噪能生成图像

5.1 分而治之的力量

# 为什么要 1000 步而非 1 步直接生成?

print("一步生成 vs 多步去噪的本质区别:")
print()
print("一步生成(ill-posed):")
print("  N(0,I) → 图像  是多对多映射")
print("  同一个噪声向量理论上对应无穷多张图像")
print("  网络无法确定"应该"生成哪一张")
print()
print("多步去噪(well-posed):")
print("  每步任务:xₜ → xₜ₋₁")
print("  相邻步骤之间的分布差异很小")
print("  条件分布 p(xₜ₋₁|xₜ) 近似高斯,学起来容易")
print()

# 用数字感受"每步移动的距离"
T = 1000
betas = torch.linspace(1e-4, 0.02, T)
alphas_cumprod = torch.cumprod(1 - betas, 0)

print("每步平均去噪幅度(相邻 xₜ₋₁ 和 xₜ 的期望距离):")
print(f"{'时间步区间':^20} {'信号变化量':^16} {'每步移动幅度':^16}")
print("─" * 55)
checkpoints = [(999, 900), (900, 750), (750, 500), (500, 250), (250, 0)]
for t_hi, t_lo in checkpoints:
    delta = (alphas_cumprod[t_lo] - alphas_cumprod[t_hi]).abs().item()
    per_step = delta / (t_hi - t_lo)
    print(f"  t={t_hi:4d}{t_lo:4d}     {delta:^16.4f} {per_step:^16.6f}")

print("\n→ 每步只做微小调整,局部近似高斯,容易学习")
print("→ 1000 步小步走 = 将困难任务分解为 1000 个容易的子任务")

5.2 得分函数的视角

# 另一种理解:扩散模型在学习"往哪走才能接近真实数据"

print("得分函数(Score Function)的直觉:")
print()
print("  得分函数 s(x) = ∇_x log p(x)")
print("  含义:在数据空间的任意一点 x,指向'数据密度增大'的方向")
print()
print("  类比:你在一座山里迷路(纯噪声 = 荒野)")
print("       得分函数 = 指向人烟方向的指南针")
print("       每走一步都朝人多的方向走(高密度区域)")
print("       最终走到城市(真实图像分布)")
print()
print("  扩散模型的去噪网络 ε_θ(xₜ, t)")
print("  本质上是在学习不同噪声程度下的得分函数")
print("  ε_θ(xₜ, t) ∝ -s(xₜ, t)  (符号相反,方向一致)")
print()
print("  → 每步去噪 = 沿得分函数方向走一小步")
print("  → 1000 步后,从荒野(噪声)走到了城市(真实图像)")

5.3 训练数据的隐式编码

扩散模型不是"记忆"而是"理解":

传统方式:存图像数据库,检索时找最近邻
扩散模型:把"什么是真实图像"的统计规律压进网络权重

一个 DDPM(~100M 参数)训练在 ImageNet(~130GB 图像)上:
  没有记住任何一张具体图像
  而是学会了"像素排列的规律"

生成新图像时:
  从完全随机的噪声出发(覆盖所有可能)
  用学到的规律逐步"约束"这个随机噪声
  使其满足"真实图像"的统计特性
  最终得到的图像 = 不在训练集中的全新图像

这就是为什么扩散模型能"创作"而不只是"复制"

六、代码初体验:用 diffusers 感受扩散过程

# pip install diffusers transformers accelerate torch

import torch
import numpy as np
from diffusers import DDPMScheduler

# ── 体验1:噪声调度可视化 ────────────────────────────────────
def explore_noise_schedule():
    """直观感受图像是如何被噪声逐步淹没的"""

    scheduler = DDPMScheduler(
        num_train_timesteps=1000,
        beta_schedule="linear",
        beta_start=0.0001,
        beta_end=0.02,
    )

    ab = scheduler.alphas_cumprod.numpy()

    print("DDPM 线性噪声调度:图像信号随时间的衰减")
    print(f"{'时间步 t':^10} {'信号保留%':^14} {'噪声占比%':^14} {'视觉感受':^20}")
    print("─" * 62)

    visual_hints = {
        1:   "几乎未变化",
        100: "轻微颗粒感",
        250: "明显模糊",
        500: "勉强可辨",
        750: "基本看不出",
        900: "接近纯噪声",
        999: "纯高斯噪声",
    }

    for t, hint in visual_hints.items():
        signal_pct = ab[t] * 100
        noise_pct  = (1 - ab[t]) * 100
        print(f"  {t:^10} {signal_pct:^14.1f} {noise_pct:^14.1f} {hint:^20}")


# ── 体验2:手动跑一次"迷你扩散" ─────────────────────────────
def mini_diffusion_demo():
    """
    用极简代码演示扩散过程的本质
    不依赖真实神经网络,用随机预测演示框架
    """
    print("\n迷你扩散演示(10步,随机网络):")

    T = 10
    betas = torch.linspace(0.01, 0.5, T)
    alphas = 1.0 - betas
    alphas_cumprod = torch.cumprod(alphas, 0)
    sqrt_ab   = alphas_cumprod.sqrt()
    sqrt_1mab = (1 - alphas_cumprod).sqrt()

    # 模拟一个"图像"(1×1 像素,方便打印)
    x0 = torch.tensor([1.0])   # 原始信号

    # ── 前向过程 ──
    print("\n前向过程(加噪声):")
    for t in range(1, T + 1):
        epsilon = torch.randn(1)
        xt = sqrt_ab[t-1] * x0 + sqrt_1mab[t-1] * epsilon
        print(f"  t={t:2d}: x₀={x0.item():.3f} → x_{t}={xt.item():+.3f}  "
              f"(信号:{sqrt_ab[t-1].item():.3f}×x₀ + 噪声:{sqrt_1mab[t-1].item():.3f}×ε)")

    # ── 反向过程(用"完美预测"演示,真实情况由网络预测)──
    print("\n反向过程(去噪):假设网络完美预测噪声")
    xt = torch.randn(1)   # 从纯噪声出发
    print(f"  初始噪声: x_T = {xt.item():+.4f}")
    for t in reversed(range(1, T + 1)):
        # 真实场景:这里用神经网络预测 epsilon
        # 演示用:假设预测完全正确(epsilon=0,即往 x₀ 方向走)
        predicted_epsilon = torch.zeros(1)

        alpha     = alphas[t-1]
        beta      = betas[t-1]
        sqrt_a    = alpha.sqrt()
        sqrt_1mab_t = sqrt_1mab[t-1]

        # 反向均值公式(简化版)
        xt = (xt - beta / sqrt_1mab_t * predicted_epsilon) / sqrt_a
        if t > 1:
            xt = xt + beta.sqrt() * torch.randn(1) * 0.1  # 加少量随机性

        print(f"  t={t:2d}{t-1}: x_{t}={xt.item():+.4f}")

    print(f"\n  最终生成值: {xt.item():.4f}  (原始值: {x0.item():.3f})")
    print("  (真实网络训练后,会更准确地还原到数据分布附近)")


# ── 体验3:用 diffusers 真实感受推理流程 ────────────────────
def feel_the_inference_pipeline():
    """
    用 diffusers 跑一个真实的扩散过程
    展示 scheduler 如何管理每步的噪声系数
    """
    print("\n使用 diffusers DDPMScheduler 感受推理流程:")

    scheduler = DDPMScheduler(num_train_timesteps=1000)
    scheduler.set_timesteps(num_inference_steps=50)   # DDIM 加速:只用 50 步

    # 模拟 latent(真实模型中这是 VAE 的潜空间张量)
    latent = torch.randn(1, 4, 64, 64)   # 512×512 图像对应 64×64 的 latent

    print(f"初始 latent: shape={latent.shape}, "
          f"mean={latent.mean():.3f}, std={latent.std():.3f}")
    print()
    print(f"推理步骤(共 {len(scheduler.timesteps)} 步):")
    print(f"{'步骤':^6} {'时间步 t':^10} {'latent 均值':^14} {'latent 标准差':^14}")
    print("─" * 48)

    for i, t in enumerate(scheduler.timesteps):
        # 模拟网络预测(真实情况:这里输入 UNet)
        noise_pred = torch.randn_like(latent) * 0.1   # 假设预测了一个小噪声

        # scheduler 根据 t 计算去噪后的 latent
        latent = scheduler.step(noise_pred, t, latent).prev_sample

        if i % 10 == 0 or i == len(scheduler.timesteps) - 1:
            print(f"  {i:^6} {t.item():^10} {latent.mean().item():^14.4f} "
                  f"{latent.std().item():^14.4f}")

    print(f"\n最终 latent: mean={latent.mean():.3f}, std={latent.std():.3f}")
    print("(真实场景:最终 latent 送入 VAE 解码器 → 512×512 图像)")


# 运行所有演示
explore_noise_schedule()
mini_diffusion_demo()
feel_the_inference_pipeline()

七、能力边界与当前局限

7.1 扩散模型能做什么

capabilities = [
    ("无条件图像生成",   "DDPM / DDIM",          "从噪声→真实图像,无需提示词"),
    ("文本引导生成",     "Stable Diffusion / DALL·E", "自然语言描述→图像"),
    ("图像编辑",         "InstructPix2Pix / SDEdit", "修改图像局部内容"),
    ("图像超分辨率",     "SR3 / StableSR",        "低清→高清,细节修复"),
    ("图像修复",         "Stable Diffusion Inpaint","遮挡区域智能填充"),
    ("风格迁移",         "IP-Adapter / ControlNet", "保留内容,改变风格"),
    ("视频生成",         "Sora / CogVideo",       "文字→高质量视频"),
    ("音频/音乐生成",    "AudioLDM / MusicLDM",  "文字→音频片段"),
    ("3D 内容生成",      "DreamFusion / Zero123", "2D图像→3D模型"),
    ("分子/蛋白质设计",  "DiffSBDD / RFDiffusion", "药物分子/蛋白质结构"),
]

print("扩散模型的应用版图(2026年):")
print(f"{'应用领域':^18} {'代表模型':^26} {'能力描述':^32}")
print("─" * 80)
for domain, models, desc in capabilities:
    print(f"  {domain:16s}  {models:24s}  {desc}")

7.2 当前的局限与解决方向

局限1:采样速度(已大幅改善)
  DDPM 原版:1000 步 ≈ 30 秒(512×512,A100)
  DDIM:50 步 ≈ 1.5 秒
  一致性模型(2023):1-4 步 ≈ 0.1 秒  ← 接近 GAN 速度

局限2:训练成本(通过微调缓解)
  训练 Stable Diffusion:数百 GPU × 天 → 普通人做不到
  LoRA 微调:单卡 A100 × 几小时 → 大幅降低门槛
  DreamBooth:3-5 张图片 + 1小时 → 个人风格定制化

局限3:精确控制仍有困难
  "画面左边一只红猫,右边一只蓝狗" → 仍然困难
  ControlNet / IP-Adapter → 结构/外观控制大幅改善
  空间推理弱点仍在研究中

局限4:角色/风格一致性
  连续生成的多张图:人物/风格难保持一致
  InstantID、StoryDiffusion → 正在解决

局限5:幻觉问题
  文字渲染(diffusion 画文字往往模糊错误)
  FLUX、Ideogram → 文字质量显著提升

总结

三句话记住扩散模型的核心:

① 前向过程:把真实图像一步步变成纯噪声, T T T 步后变成 N ( 0 , I ) \mathcal{N}(0, I) N(0,I),人为定义,不需要学习。

② 训练:让神经网络学会"给定加了 t t t 步噪声的图,预测其中包含的噪声是什么",损失函数就是简单的 MSE。

③ 生成:从纯随机噪声出发,用训练好的网络一步步去噪, T T T 步后得到一张全新的逼真图像。

扩散模型统治生成领域的根本原因:训练稳定(无对抗训练)+ 质量极高(分步渐进去噪)+ 天然可控(条件生成注入自然)。

下一篇预告:数学基础——前向过程的马尔可夫链形式 q ( x t ∣ x t − 1 ) q(x_t|x_{t-1}) q(xtxt1),以及最关键的推导:为什么可以从 x 0 x_0 x0 直接跳到任意步 x t x_t xt(重参数化技巧),不需要逐步计算——这是训练高效的根本。


💬 你第一次接触扩散模型是通过 Stable Diffusion 生图,还是读论文? 欢迎评论区分享!

🙏 如果这篇帮到你,点赞 + 收藏,系列持续更新!


本文为原创技术分享。代码在 Python 3.12 + PyTorch 2.x + diffusers 0.27 下验证。最后更新:2026-05-20

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐