Skip to content

DDPM

上文我们介绍了扩散模型的核心思想,而DDPM作为首个将扩散模型具体实现的模型,自2020年论文发表以来就受到广泛应用,本文将对DDPM的原理和实现做具体说明。

公式介绍

首先我们对扩散模型加噪和去噪的噪声计算公式介绍,以便后续工作的展开。需要注意的是,本节内容更注重与模型的实现和架构逻辑,更详细的公式推导可参考本站后续附加文章。

前向加噪

模型训练时需要输入给定原始图像加噪后的数据,设原数据为x0,第t步加噪后的数据为xt,最终加噪完成的数据xT应为纯噪声数据。

我们假设随机噪声符合正态分布,即εt=N(0,1),加噪过程可以描述成均值为1βtxt1,方差为βtI的正态分布,I 代表单位矩阵:

q(xt|xt1)N(1βtxt1,βtI)

由此可以得到加噪迭代公式:

xt=αtxt1+βtεt;αt=1βt

迭代后推导出的加噪公式,即第t步加噪后的数据可表示为:

(1)xt=α¯tx0+1α¯tε,α¯t=Tαt

写成加噪分布的形式为:

q(xt|x0)N(sα¯tx0,(1α¯t)I)

反向去噪

Diffusion Model并不是直接由xt预测xt1,而是预测加在xt上的“噪声”,通过去噪得到xt1,这样做是兼顾 “训练效率、模型稳定性、生成多样性” 的最优选择。

反向过程则是从纯噪声xT 到真实数据 x0,这里反向分布公式可由贝叶斯定理推出:

(2)q(xt1|xt)=q(xt|xt1)q(xt1|x0)q(xt|x0)

该公式表示给定xt去求xt1,分子分母的三个分布在前向加噪中都已得到,分式的三个分布都是高斯分布,则q(xt1|xt)也必然是高斯分布。

  • 单步加噪分布,αt=1βtβt是单步噪声方差:
q(xt|xt1)N(αtxt1,(1αt)I)
  • x0xt1的累计加噪分布,α¯t1=i=1t1αi
q(xt1|x0)N(α¯t1x0,(1α¯t1)I)
  • x0xt的累计加噪分布,α¯t=i=1tαi
q(xt|x0)N(α¯tx0,(1α¯t)I)

将三式代入公式(2),推导出已知第t步时第s步的数据分布q(xt1|xt)的均值和方差,用角标表示条件分布。

均值

μt1|t=αt(1α¯t1)1α¯txt+α¯t1(1αt)1α¯tx0

方差

σt1|t=1α¯t11α¯t(1αt)I

这里的均值使用了参数x0,但在预测中我们并不预先知道,不然就不用预测了,所以我们要用xt来预测x0,由前向扩散公式 (1) 反解出x0,这里εt是第t步的真实噪声:

(3)x0=1α¯t(xt1α¯tεt)

将其代入反向分布的均值μt1|t中,用模型输出的预测噪声 εθ 近似真实噪声εt,得到反向去噪公式:

(4)xt1=1αt(xtβt1α¯tεθ(xt,t))+σtz

这里σt=1α¯t11α¯t(1αt)是噪声强度系数,zN(0,1)是随机噪声。

因此,利用该公式(4),针对模型每轮预测的噪声 εθ,都可以得到下一步的数据xt1

损失函数

DDPM 的损失函数是在所有时间步上对预测噪声与真实噪声的均方误差进行加权求和,公式如下:

LDDPM=Et,x0,ϵ[ϵϵθ(xt,t)2]=Et,x0,ϵ[ϵϵθ(α¯tx0+1α¯tε,t)2]

该公式是由变分推断一步步化简得到,具体的公式推导在此不做展开,同样可参考本站后续文章。

模型运行流程

训练

DDPM的单步训练示意图如下:

在每轮训练时,它随机选取时间步t,并从标准正态分布中采样得到噪声ϵ,根据前向加噪公式 (1) 计算得到含噪数据xt,把 txt 送入噪声预测网络,预测出加在数据中的噪声 ϵθ ,将预测噪声ϵθ和实际采样噪声 ϵ 计算损失函数,更新权重。以此往复训练,直至所有轮次结束。

推理

扩散模型的推理过程则是从正态分布中随机采样得到纯噪声XT,随后设置时间总步长T,将XTT送入噪声预测网络,逐步去噪,直至得到图像X0,示意图如下:

噪声预测网络

接下来我们讨论Diffusion Model预测噪声功能的核心部分,根据上述讨论,我们可以理解,扩散模型实际上还是一种神经网络,只不过该神经网络的输入数据经过处理,接收含噪数据和时间步,输出的预测数据也经过了处理得到去噪后数据,最常用的噪声预测网络是——Unet网络

对于它的具体框架我们在前文已做讨论,在此不做展开,只对其如何预测噪声进行说明,整个预测网络的计算流程如下示意图:

时间步嵌入

根据扩散模型的原理我们知道,在预测网络训练时需要输入当前的时间T,所谓时间步嵌入就是将标量T通过给定的数学公式转换为一个时间向量,再通过线性变换与图像数据输入融合,而上图的下半部分就是时间步向量生成和嵌入的具体示意图。

时序向量生成

我们首先定义一个计算公式将标量T得到时间向量,通常会选择基于正弦和余弦函数的位置编码来做时间步嵌入,其具体公式如下:

PE(t,2i)=sin(t10000k)PE(t,2i+1)=cos(t10000k)k=2idmodel

公式PE(t,x)表示时间步 t 对应的嵌入向量的第x个元素,x的取值范围是[0,dmodel1]。对于向量的偶数位元素使用sin计算,奇数位使用cos计算。

示例

我们想计算一个十一维嵌入向量第t=4时刻第5个元素的值,因为5是奇数,所以使用cos公式计算,且i=(51)2=2,代入:

k=2×211=411PE(4,5)=cos(410000(4/11))0.99015

对于一个维度是11的嵌入向量,我们可以计算出t0t9每个时间步对应的向量:

t_0:[0,	1,	0,	1,	0,	1,	0,	1,	0,	1,	0]
t_1:[0.841470985,	0.540302306,	0.18628711,	0.98249535,	0.035104703,	0.99938364,	0.006579285,	0.999978356,	0.001232846,	0.99999924,	0.000231013]
t_2:[0.909297427,	-0.416146837,	0.366052439,	0.930594225,	0.070166132,	0.99753532,	0.013158285,	0.999913426,	0.002465691,	0.99999696,	0.000462026]
t_3:[0.141120008,	-0.989992497,	0.533002529,	0.846113647,	0.105141066,	0.994457317,	0.019736715,	0.999805212,	0.003698532,	0.99999316,	0.000693039]
t_4:[-0.756802495,	-0.653643621,	0.681292572,	0.732011223,	0.13998639,	0.990153428,	0.026314291,	0.999653719,	0.004931367,	0.999987841,	0.000924052]
t_5:[-0.958924275,	0.283662185,	0.80573104,	0.592281598,	0.17465915,	0.984628956,	0.032890728,	0.999458954,	0.006164195,	0.999981001,	0.001155065]
t_6:[-0.279415498,	0.960170287,	0.901961427,	0.431816609,	0.209116605,	0.977890713,	0.039465741,	0.999220924,	0.007397013,	0.999972642,	0.001386077]
t_7:[0.656986599,	0.753902254,	0.966614776,	0.256234022,	0.243316277,	0.969947003,	0.046039046,	0.998939641,	0.00862982,	0.999962762,	0.00161709]
t_8:[0.989358247,	-0.145500034,	0.997427618,	0.071680862,	0.277216008,	0.960807621,	0.052610358,	0.998615116,	0.009862614,	0.999951363,	0.001848103]
t_9:[0.412118485,	-0.911130262,	0.993321218,	-0.115381796,	0.310774009,	0.950483832,	0.059179393,	0.998247364,	0.011095393,	0.999938444,	0.002079115]

通过绘图查看0~50时间步下嵌入向量前7个元素的分布,观察ti两个变量对数值的影响。

向量嵌入

在得到ti时刻的n维嵌入向量后,往往需要将其与图像数据嵌入,这个过程需要解决两组数据大小不一致和选用什么融合方法的两个问题。在扩散模型中,主要通过自适应归一化的方式将时间步向量注入到 UNet 网络。

实例归一化

对于输入的特征图 x ,假设其形状为 (N,C,H,W),其中 N 是批量大小, C 是通道数, H 和 W 分别是特征图的高度和宽度。实例归一化是对每个样本的每个通道分别计算均值 μn,c和方差 σn,c2,并进行归一化:

IN(x)n,c,h,w=xn,c,h,wμn,cσn,c2+ϵ

其中 ϵ是一个很小的常数,用于防止分母为零。

生成缩放和偏移因子

将时间步嵌入向量输入到一个多层感知机(MLP)中,经过变换输出与特征图通道数 C 相同维度的缩放因子 γ 和偏移因子 β ,即 [γ,β]=MLP(condition) 。

自适应调整

使用生成的缩放因子 γ 和偏移因子 β 对实例归一化后的特征图进行调整,得到最终经过 AdaIN 操作的特征图,在计算过程中,标量γiβi会利用广播机制与矩阵中的每一个值做乘法和加法:

AdaIN(x)n,c,h,w=γcIN(x)n,c,h,w+βc

上述利用自适应归一化方法进行时间步嵌入的示意图如下:

本示例中时间向量维度为10,上节点输入数据为[8,64,64]8通道,64×64大小图像,多层感知机输出节点为82=16,前八个节点作为缩放因子 [γ0,,γ7] ,后八个节点作为偏移因子 [β0,,β7] ,对输入的每一通道进行归一化后得到八个归一化后的矩阵[C0,,C7],最后将系数和矩阵相乘(广播机制),得到[γ0C0+β0,,γ7C7+β7],将其输入Unet的下一节点。

其他嵌入方法

除了常用的自适应归一化方法外,以下方法也可进行时间步嵌入:

简单相加

将嵌入向量通过线性层投影到与特征图相同的通道维度后,直接与特征图进行逐元素相加,将嵌入向量携带的信息叠加到网络特征上。

对时间步嵌入向量进行线性变换,使其维度与待融合的特征图通道数相同。例如,若特征图通道数为 C,嵌入向量维度为 D,则通过一个线性层 W(维度为 C×D)对嵌入向量进行变换,得到投影后的嵌入向量 proj(PE) 。将投影后的嵌入向量 proj(PE) 与特征图 x 进行逐元素相加,得到融合后的特征 xfused=x+proj(PE) 。其示意图如下:

优势:实现简单,计算量相对较小,能快速将嵌入向量的信息融入到网络特征中,在一些简单场景或对计算资源要求较高的情况下较为适用。

拼接

在通道维度上直接将嵌入向量与特征图拼接在一起,然后通过后续的卷积层等操作,让模型学习到嵌入向量和网络特征的联合表示。

同样先将嵌入向量通过线性层投影到合适的通道数,使其与特征图在通道维度上可以进行拼接操作。沿通道维度将投影后的嵌入向量与特征图拼接起来,得到新的特征表示 xconcat=concat(x,proj(PE)) 。对拼接后的特征图进行卷积等操作,进一步提取和融合信息,其具体步骤示意图如下:

优势:保留了嵌入向量和网络特征的原始信息,为模型提供了更丰富的输入,有助于模型学习到两者之间更复杂的关系,在一些对特征信息完整性要求较高的任务中表现较好 ,但会增加特征图的通道数,从而增加后续卷积层的计算量。

超参数

根据上文推导我们总结出两个重要公式,他们是整个模型的核心,同时还要定义网络结构、训练轮次、时间步长等超参数,以下做详细说明:

噪声调度参数

前向加噪,直接计算第t时刻的加噪后图像:

xt=α¯tx0+1α¯tε

反向去噪,根据模型预测的噪声得到下一时间步的数据:

xt1=1αt[xtβt1α¯tεθ(xt,t)]+σtz
  • αt=1βt,βt,t[0,T]

  • α¯t=Tαt

  • 噪声强度:σt=1α¯t11α¯t(1αt)

  • 随机噪声:zN(0,1)

在两个公式中涉及的系数 αt 可以由 βt 推出,也就是需要定义 T 个超参数,[β0,β1,,βT]

具体的超参数β无需全部手动设置,在给定βstartβstart后,利用噪声调度策略生成序列。

线性调度

利用公式:βt=βstart+(βendβstart)(t1)(T1)生成序列,在去噪扩散概率模型(DDPM)的原始论文中,采用了线性噪声调度,βstart=0.0001, βend=0.02,比较常用,效果稳定可靠。

余弦调度

这种序列在加噪初期βt增长非常缓慢,让模型能更充分地学习图像的细微结构;在加噪后期,βt迅速增大,确保图像能顺利过渡到纯噪声,通常能获得比线性调度更好的生成质量,尤其是在细节和纹理方面。

网络结构

超参数说明
模型类型常用Unet网络来预测。
特征通道数控制网络容量,通道数越多,模型表达能力越强,但计算和内存消耗也越大。
注意力机制在分辨率较低的层加入注意力机制,能有效捕捉长距离依赖。
时间步嵌入方法常用正弦/余弦嵌入。

训练参数

超参数可选说明
批量大小16, 32, 64影响训练速度和模型收敛。受限于 GPU 内存,通常越大越好,但需在内存允许范围内。
学习率2e-4控制参数更新的步长。DDPM 对学习率较为敏感,2e-4 是一个经过验证的良好起点。
优化器Adam/ AdamWAdamW是 Adam 的改进版,加入了权重衰减,能有效防止过拟合。
权重衰减1e-4正则化项,防止权重过大,提升模型泛化能力。
训练轮数50-200训练的总迭代次数。需要根据数据集大小和模型收敛情况来决定。