news 2026/4/17 10:00:31

可扩散模型(Diffusion Models)详解:从原理到应用

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
可扩散模型(Diffusion Models)详解:从原理到应用

使用MINIST实现的扩散模型可见diffusion_minist:基于扩散模型的MNIST手写数字生成项目 - AtomGit | GitCode

可扩散模型是近年来生成式 AI 领域的热门领域。与 GAN、VAE 等传统生成模型相比,它通过 “逐步加噪 - 逐步去噪” 的独特思路,实现了对复杂数据分布的精准建模。本文将从直观理解到数学原理,逐步解析可扩散模型的工作机制。

一、核心思想:从 “加噪” 到 “去噪” 的逆转游戏

可扩散模型的核心灵感来自物理学中的 “扩散过程”—— 就像一滴墨在水中逐渐扩散直至均匀混合,模型通过模拟 “数据→噪声” 的扩散过程,再学习逆转这个过程(“噪声→数据”),最终实现从随机噪声生成逼真数据的目标。

简单来说,它分为两个互补的过程:

  1. 前向扩散(Forward Diffusion):人为地、逐步地向清晰数据(如一张图片)中添加高斯噪声,直到数据完全变成随机噪声(类似 “墨水滴入水中” 的过程)。
  2. 反向扩散(Reverse Diffusion):训练一个神经网络学习 “去噪” 能力,从纯噪声出发,逐步移除噪声,最终恢复出清晰的数据(类似 “从浑浊水中还原墨水” 的逆过程)。

二、前向扩散:如何让数据 “变成” 噪声?

前向扩散是一个确定性的过程:我们按照预设的 “噪声调度表”,分 T 步向数据中添加噪声,最终让数据 x₀(如原始图片)变成近似标准正态分布的噪声 x_T。

1. 数学定义

设原始数据为 x₀(服从真实数据分布 p_data),前向扩散的每一步 t(从 1 到 T)都按如下规则添加噪声:

其中:

  • εₜ₋₁ 是服从标准正态分布的噪声(ε ~ 𝒩(0, I));
  • αₜ 是一个预设的 “保持系数”(通常在 0.995~1 之间),控制每一步保留的原始信息比例;
  • 为简化计算,定义累积系数 ᾱₜ = α₁・α₂・…・αₜ(ᾱ₀=1,ᾱ_T≈0)。

2. 直观理解

  • 初始时(t=0),x₀是清晰的原始数据(如一张猫的图片);
  • 随着 t 增大,xₜ中噪声比例逐渐增加(√(1-αₜ) 增大),原始信息比例逐渐减少(√αₜ减小);
  • 当 t=T 时,ᾱ_T≈0,x_T ≈ ε(几乎是纯噪声,肉眼无法分辨原始内容)。

这种设计的巧妙之处在于:任意 xₜ都可以直接由 x₀和噪声表示,无需逐步计算前序步骤。通过数学推导可得:
(其中 ε 是某一固定噪声)

这一性质极大简化了后续的反向扩散过程。

三、反向扩散:如何从噪声 “还原” 数据?

反向扩散是需要学习的过程:我们需要训练一个模型,从纯噪声 x_T 出发,逐步预测并移除噪声,经过 T 步后还原出清晰数据 x₀。

1. 核心挑战

反向扩散的每一步 t,需要从 xₜ推断出 xₜ₋₁。由于前向过程是确定的,理论上 xₜ₋₁的分布 p (xₜ₋₁|xₜ) 可由贝叶斯公式推导,但实际计算复杂。因此,可扩散模型通过近似建模解决这一问题。

2. 模型设计:预测噪声而非直接预测数据

可扩散模型的关键技巧是:不直接预测 xₜ₋₁,而是预测前向过程中添加的噪声 ε

具体来说,训练一个神经网络 ε_θ(xₜ, t)(θ 是模型参数,t 是当前步骤的 “时间编码”),输入是带噪声的数据 xₜ和步骤 t,输出是对前向过程中添加的噪声 ε 的预测。

为什么预测噪声?因为从 xₜ和预测的噪声 ε_θ,可以通过前向公式的逆运算反推出 xₜ₋₁:

其中 ϵt​ 是随机噪声(用于保留生成多样性),σₜ是预设的标准差(由 αₜ和ᾱₜ计算)。

3. 网络结构:U-Net 是主流选择

用于预测噪声的 ε_θ 通常采用U-Net 架构(如 Stable Diffusion),并结合以下关键设计:

  • 时间编码(Time Embedding):将步骤 t 转换为高维向量,输入网络以区分不同去噪阶段;
  • 注意力机制:在网络中间层加入自注意力或交叉注意力(如 Stable Diffusion 的文本引导生成),捕捉长距离依赖;
  • 残差连接:帮助深层网络训练,缓解梯度消失问题。

四、训练:如何让模型学会 “去噪”?

可扩散模型的训练过程异常简单,核心是最小化预测噪声与真实噪声的差异

1. 训练目标(损失函数)

随机采样:

  • 原始数据 x₀ ~ p_data;
  • 步骤 t ~ Uniform (1, T);
  • 噪声 ε ~ 𝒩(0, I)。

根据前向公式生成 xₜ = √ᾱₜ・x₀ + √(1-ᾱₜ)・ε,然后让模型 ε_θ(xₜ, t) 预测 ε,损失函数为:
L = 𝔼[x₀, t, ε] [ || ε - ε_θ(xₜ, t) ||² ]

预测噪声与真实噪声的均方误差(MSE)。这种简单的损失函数是可扩散模型训练稳定的重要原因(无需像 GAN 那样进行对抗训练)。

2. 训练过程

  1. 初始化网络 ε_θ(如 U-Net)和噪声调度表(α₁, α₂, ..., α_T);
  2. 迭代采样 x₀、t、ε,生成 xₜ;
  3. 计算模型预测的 ε_θ(xₜ, t) 与真实 ε 的 MSE 损失;
  4. 通过梯度下降更新网络参数 θ;
  5. 重复步骤 2-4 直至收敛。

五、采样:从噪声生成数据的过程

训练完成后,即可通过反向扩散过程生成新数据,步骤如下:

  1. 从标准正态分布采样初始噪声:x_T ~ 𝒩(0, I);
  2. 对 t 从 T 到 1 逐步迭代:
    • 用模型 ε_θ(xₜ, t) 预测噪声;
    • 根据 xₜ和预测噪声,通过逆公式计算 xₜ₋₁;
  3. 当 t=0 时,x₀即为生成的最终数据。

为加速采样(原始 T 通常取 1000,较慢),可采用 DDIM(Denoising Diffusion Implicit Models)等改进算法,将采样步数减少到 20-50 步,同时保持生成质量。

六、优势与应用

优势

  1. 生成质量高:能生成细节丰富、逼真度高的数据(如图像、视频);
  2. 训练稳定:基于 MSE 损失,无需对抗训练,不易崩溃;
  3. 易于控制:可通过条件输入(如文本、边缘图)引导生成方向(如 Stable Diffusion 的文本到图像)。

应用场景

  • 图像生成:文生图(DALL・E 2)、图生图(Stable Diffusion)、图像修复 / 超分;
  • 视频生成:如 Sora,通过时空扩散模型生成逼真视频;
  • 3D 建模:从文本生成 3D 模型;
  • 其他领域:语音合成、分子结构生成等。

七、代码示例

import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms from torch.utils.data import DataLoader import matplotlib.pyplot as plt import numpy as np # 1. 配置参数 device = torch.device("cuda" if torch.cuda.is_available() else "cpu") image_size = 28 # MNIST图像大小 channels = 1 # 灰度图像,通道数为1 batch_size = 128 epochs = 10 # 训练轮次 T = 1000 # 扩散步数 lr = 2e-4 # 2. 定义噪声调度(前向扩散的β参数) # β从较小值线性增加到较大值,控制每步加噪强度 betas = torch.linspace(0.0001, 0.02, T).to(device) alphas = 1.0 - betas alphas_cumprod = torch.cumprod(alphas, dim=0) # 累积乘积:α₁α₂...αₜ alphas_cumprod_prev = torch.cat([torch.tensor([1.0]).to(device), alphas_cumprod[:-1]]) # 3. 前向扩散过程:给图像添加噪声 def forward_diffusion(x0, t, noise=None): """ x0: 原始图像 (batch_size, channels, H, W) t: 时间步 (batch_size,) 返回:t步加噪后的图像和添加的噪声 """ if noise is None: noise = torch.randn_like(x0) # 生成标准正态噪声 # 从累积乘积中获取当前时间步的α值 sqrt_alphas_cumprod_t = torch.sqrt(alphas_cumprod[t])[:, None, None, None] sqrt_one_minus_alphas_cumprod_t = torch.sqrt(1.0 - alphas_cumprod[t])[:, None, None, None] # 前向扩散公式:xₜ = √ᾱₜ x₀ + √(1-ᾱₜ) ε xt = sqrt_alphas_cumprod_t * x0 + sqrt_one_minus_alphas_cumprod_t * noise return xt, noise # 4. 定义噪声预测网络(U-Net简化版) class SimpleUNet(nn.Module): def __init__(self, channels=1): super().__init__() # 时间步编码:将t转换为高维向量 self.time_mlp = nn.Sequential( nn.Linear(T, 128), nn.ReLU(), nn.Linear(128, 128) ) # 主干网络:简单卷积网络 self.conv1 = nn.Conv2d(channels + 128, 64, 3, padding=1) # 输入:图像+时间编码 self.conv2 = nn.Conv2d(64, 64, 3, padding=1) self.conv3 = nn.Conv2d(64, channels, 3, padding=1) # 输出噪声 self.relu = nn.ReLU() def forward(self, x, t): # 时间步编码:将t转换为独热向量后输入MLP t_emb = nn.functional.one_hot(t, num_classes=T).float() # (batch, T) t_emb = self.time_mlp(t_emb) # (batch, 128) # 将时间编码与图像拼接(在通道维度) t_emb = t_emb[:, :, None, None].repeat(1, 1, x.shape[2], x.shape[3]) # (batch, 128, H, W) x = torch.cat([x, t_emb], dim=1) # (batch, channels+128, H, W) # 卷积网络预测噪声 x = self.relu(self.conv1(x)) x = self.relu(self.conv2(x)) x = self.conv3(x) return x # 5. 训练函数 def train(batch_size): # 加载数据 transform = transforms.Compose([ transforms.ToTensor(), transforms.Normalize(0.5, 0.5) # 归一化到[-1, 1] ]) train_dataset = datasets.MNIST( root=r'C:\COMPUTER\python\计算机视觉\GAN\mnist data', train=True, download=True, transform=transform ) train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True) # 初始化模型、优化器 model = SimpleUNet().to(device) optimizer = optim.Adam(model.parameters(), lr=lr) criterion = nn.MSELoss() # 噪声预测用MSE损失 model.train() for epoch in range(epochs): total_loss = 0 for batch in train_loader: x0, _ = batch # 只需要图像,不需要标签 x0 = x0.to(device) batch_size = x0.shape[0] # 随机采样时间步 t = torch.randint(0, T, (batch_size,), device=device).long() # 前向扩散得到带噪声图像和真实噪声 xt, noise = forward_diffusion(x0, t) # 模型预测噪声 noise_pred = model(xt, t) # 计算损失并优化 loss = criterion(noise_pred, noise) optimizer.zero_grad() loss.backward() optimizer.step() total_loss += loss.item() avg_loss = total_loss / len(train_loader) print(f"Epoch {epoch + 1}/{epochs}, Average Loss: {avg_loss:.4f}") return model # 6. 采样函数(反向扩散:从噪声生成图像) def sample(model, num_samples=10): model.eval() with torch.no_grad(): # 从纯噪声开始 x = torch.randn(num_samples, channels, image_size, image_size).to(device) # 逐步去噪 for t in reversed(range(0, T)): t_tensor = torch.tensor([t] * num_samples, device=device).long() # 预测当前噪声 noise_pred = model(x, t_tensor) # 计算去噪所需参数 alpha_t = alphas[t] alpha_cumprod_t = alphas_cumprod[t] beta_t = betas[t] # 反向扩散公式:从xₜ计算xₜ₋₁ if t > 0: noise = torch.randn_like(x) else: noise = torch.zeros_like(x) # 最后一步不加噪声 x = (1 / torch.sqrt(alpha_t)) * ( x - ((1 - alpha_t) / torch.sqrt(1 - alpha_cumprod_t)) * noise_pred ) + torch.sqrt(beta_t) * noise # 转换为可显示的图像格式 x = x.cpu().numpy() x = (x + 1) / 2 # 从[-1,1]转回[0,1] return x # 7. 执行训练并生成样本 if __name__ == "__main__": model = train(batch_size) samples = sample(model, num_samples=10) # 显示生成的图像 plt.figure(figsize=(10, 2)) for i in range(10): plt.subplot(1, 10, i + 1) plt.imshow(samples[i].squeeze(), cmap="gray") plt.axis("off") plt.show()

八、总结

可扩散模型通过 “前向加噪 - 反向去噪” 的思路,实现了对复杂数据分布的精准建模。其核心是用简单的噪声预测任务替代直接的数据生成,通过 U-Net 等网络学习去噪能力,最终从随机噪声中 “生长” 出逼真数据。

尽管采样速度较慢(需多步迭代),但其生成质量和训练稳定性使其成为当前生成式 AI 的主流技术。随着加速算法的发展(如 DDIM、Flash Diffusion),可扩散模型的应用场景还在不断扩展,未来有望在更多领域展现潜力。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/17 10:00:18

IPD实战—需求管理(OR)流程的五大关键步骤解析

1. 需求管理为什么是IPD的第一道门槛 第一次接触IPD体系时,很多人会疑惑为什么要把需求管理放在最前面。我刚开始带团队做智能硬件开发时也犯过错误——直接让工程师照着竞品开干,结果产品上市后用户根本不买单。后来才明白,需求管理就像盖房…

作者头像 李华
网站建设 2026/4/17 9:59:25

Windows激活终极解决方案:KMS_VL_ALL_AIO完整使用指南

Windows激活终极解决方案:KMS_VL_ALL_AIO完整使用指南 【免费下载链接】KMS_VL_ALL_AIO Smart Activation Script 项目地址: https://gitcode.com/gh_mirrors/km/KMS_VL_ALL_AIO 还在为Windows系统激活问题烦恼吗?KMS_VL_ALL_AIO智能激活脚本为你…

作者头像 李华
网站建设 2026/4/17 9:58:21

网盘直链下载助手终极指南:告别限速的完整解决方案

网盘直链下载助手终极指南:告别限速的完整解决方案 【免费下载链接】Online-disk-direct-link-download-assistant 一个基于 JavaScript 的网盘文件下载地址获取工具。基于【网盘直链下载助手】修改 ,支持 百度网盘 / 阿里云盘 / 中国移动云盘 / 天翼云盘…

作者头像 李华
网站建设 2026/4/17 9:57:18

小玩意 - 红包算法揭秘(公平分配 vs 先到先得)

1. 红包算法的两种江湖:公平与手速的终极对决 每次群里发红包,总有人抱怨"又没抢到大包",也有人得意"今天手气不错"。但你知道吗?红包金额的分配背后藏着精妙的数学设计。就像切蛋糕,有人追求每块…

作者头像 李华
网站建设 2026/4/17 9:53:42

AcadHomepage自定义开发教程:从基础布局到高级功能扩展

AcadHomepage自定义开发教程:从基础布局到高级功能扩展 【免费下载链接】acad-homepage.github.io AcadHomepage: A Modern and Responsive Academic Personal Homepage 项目地址: https://gitcode.com/gh_mirrors/ac/acad-homepage.github.io AcadHomepage是…

作者头像 李华
网站建设 2026/4/17 9:52:31

从数据混乱到决策清晰:2025年数据工程必备开源工具实战指南

从数据混乱到决策清晰:2025年数据工程必备开源工具实战指南 【免费下载链接】data-engineer-handbook This is a repo with links to everything youd ever want to learn about data engineering 项目地址: https://gitcode.com/GitHub_Trending/da/data-enginee…

作者头像 李华