问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

扩散模型:从噪声中重建艺术——图片生成的革命性技术

创作时间:
作者:
@小白创作中心

扩散模型:从噪声中重建艺术——图片生成的革命性技术

引用
CSDN
1.
https://m.blog.csdn.net/m0_65481401/article/details/144927135

扩散模型是近年来人工智能领域的一个突破性技术,它通过模拟物理中的扩散过程,从随机噪声中逐步生成清晰且细节丰富的图像。本文将带你深入了解扩散模型的工作原理、研究背景和实际应用,通过一个具体的图片生成案例,展示扩散模型如何从随机噪声中生成清晰的图片。

扩散模型的研究背景和意义

在生成模型的发展历程中,生成对抗网络(GAN)曾一度占据主导地位。然而,GAN 存在诸如模式崩塌、不稳定性等问题,限制了其在高质量图像生成中的表现。而扩散模型的出现,为生成模型带来了新的可能。

扩散模型的灵感来源于物理中的扩散过程:数据逐步被噪声污染,而模型的任务是通过逆扩散过程将噪声还原为清晰的图像。这种逐步去噪的方式,不仅提高了生成的稳定性,还使得模型在生成细节上表现得更加出色。

扩散模型的意义在于:

  1. 高质量生成:生成的图像细节丰富,质量媲美甚至超越 GAN。
  2. 训练稳定性:避免了 GAN 中的对抗训练问题。
  3. 广泛应用:从图像生成到修复、超分辨率、风格迁移等,扩散模型几乎无所不能。

研究现状

扩散模型最早由 Sohl-Dickstein et al. 在 2015 年提出,但直到 2020 年,Ho et al. 提出的 Denoising Diffusion Probabilistic Models (DDPM) 才使其成为主流。此后,扩散模型的研究迅速发展,出现了许多改进版本和应用:

  • DDPM (2020):提出了去噪扩散概率模型,奠定了扩散模型的基础。
  • Improved DDPM (2021):改进了采样效率,使生成速度显著提升。
  • Score-based Generative Models (2021):通过分数匹配(score matching)理解扩散过程,提出了统一的理论框架。
  • Latent Diffusion Models (LDM, 2022):结合潜在空间的扩散模型,大幅降低了计算成本。
  • Stable Diffusion (2022):基于 LDM 的文本到图像生成模型,成为当前最流行的扩散模型之一。

最新的论文

以下是扩散模型领域的几篇重要论文:

  1. Denoising Diffusion Probabilistic Models (Ho et al., 2020)
    论文链接
  2. Improved Denoising Diffusion Probabilistic Models (Nichol et al., 2021)
    论文链接
  3. Latent Diffusion Models (Rombach et al., 2022)
    论文链接
  4. Score-Based Generative Modeling through Stochastic Differential Equations (Song et al., 2021)
    论文链接

扩散模型在图片生成中的工作原理

扩散模型的核心过程可以分为两个阶段:正向扩散(Forward Diffusion)逆向生成(Reverse Generation)

1.正向扩散

在正向扩散过程中,模型从真实图像开始,逐步添加噪声,最终将图像转换为纯噪声。这个过程可以用以下公式表示:

其中,βt 是一个预定义的噪声调度参数,控制每一步添加的噪声量。

2.逆向生成

逆向生成是正向扩散的逆过程。模型从纯噪声开始,逐步去噪,最终生成一幅清晰的图像。逆向过程的核心是学习一个条件概率分布:

其中,μθ 和 Σθ 是通过神经网络学习得到的参数。

3.训练目标

扩散模型的训练目标是最小化去噪误差,即预测噪声的误差:

其中,ϵ是正向扩散过程中添加的噪声,ϵθ是模型预测的噪声。

一个具体的图片生成案例

我们以 CIFAR-10 数据集上的图片生成为例,展示扩散模型如何从随机噪声中生成清晰的图片。

数据集准备

CIFAR-10 是一个包含 10 类彩色图片的小型数据集,每张图片的分辨率为 32x32。我们将使用这个数据集来训练扩散模型。

扩散过程的实现

以下是扩散模型的核心实现代码:

import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import datasets, transforms
from torchvision.utils import save_image
import os

# 参数设置
image_size = 32
channels = 3
timesteps = 1000  # 扩散过程的时间步数
beta_start = 1e-4
beta_end = 0.02
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

# 生成噪声调度表
def linear_beta_schedule(timesteps):
    return torch.linspace(beta_start, beta_end, timesteps)

betas = linear_beta_schedule(timesteps).to(device)
alphas = 1.0 - betas
alphas_cumprod = torch.cumprod(alphas, axis=0)

# 正向扩散过程
def forward_diffusion_sample(x0, t, noise=None):
    if noise is None:
        noise = torch.randn_like(x0)
    sqrt_alpha_cumprod = torch.sqrt(alphas_cumprod[t])[:, None, None, None]
    sqrt_one_minus_alpha_cumprod = torch.sqrt(1 - alphas_cumprod[t])[:, None, None, None]
    return sqrt_alpha_cumprod * x0 + sqrt_one_minus_alpha_cumprod * noise, noise

# UNet 去噪网络
class UNet(nn.Module):
    def __init__(self):
        super(UNet, self).__init__()
        self.conv1 = nn.Conv2d(channels, 64, 3, padding=1)
        self.conv2 = nn.Conv2d(64, 64, 3, padding=1)
        self.conv3 = nn.Conv2d(64, channels, 3, padding=1)

    def forward(self, x, t):
        t_embedding = torch.sin(t).unsqueeze(-1).unsqueeze(-1)
        x = x + t_embedding
        x = F.relu(self.conv1(x))
        x = F.relu(self.conv2(x))
        x = self.conv3(x)
        return x

# 模型初始化
model = UNet().to(device)
optimizer = torch.optim.Adam(model.parameters(), lr=1e-4)

# 数据集加载
transform = transforms.Compose([
    transforms.ToTensor(),
    transforms.Normalize((0.5,), (0.5,))
])
dataset = datasets.CIFAR10(root='./data', train=True, transform=transform, download=True)
dataloader = torch.utils.data.DataLoader(dataset, batch_size=64, shuffle=True)

# 训练过程
def train(model, dataloader, optimizer, timesteps):
    model.train()
    for epoch in range(10):  # 训练 10 个 Epoch
        for x0, _ in dataloader:
            x0 = x0.to(device)
            t = torch.randint(0, timesteps, (x0.size(0),), device=device).long()
            x_t, noise = forward_diffusion_sample(x0, t)
            noise_pred = model(x_t, t)
            loss = F.mse_loss(noise_pred, noise)
            optimizer.zero_grad()
            loss.backward()
            optimizer.step()
        print(f"Epoch {epoch + 1}, Loss: {loss.item()}")

# 开始训练
train(model, dataloader, optimizer, timesteps)

# 生成图片
def sample(model, n_samples):
    model.eval()
    with torch.no_grad():
        x = torch.randn((n_samples, channels, image_size, image_size), device=device)
        for t in reversed(range(timesteps)):
            t_batch = torch.full((n_samples,), t, device=device, dtype=torch.long)
            predicted_noise = model(x, t_batch)
            beta_t = betas[t]
            alpha_t = alphas[t]
            alpha_cumprod_t = alphas_cumprod[t]
            x = (x - beta_t / torch.sqrt(1 - alpha_cumprod_t) * predicted_noise) / torch.sqrt(alpha_t)
        return x

# 生成并保存图片
generated_images = sample(model, n_samples=16)
save_image(generated_images, "generated_images.png", nrow=4)

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号