0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

什么是Diffusion Model?Diffusion Model生成图像过程

jf_pmFSk4VX 来源:GiantPandaCV 作者:梁德澎 2022-11-29 15:34 次阅读

前言

最近 AI 绘图非常的火,其背后用到的核心技术之一就是 Diffusion Model(扩散模型),虽然想要完全弄懂 Diffusion Model 和其中复杂的公式推导需要掌握比较多的前置数学知识,但这并不妨碍我们去理解其原理。接下来会以笔者所理解的角度去讲解什么是 Diffusion Model。

什么是 Diffusion Model

前向 Diffusion 过程

Diffusion Model 首先定义了一个前向扩散过程,总共包含T个时间步,如下图所示:

52574dfc-6cdd-11ed-8abf-dac502259ad0.png

最左边的蓝色圆圈 x0 表示真实自然图像,对应下方的狗子图片。

最右边的蓝色圆圈 xT 则表示纯高斯噪声,对应下方的噪声图片。

最中间的蓝色圆圈 xt 则表示加了噪声的 x0 ,对应下方加了噪声的狗子图片。

箭头下方的 q(xt|xt-1) 则表示一个以前一个状态 xt-1 为均值的高斯分布,xt 从这个高斯分布中采样得到。

所谓前向扩散过程可以理解为一个马尔可夫链(见参考资料[7]),即通过逐步对一张真实图片添加高斯噪声直到最终变成纯高斯噪声图片。

那么具体是怎么添加噪声呢,公式表示如下:

52690ede-6cdd-11ed-8abf-dac502259ad0.png

也就是每一时间步的 xt 是从一个,以 1-βt 开根号乘以 xt-1 为均值,βt为方差的高斯分布中采样得到的。

其中βt, t ∈ [1, T] 是一系列固定的值,由一个公式生成。

在参考资料 [2] 中设置 T=1000, β1=0.0001, βT=0.02,并通过一句代码生成所有 βt 的值:

# https://pytorch.org/docs/stable/generated/torch.linspace.html
betas = torch.linspace(start=0.0001, end=0.02, steps=1000)

然后在采样得到 xt 的时候并不是直接通过高斯分布 q(xt|xt-1) 采样,而是用了一个重参数化的技巧(详见参考资料[4]第5页)。

简单来说就是,如果想要从一个任意的均值 μ 方差 σ^2 的高斯分布中采样

527bd122-6cdd-11ed-8abf-dac502259ad0.png

可以首先从一个标准高斯分布(均值0,方差1)中进行采样得到 ε,

然后 μ + σ·ε 就等价于从任意高斯分布中进行采样的结果。公式表示如下:

528e1e86-6cdd-11ed-8abf-dac502259ad0.png

接着回来看具体怎么采样得到噪声图片 xt呢,

52690ede-6cdd-11ed-8abf-dac502259ad0.png

也是首先从标准高斯分布中采样,接着乘以标准差再加上均值 ,伪代码如下:

# https://pytorch.org/docs/stable/generated/torch.randn_like.html
betas = torch.linspace(start=0.0001, end=0.02, steps=1000)
noise = torch.randn_like(x_0)
xt = sqrt(1-betas[t]) * xt-1 + sqrt(betas[t]) * noise

然后前向扩散过程还有个属性,就是可以直接从 x0 采样得到中间任意一个时间步的噪声图片 xt,公式如下:

52b05988-6cdd-11ed-8abf-dac502259ad0.png

其中的 αt 表示:

52c678a8-6cdd-11ed-8abf-dac502259ad0.png52db9580-6cdd-11ed-8abf-dac502259ad0.png

具体怎么推导出来的可以看参考资料[4] 第11页,伪代码表示如下:

betas = torch.linspace(start=0.0001, end=0.02, steps=1000)
alphas = 1 - betas
# cumprod 相当于为每个时间步 t 计算一个数组 alphas 的前缀乘结果
# https://pytorch.org/docs/stable/generated/torch.cumprod.html
alphas_cum = torch.cumprod(alphas, 0)
alphas_cum_s = torch.sqrt(alphas_cum)
alphas_cum_sm = torch.sqrt(1 - alphas_cum)

# 应用重参数化技巧采样得到 xt
noise = torch.randn_like(x_0)
xt = alphas_cum_s[t] * x_0 + alphas_cum_sm[t] * noise

通过上述的讲解,读者应该对 Diffusion Model 的前向扩散过程有比较清晰的理解了。

不过我们的目的不是要做图像生成吗?

现在只是从数据集中的真实图片得到一张噪声图,那具体是怎么做图像生成呢?

反向 Diffusion 过程

52f37876-6cdd-11ed-8abf-dac502259ad0.png

反向扩散过程 q(xt-1|xt, x0) (看粉色箭头)是前向扩散过程 q(xt|xt-1) 的后验概率分布。

和前向过程相反是从最右边的纯高斯噪声图,逐步采样得到真实图像 x0。

后验概率 q(xt-1|xt, x0) 的形式可以根据贝叶斯公式推导得到(推导过程详见参考资料[4]第12页):

531f14fe-6cdd-11ed-8abf-dac502259ad0.png

也是一个高斯分布。

其方差从公式上看是个常量,所有时间步的方差值都是可以提前计算得到的:

53344db0-6cdd-11ed-8abf-dac502259ad0.png

计算伪代码如下:

betas = torch.linspace(start=0.0001, end=0.02, steps=1000)
alphas = 1 - betas
alphas_cum = torch.cumprod(alphas, 0)
alphas_cum_prev = torch.cat((torch.tensor([1.0]), alphas_cum[:-1]), 0)
posterior_variance = betas * (1 - alphas_cum_prev) / (1 - alphas_cum)

然后看均值的计算,

534d6cb4-6cdd-11ed-8abf-dac502259ad0.png

对于反向扩散过程,在采样生成 xt-1 的时候 xt 是已知的,而其他系数都是可以提前计算得到的常量。

但是现在问题来了,在真正通过反向过程生成图像的时候,x0 我们是不知道的,因为这是待生成的目标图像。

好像变成了鸡生蛋,蛋生鸡的问题,那该怎么办呢?

Diffusion Model 训练目标

当一个概率分布q 求解困难的时候,我们可以换个思路(详见参考资料[5,6])。

通过人为构造一个新的分布 p,然后目标就转为缩小分布 p 和 q 之间差距。

通过不断修改 p 的参数去缩小差距,当 p 和 q 足够相似的时候就可以替代 q 了。

然后回到反向 Diffusion 过程,由于后验分布 q(xt-1|xt, x0) 没法直接求解。

52f37876-6cdd-11ed-8abf-dac502259ad0.png

那么我们就构造一个高斯分布 p(xt-1|xt)(见绿色箭头),让其方差和后验分布 q(xt-1|xt, x0) 一致:

53344db0-6cdd-11ed-8abf-dac502259ad0.png

而其均值则设为:

538d87cc-6cdd-11ed-8abf-dac502259ad0.png

和 q(xt-1|xt, x0) 的区别在于,x0 改为 xθ(xt, t) 由一个深度学习模型预测得到,模型输入是噪声图像 xt 和时间步 t 。

然后缩小分布 p(xt-1|xt) 和 q(xt-1|xt, x0) 之间差距,变成优化以下目标函数(推导过程详见参考资料[4]第13页):

53a923ba-6cdd-11ed-8abf-dac502259ad0.png

但是如果让模型直接从 xt 去预测 x0,这个拟合难度太高了,我们再继续换个思路。

前面介绍前向扩散过程提到,xt 可以直接从 x0 得到:

52b05988-6cdd-11ed-8abf-dac502259ad0.png53e010a0-6cdd-11ed-8abf-dac502259ad0.png

将上面的公式变换一下形式:

53f888b0-6cdd-11ed-8abf-dac502259ad0.png

代入上面 q(xt-1|xt, x0) 的均值式子中可得(推导过程详见参考资料[4]第15页):

54153d52-6cdd-11ed-8abf-dac502259ad0.png

观察上述变换后的式子,发现后验概率 q(xt-1|xt, x0) 的均值只和 xt 和前向扩散时候时间步 t 所加的噪声有关。

所以我们同样对构造的分布 p(xt-1|xt) 的均值做一下修改:

542f555c-6cdd-11ed-8abf-dac502259ad0.png

将模型改为去预测在前向时间步 t 所添加的高斯噪声 ε,模型输入是 xt 和 时间步 t:

544964f6-6cdd-11ed-8abf-dac502259ad0.png

接着优化的目标函数就变为(推导过程详见参考资料[4]第15页):

545cdf40-6cdd-11ed-8abf-dac502259ad0.png

然后训练过程算法描述如下,最终的目标函数前面的系数都去掉了,因为是常量:

54767ec8-6cdd-11ed-8abf-dac502259ad0.png

可以看到虽然前面的推导过程很复杂,但是训练过程却很简单。

首先每个迭代就是从数据集中取真实图像 x0,并从均匀分布中采样一个时间步 t,

然后从标准高斯分布中采样得到噪声 ε,并根据公式计算得到 xt。

接着将 xt 和 t 输入到模型让其输出去拟合预测噪声 ε,并通过梯度下降更新模型,一直循环直到模型收敛。

而采用的深度学习模型是类似 UNet 的结构(详见参考资料[2]附录B)。

训练过程的伪代码如下:

betas = torch.linspace(start=0.0001, end=0.02, steps=1000)
alphas = 1 - betas
alphas_cum = torch.cumprod(alphas, 0)
alphas_cum_s = torch.sqrt(alphas_cum)
alphas_cum_sm = torch.sqrt(1 - alphas_cum)

def diffusion_loss(model, x0, t, noise):
    # 根据公式计算 xt
    xt = alphas_cum_s[t] * x0 + alphas_cum_sm[t] * noise
    # 模型预测噪声
    predicted_noise = model(xt, t)
    # 计算Loss
    return mse_loss(predicted_noise, noise)

for i in len(data_loader):
    # 从数据集读取一个 batch 的真实图片
    x0 = next(data_loader)
    # 采样时间步
    t = torch.randint(0, 1000, (batch_size,))
    # 生成高斯噪声
    noise = torch.randn_like(x_0)
    loss = diffusion_loss(model, x0, t, noise)
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()

Diffusion Model 生成图像过程

模型训练好之后,在真实的推理阶段就必须从时间步 T 开始往前逐步生成图片,算法描述如下:

54a41496-6cdd-11ed-8abf-dac502259ad0.png

一开始先生成一个从标准高斯分布生成噪声,然后每个时间步 t,将上一步生成的图片 xt 输入模型模型预测出噪声。接着从标准高斯分布中采样一个噪声,根据重参数化技巧,后验概率的均值和方差公式,计算得到 xt-1,直到时间步 1 为止。

改进 Diffusion Model

文章 [3] 中对 Diffusion Model 提出了一些改进点。

对方差 βt 的改进

前面提到 βt 的生成是将一个给定范围均匀的分成 T 份,然后每个时间步对应其中的某个点:

betas = torch.linspace(start=0.0001, end=0.02, steps=1000)

然后文章 [3] 通过实验观察发现,采用这种方式生成方差 βt 会导致一个问题,就是做前向扩散的时候到靠后的时间步噪声加的太多了。

这样导致的结果就是在前向过程靠后的时间步,在反向生成采样的时候并没有产生太大的贡献,即使跳过也不会对生成结果有多大的影响。

接着论文[3] 中就提出了新的 βt 生成策略,和原策略在前向扩散的对比如下图所示:

54c0ab74-6cdd-11ed-8abf-dac502259ad0.png

第一行就是原本的生成策略,可以看到还没到最后的时间步就已经变成纯高斯噪声了,

而第二行改进的策略,添加噪声的速度就慢一些,看起来也更合理。

54e9d8be-6cdd-11ed-8abf-dac502259ad0.png

实验结果表明,针对 imagenet 数据集 64x64 的图片,原始的策略在做反向扩散的时候,即使跳过开头的 20% 的时间步,都不会对指标有很大的影响。

然后看下新提出的策略公式:

551816ca-6cdd-11ed-8abf-dac502259ad0.png552d6d9a-6cdd-11ed-8abf-dac502259ad0.png

其中 s 设置为 0.008同时限制 βt最大值为 0.999,伪代码如下:

T = 1000
s = 8e-3
ts = torch.arange(T + 1, dtype=torch.float64) / T + s
alphas = ts / (1 + s) * math.pi / 2
alphas = torch.cos(alphas).pow(2)
alphas = alphas / alphas[0]
betas = 1 - alphas[1:] / alphas[:-1]
betas = betas.clamp(max=0.999)

对生成过程时间步数的改进

原本模型训练的时候是假定在 T个时间步下训练的,在生成图像的时候,也必须从 T 开始遍历到 1 。而论文 [3] 中提出了一种不需要重新训练就可以减少生成步数的方法,从而显著提升生成的速度。

这个方法简单描述就是,原来是 T 个时间步现在设置一个更小的时间步数 S ,将 S 时间序列中的每一个时间步 s 和 T时间序列中的步数 t 对应起来,伪代码如下:

T = 1000
S = 100
start_idx = 0
all_steps = []
frac_stride = (T - 1) / (S - 1)
cur_idx = 0.0
s_timesteps = []
for _ in range(S):
    s_timesteps.append(start_idx + round(cur_idx))
    cur_idx += frac_stride

接着计算新的 β ,St 就是上面计算得到的 s_timesteps:

5549d886-6cdd-11ed-8abf-dac502259ad0.png

伪代码如下:

alphas = 1 - betas
alphas_cum = torch.cumprod(alphas, 0)
last_alpha_cum = 1.0
new_betas = []
# 遍历原来的 alpha 前缀乘序列
for i, alpha_cum in enumerate(alphas_cum):
    # 当原序列 T 的索引 i 在新序列 S 中时,计算新的 beta
    if i in s_timesteps:
        new_betas.append(1 - alpha_cum / last_alpha_cum)
        last_alpha_cum = alpha_cum

简单看下实验结果:

5566a380-6cdd-11ed-8abf-dac502259ad0.png

关注画蓝线的红色和绿色实线,可以看到采样步数从 1000 缩小到 100 指标也没有降多少。







审核编辑:刘清

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 图像处理
    +关注

    关注

    26

    文章

    1224

    浏览量

    55823

原文标题:一文弄懂 Diffusion Model

文章出处:【微信号:GiantPandaCV,微信公众号:GiantPandaCV】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    基于扩散模型的图像生成过程

    等很难用文本指定。   最近,谷歌发布了MediaPipe Diffusion插件,可以在移动设备上运行「可控文本到图像生成」的低成本解决方案,支持现有的预训练扩散模型及其低秩自适应(LoRA)变体 背景知识 基于扩散模型的
    的头像 发表于 07-17 11:00 2108次阅读
    基于扩散模型的<b class='flag-5'>图像</b><b class='flag-5'>生成</b><b class='flag-5'>过程</b>

    Stable Diffusion的完整指南:核心基础知识、制作AI数字人视频和本地部署要求

    的,其目的是消除对训练图像的连续应用高斯噪声,可以将其视为一系列去噪自编码器。Stable Diffusion由3个部分组成:变分自编码器(VAE)、U-Net和一个文本编码器。添加和去除高斯噪声的过程
    的头像 发表于 09-18 10:06 1577次阅读
    Stable <b class='flag-5'>Diffusion</b>的完整指南:核心基础知识、制作AI数字人视频和本地部署要求

    PSpice如何利用Model Editor建立模拟用的Model

    PSpice 提供Model Editor 建立组件的Model,从组件供货商那边拿该组件的Datasheet,透过描点的方式就可以简单的建立组件的Model,来做电路的模拟。PSpice 如何利用
    发表于 03-31 11:38

    Stability AI开源图像生成模型Stable Diffusion

    Stable Diffusion 的很多用户已经公开发布了生成图像的样例,Stability AI 的首席开发者 Katherine Crowson 在推特上分享了许多图像。基于 AI
    的头像 发表于 09-21 15:37 2602次阅读

    从一个名为DDPM的模型说起

    DDPM模型,全称Denoising Diffusion Probabilistic Model,可以说是现阶段diffusion模型的开山鼻祖。不同于前辈GAN、VAE和flow等模型,di
    的头像 发表于 01-05 15:40 1211次阅读

    一文读懂Stable Diffusion教程,搭载高性能PC集群,实现生成式AI应用

    PC Farm、生成式AI和Stable Diffusion模型都是非常有用的工具和技术,可以帮助用户快速构建和管理计算机集群,生成高质量的数据和图像,提高模型的泛化能力和鲁棒性。
    的头像 发表于 05-01 07:47 1890次阅读
    一文读懂Stable <b class='flag-5'>Diffusion</b>教程,搭载高性能PC集群,实现<b class='flag-5'>生成</b>式AI应用

    基于Diffusion Probabilistic Model的医学图像分割

    MedSegDiff 在原版 DPM 的基础上引入了动态条件编码,增强 DPM 在医学图像分割上的分步注意力能力。
    的头像 发表于 05-04 18:14 3013次阅读
    基于<b class='flag-5'>Diffusion</b> Probabilistic <b class='flag-5'>Model</b>的医学<b class='flag-5'>图像</b>分割

    使用OpenVINO™在算力魔方上加速stable diffusion模型

    Stable Diffusion 是 stability.ai 开源的 AI 图像生成模型,实现输入文字,生成图像的功能。Stable
    的头像 发表于 05-12 09:10 947次阅读
    使用OpenVINO™在算力魔方上加速stable <b class='flag-5'>diffusion</b>模型

    优化 Stable Diffusion 在 GKE 上的启动体验

    Diffusion 等应运而生。Stable Diffusion 是一个文字生成图像Diffusion 模型,它能够根据给定任何文本输
    的头像 发表于 06-03 08:35 578次阅读

    树莓派能跑Stable Diffusion了?

    Stable Diffusion是一种文本到图像生成的大型深度学习模型,它可以根据文本的描述生成详细的图像,也可以用于其他任务,如
    的头像 发表于 07-26 11:46 1106次阅读

    Stable Diffusion的完整指南:核心基础知识、制作AI数字人视频和本地部署要求

    13400;i3 12100;i7 12700 ;i9 12900  在当今的数字时代,人工智能正在逐步改变人们的生活和工作方式。其中,Stable Diffusion作为一种深度学习技术,受到广泛关注。它能够通过对图像或视频进行处理,
    的头像 发表于 09-07 14:12 1432次阅读
    Stable <b class='flag-5'>Diffusion</b>的完整指南:核心基础知识、制作AI数字人视频和本地部署要求

    DDFM:首个使用扩散模型进行多模态图像融合的方法

    近来去噪扩散概率模型 Denoising diffusion probabilistic model (DDPM)在图像生成中获得很多进步,通过对一张noise-corrupted
    的头像 发表于 09-19 16:02 1518次阅读
    DDFM:首个使用扩散模型进行多模态<b class='flag-5'>图像</b>融合的方法

    NeurIPS 2023 | 扩散模型解决多任务强化学习问题

    扩散模型(diffusion model)在 CV 领域甚至 NLP 领域都已经有了令人印象深刻的表现。最近的一些工作开始将 diffusion model 用于强化学习(RL)中来解
    的头像 发表于 10-02 10:45 447次阅读
    NeurIPS 2023 | 扩散模型解决多任务强化学习问题

    Stability AI试图通过新的图像生成人工智能模型保持领先地位

    Stability AI的最新图像生成模型Stable Cascade承诺比其业界领先的前身Stable Diffusion更快、更强大,而Stable Diffusion是许多其他文
    的头像 发表于 02-19 16:03 431次阅读
    Stability AI试图通过新的<b class='flag-5'>图像</b><b class='flag-5'>生成</b>人工智能模型保持领先地位

    韩国科研团队发布新型AI图像生成模型KOALA,大幅优化硬件需求

    由此模型的核心在于其运用了“知识蒸馏”(knowledge distillation)技术,这使得开源图像生成工具Stable Diffusion XL可大幅缩小其规模。原Stable Dif
    的头像 发表于 03-01 14:10 218次阅读