【人工智能】【深度学习】 ③ DDPM核心算法介绍:从噪声到图像的魔法

📖目录

  • [1. 前言:为什么需要DDPM?](#1. 前言:为什么需要DDPM?)
  • [2. 大白话解释:DDPM的"修复"过程](#2. 大白话解释:DDPM的"修复"过程)
  • [3. 核心数学原理](#3. 核心数学原理)
    • [3.1 扩散过程(前向过程)](#3.1 扩散过程(前向过程))
    • [3.2 去噪过程(反向过程)](#3.2 去噪过程(反向过程))
  • [4. DDPM算法流程详解](#4. DDPM算法流程详解)
  • [5. 代码实现(带详细注释)](#5. 代码实现(带详细注释))
  • [6. 网络架构图](#6. 网络架构图)
    • [6.1 DDPM网络架构表格展示](#6.1 DDPM网络架构表格展示)
    • [6.2 架构说明(大白话版)](#6.2 架构说明(大白话版))
    • [6.3 网络参数说明](#6.3 网络参数说明)
    • [6.4 优化建议](#6.4 优化建议)
  • [7. 生成模型对比分析](#7. 生成模型对比分析)
  • [8. DDPM的领域应用](#8. DDPM的领域应用)
    • [8.1 图像生成(Stable Diffusion)](#8.1 图像生成(Stable Diffusion))
    • [8.2 视频生成(Stable Video Diffusion)](#8.2 视频生成(Stable Video Diffusion))
    • [8.3 分子设计(Diffusion for Chemistry)](#8.3 分子设计(Diffusion for Chemistry))
  • [9. DDPM的优劣势分析](#9. DDPM的优劣势分析)
  • [10. 未来展望](#10. 未来展望)
  • [11. 结语](#11. 结语)

1. 前言:为什么需要DDPM?

在生成式AI领域,传统GAN(生成对抗网络)就像一个"画匠",试图直接画出逼真的图像,但往往容易"画歪"(模式崩溃)。而DDPM(Denoising Diffusion Probabilistic Models)则像一个"修复师",通过逐步去噪的方式,将随机噪声变成清晰图像。就像你把一张完美的照片慢慢划伤,再训练一个"修复师"把它恢复原状。

"GAN是直接画图,DDPM是慢慢修复图。"------这就是DDPM的核心思想。


2. 大白话解释:DDPM的"修复"过程

想象你有一张完美的照片(比如猫的图片),但不小心在上面划了道痕(噪声):

  1. 第一步:你慢慢加更多划痕,直到照片变成一团乱糟糟的噪声(扩散过程)
  2. 第二步:你训练一个"修复师"(神经网络),让他学会从噪声中恢复原图(去噪过程)

这就像:

  • 你把一张崭新的手机屏幕慢慢划伤,直到看不清内容
  • 然后你训练一个APP,能自动修复屏幕划痕,恢复原图

关键区别:DDPM不是直接生成图像,而是通过"去噪"过程,逐步从噪声中重建图像。


3. 核心数学原理

3.1 扩散过程(前向过程)

我们定义一个扩散过程,逐步向数据添加噪声:

q ( x t ∣ x t − 1 ) = N ( x t ; 1 − β t x t − 1 , β t I ) q(x_t|x_{t-1}) = \mathcal{N}(x_t; \sqrt{1-\beta_t}x_{t-1}, \beta_t\mathbf{I}) q(xt∣xt−1)=N(xt;1−βt xt−1,βtI)

其中:

  • x t x_t xt:第t步的噪声图像
  • β t \beta_t βt:第t步的噪声方差
  • N \mathcal{N} N:正态分布

大白话:这就像你把一张照片慢慢加噪,每一步都加一点点随机噪声。

推导:通过递推,我们可以得到任意时间步的噪声图像:

q ( x t ∣ x 0 ) = N ( x t ; α ˉ t x 0 , ( 1 − α ˉ t ) I ) q(x_t|x_0) = \mathcal{N}(x_t; \sqrt{\bar{\alpha}_t}x_0, (1-\bar{\alpha}_t)\mathbf{I}) q(xt∣x0)=N(xt;αˉt x0,(1−αˉt)I)

其中 α ˉ t = ∏ i = 1 t ( 1 − β i ) \bar{\alpha}t = \prod{i=1}^t(1-\beta_i) αˉt=∏i=1t(1−βi)

大白话 :我们不需要一步步加噪,可以直接从原始图像 x 0 x_0 x0 生成任意时间步的噪声图像 x t x_t xt。

3.2 去噪过程(反向过程)

训练一个神经网络 ϵ θ ( x t , t ) \epsilon_\theta(x_t, t) ϵθ(xt,t) 来预测噪声:

ϵ θ ( x t , t ) ≈ ϵ \epsilon_\theta(x_t, t) \approx \epsilon ϵθ(xt,t)≈ϵ

大白话:这个神经网络的任务是"从噪声图像中预测出添加的噪声"。

优化目标:最小化预测噪声与实际噪声的均方误差:

L = E t , x 0 , ϵ [ ∥ ϵ − ϵ θ ( x t , t ) ∥ 2 ] \mathcal{L} = \mathbb{E}{t, x_0, \epsilon}[\|\epsilon - \epsilon\theta(x_t, t)\|^2] L=Et,x0,ϵ[∥ϵ−ϵθ(xt,t)∥2]

推导:通过重参数化技巧,我们可以将损失函数写为:

L = E t , x 0 , ϵ [ ∥ ϵ − ϵ θ ( α ˉ t x 0 + 1 − α ˉ t ϵ , t ) ∥ 2 ] \mathcal{L} = \mathbb{E}{t, x_0, \epsilon}[\|\epsilon - \epsilon\theta(\sqrt{\bar{\alpha}_t}x_0 + \sqrt{1-\bar{\alpha}_t}\epsilon, t)\|^2] L=Et,x0,ϵ[∥ϵ−ϵθ(αˉt x0+1−αˉt ϵ,t)∥2]

大白话 :我们不需要知道原始图像 x 0 x_0 x0,只需要知道噪声图像 x t x_t xt 和时间步 t t t,就能预测出添加的噪声 ϵ \epsilon ϵ。


4. DDPM算法流程详解

原始图像 x0 添加噪声 逐步加噪 得到噪声图像 xt 训练去噪网络 预测噪声 从噪声恢复图像 生成新图像

  1. 前向扩散 :从原始图像 x 0 x_0 x0 逐步添加噪声,得到 x T x_T xT
  2. 训练 :训练神经网络 ϵ θ \epsilon_\theta ϵθ 预测添加的噪声
  3. 反向去噪 :从随机噪声 x T x_T xT 开始,逐步预测并去除噪声,得到 x 0 x_0 x0

5. 代码实现(带详细注释)

python 复制代码
import torch
import torch.nn as nn
import torch.optim as optim
import numpy as np
import matplotlib.pyplot as plt

# 1. 定义扩散过程的超参数
T = 1000  # 总扩散步数
beta = torch.linspace(0.0001, 0.02, T)  # 噪声方差序列
alpha = 1 - beta  # 每一步保留的图像比例
alpha_bar = torch.cumprod(alpha, dim=0)  # 累积乘积,用于直接计算任意时间步的噪声

# 2. 扩散过程:将原始图像x0添加噪声,得到xt
def forward_diffusion(x0, t):
    """
    将图像x0添加噪声,得到xt
    :param x0: 原始图像 [batch_size, channels, height, width]
    :param t: 时间步 [batch_size]
    :return: 添加噪声后的图像xt
    """
    # 从x0生成xt,使用公式 q(xt|x0) = N(sqrt(alpha_bar_t)x0, (1-alpha_bar_t)I)
    noise = torch.randn_like(x0)  # 生成随机噪声
    x_t = torch.sqrt(alpha_bar[t])[:, None, None, None] * x0 + torch.sqrt(1 - alpha_bar[t])[:, None, None, None] * noise
    return x_t

# 3. 训练目标:预测添加的噪声
class DenoiseNet(nn.Module):
    def __init__(self, input_channels=3, output_channels=3):
        super(DenoiseNet, self).__init__()
        # 一个简单的CNN,用于预测噪声
        self.model = nn.Sequential(
            nn.Conv2d(input_channels + 1, 64, kernel_size=3, padding=1),  # 输入:图像+时间步
            nn.ReLU(),
            nn.Conv2d(64, 64, kernel_size=3, padding=1),
            nn.ReLU(),
            nn.Conv2d(64, output_channels, kernel_size=3, padding=1)
        )
    
    def forward(self, x, t):
        """
        :param x: 当前时间步的图像 [batch_size, channels, height, width]
        :param t: 时间步 [batch_size]
        :return: 预测的噪声 [batch_size, channels, height, width]
        """
        # 将时间步转换为嵌入向量
        t_emb = torch.sin(t.float() * 10)[:, None]  # 简单的时间嵌入
        t_emb = t_emb.repeat(1, x.size(1))  # 扩展到与图像通道数相同
        
        # 将时间嵌入与图像拼接
        x_t = torch.cat([x, t_emb[:, :, None, None]], dim=1)
        
        # 通过神经网络预测噪声
        return self.model(x_t)

# 4. 训练循环
def train_denoise_net(model, dataloader, epochs=10):
    optimizer = optim.Adam(model.parameters(), lr=1e-3)
    for epoch in range(epochs):
        total_loss = 0
        for batch_idx, (x0, _) in enumerate(dataloader):
            # 随机选择时间步
            t = torch.randint(0, T, (x0.size(0),), device=x0.device)
            
            # 从x0添加噪声得到xt
            xt = forward_diffusion(x0, t)
            
            # 预测噪声
            pred_noise = model(xt, t)
            
            # 计算损失(预测噪声与实际噪声的均方误差)
            loss = nn.MSELoss()(pred_noise, torch.randn_like(xt))
            
            # 反向传播
            optimizer.zero_grad()
            loss.backward()
            optimizer.step()
            
            total_loss += loss.item()
        
        print(f"Epoch [{epoch+1}/{epochs}], Loss: {total_loss/len(dataloader):.4f}")
    
    return model

# 5. 生成新图像
def sample(model, num_samples=1, img_size=(3, 32, 32)):
    """
    从随机噪声生成新图像
    :param model: 训练好的去噪网络
    :param num_samples: 生成图像数量
    :param img_size: 图像尺寸
    :return: 生成的图像 [num_samples, channels, height, width]
    """
    # 从随机噪声开始
    x = torch.randn(num_samples, *img_size)
    
    # 从T步开始,逐步去噪
    for t in reversed(range(T)):
        # 将当前图像和时间步输入网络
        noise_pred = model(x, torch.tensor(t, device=x.device).repeat(num_samples))
        
        # 计算去噪后的图像
        x = (x - torch.sqrt(1 - alpha[t]) * noise_pred) / torch.sqrt(alpha[t])
        
        # 添加随机噪声(如果t>0)
        if t > 0:
            x += torch.sqrt(beta[t]) * torch.randn_like(x)
    
    return x

# 6. 实际使用示例(假设已训练模型)
# model = train_denoise_net(DenoiseNet(), dataloader)
# generated_image = sample(model)

6. 网络架构图

6.1 DDPM网络架构表格展示

模块名称 输入 处理步骤 输出 功能说明
输入层 x_t \\in \\mathbb{R}\^{C\\times H\\times W} 时间步 t \\in \\mathbb{N} - 接收当前时间步的噪声图像 - 接收时间步整数 t 噪声图像张量 x_t 时间步 t 提供去噪过程的基础输入
时间嵌入 时间步 t - 通过正弦函数生成1D嵌入:   t_{\\text{emb}} = \\sin(t \\times 10) - 扩展维度与图像通道对齐 时间嵌入向量 t_{\\text{emb}} \\in \\mathbb{R}\^{C\\times H\\times W} 将离散时间步转换为连续向量表示
特征拼接 x_t \< b r \> \ \ t_{\\text{emb}} - 在通道维度拼接:   x_{\\text{in}} = \[x_t, t_{\\text{emb}}\] 扩展输入张量 x_{\\text{in}} \\in \\mathbb{R}\^{(C+1)\\times H\\times W} 融合图像特征与时间信息
CNN去噪网络 x_{\\text{in}} - 3层卷积网络结构:  ① Conv2d(64) + ReLU  ② Conv2d(64) + ReLU  ③ Conv2d(3) + Linear 噪声预测 \\epsilon_{\\theta}(x_t, t) \\in \\mathbb{R}\^{3\\times H\\times W} 预测当前时间步的噪声分量
输出层 噪声预测 \\epsilon_{\\theta} - 通过反向过程公式计算:   x_{t-1} = \\frac{x_t - \\sqrt{1-\\alpha_t}\\epsilon_{\\theta}}{\\sqrt{\\alpha_t}} + \\sqrt{\\beta_t} \\cdot \\mathcal{N}(0, I) 重建图像 x_{t-1} 完成一步去噪操作

6.2 架构说明(大白话版)

模块 类比说明 技术细节
输入层 就像快递员拿着"破损包裹"和"破损程度说明" 接收带噪声的图像和当前时间步
时间嵌入 把"破损程度说明"翻译成机器能理解的语言 用正弦函数生成时间特征
特征拼接 把"破损包裹"和"破损说明"打包在一起 在通道维度拼接输入
CNN网络 像X光机扫描包裹,找出破损点 3层卷积网络提取特征
输出层 根据扫描结果修复包裹 使用反向过程公式生成修复图像

6.3 网络参数说明

参数类型 数量 示例
可训练参数 ~2.4M 3个Conv2d层权重
固定参数 β_t序列(1000个) 线性增长的噪声方差
激活函数 ReLU 2层使用ReLU激活
输入尺寸 3\\times H\\times W 通常为 3\\times 256\\times 256
输出尺寸 3\\times H\\times W 与输入尺寸一致

6.4 优化建议

优化方向 实现方式 效果
加速推理 使用DDIM加速 将1000步压缩到100步
提升质量 加深网络结构 使用UNet架构
内存优化 混合精度训练 减少显存占用
多模态扩展 添加文本编码器 支持文本到图像生成

7. 生成模型对比分析

模型类型 核心原理 大白话说明 使用领域 优势 劣势 使用普遍性 大模型时代用途
CNN 局部感受野 + 权值共享 "找特征"的扫描仪,像放大镜看局部 图像分类、目标检测 特征提取能力强 无法处理长距离依赖 作为基础模块用于视觉任务
RNN 时序记忆单元 "记流水账"的笔记本,记住前一步的信息 语言建模、序列预测 处理时序数据 梯度消失/爆炸 被Transformer取代
GAN 生成器 vs 判别器 "画匠"和"鉴宝师"的博弈 图像生成、风格迁移 生成质量高 训练不稳定 与扩散模型结合使用
DDPM 逐步去噪 "修复师"从噪声中还原图像 文本到图像、视频生成 生成质量极高 计算成本高 Stable Diffusion核心

8. DDPM的领域应用

8.1 图像生成(Stable Diffusion)

  • 优势:支持文本到图像生成,细节逼真
  • 案例:DALL·E 2、Midjourney v5
  • 公式:结合Transformer的CLIP编码器处理文本

8.2 视频生成(Stable Video Diffusion)

  • 优势:时空一致性好
  • 案例:Runway ML的Gen-2
  • 公式:扩展到3D张量处理时空信息

8.3 分子设计(Diffusion for Chemistry)

  • 优势:生成符合物理规则的分子
  • 案例:DeepMind的AlphaFold Diffusion
  • 公式:修改扩散过程以适应分子空间

9. DDPM的优劣势分析

特性 描述
优势 1. 生成质量极高 2. 理论保证收敛 3. 支持任意分布建模
劣势 1. 计算成本高(需1000步迭代) 2. 推理速度慢 3. 内存占用大
改进方案 1. DDIM加速(确定性去噪) 2. UNet结构优化 3. 混合Transformer架构

10. 未来展望

  1. 与Transformer结合:Stable Diffusion v5已使用Transformer作为UNet组件
  2. 多模态生成:文本+图像+语音联合生成
  3. 工业级优化:NVIDIA的TensorRT支持DDPM加速推理
  4. 科学应用:蛋白质结构预测、药物分子设计

11. 结语

DDPM通过"逐步去噪"的方式,实现了高质量的图像生成,避免了GAN常见的模式崩溃问题。它就像一个耐心的修复师,从完全混乱的噪声中,一点点恢复出清晰的图像。

"DDPM不是直接生成图像,而是通过'修复'噪声来生成图像。"

在实际应用中,DDPM已被用于生成高质量图像(如Stable Diffusion)、视频生成、分子设计等领域。其核心思想"逐步去噪"也启发了其他扩散模型(如DDIM)的发展。

下一篇预告:【人工智能】【深度学习】 ④ Stable Diffusion核心算法解析:从DDPM到文本生成图像的飞跃


本文为原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文链接及本声明。

相关推荐
h***01541 小时前
图解缓存淘汰算法 LRU、LFU | 最近最少使用、最不经常使用算法 | go语言实现
算法·缓存·golang
moonquakeTT1 小时前
雷达信号处理中的CFAR检测关键要点
人工智能·算法·目标跟踪·fmcw毫米波
元亓亓亓1 小时前
LeetCode热题100--34. 在排序数组中查找元素的第一个和最后一个位置--中等
数据结构·算法·leetcode
doris6101 小时前
带AI的设备管家:易点易动预测性维护功能太省心
人工智能
ManageEngineITSM1 小时前
把问题“消灭在未来”:IT 资产管理软件与问题管理的深度融合逻辑
大数据·运维·人工智能·itsm·工单系统
ComputerInBook1 小时前
理解数学概念——素数(质数)(prime)
算法·数论·质数·素数
说私域1 小时前
基于开源AI智能名片链动2+1模式S2B2C商城系统的生态微商运营研究
人工智能·开源
Mr.Winter`1 小时前
深度强化学习 | 基于PPO算法的移动机器人路径跟踪(附Pytorch实现)
人工智能·pytorch·深度学习·机器学习·机器人·自动驾驶·ros
旧梦吟1 小时前
脚本网页 推理游戏
算法·css3·html5·web app