扩散模型之(一)去噪扩散模型 DDPM
1.背景深度学习任务可以简单分为判别型或生成型。简而言之判别型模型学习决策边界并可以对给定的输入进行分类。生成型模型学习底层数据分布的近似值并可以从该分布中采样以生成新的数据样本。扩散模型是四个经常被提及的生成框架之一其他三个是变分自编码器 (VAE)、生成对抗网络 (GAN) 和基于流的模型flow matching、rectified flow等。简单来说扩散模型定义了一个马尔可夫链式扩散步骤缓慢地向数据中添加随机噪声逐渐将高斯噪声等众所周知的分布转换为复杂的数据分布。然后学习逆扩散过程从噪声中构建所需的数据样本。与变分自编码器 (VAE) 或流模型不同扩散模型采用固定的学习过程并且潜在变量具有高维性与原始数据相同。图 1.扩散模型的简化流程图2015年Sohl-Dickstein等人在《基于非平衡热力学的深度无监督学习》中提出了扩散模型。五年后DDPM 的出现使得扩散模型变得切实可行并开启了生成模型的新纪元。自DDPM问世以来涌现出了许多如今令人印象深刻的图像生成模型如噪声条件得分网络 NCSN基于flowmatching的 Flow Matching for Generative Modeling。目前主流的生成模型对比如下图 2.不同生成模型的可视化对比2.方法概述扩散模型的思路如下如果我们取一个数据样本并迭代地即次向其中添加噪声最终会得到纯高斯噪声。问题是我们能否逆转这个过程从高斯噪声开始生成一个干净的数据样本图 3.DDPM原理图3.前向过程 (Forward Process)DDPM前向过程也就是加噪过程的可视化说明如下图。图 4.DDPM的前向加噪过程原理图其中定义条件分布称为前向扩散kernel其定义为def forward_process_ddpms(img_t_minus_1, beta, t): Implements the forward process of a DDPM model. Args: img_t_minus_1: Image at the previous timestep (t - 1) beta: Scheduled Variance t: Current timestep Returns: Image obtained at current timestep # 1. Obtain beta_t. Reshape it to have the same number of # dimensions as our image array beta_t beta[t].reshape(-1, 1, 1) # 2. Calculate mean and variance mu np.sqrt((1.0 - beta_t)) * img_t_minus_1 sigma np.sqrt(beta_t) # 3. Obtain image at timestep t using equation (15) img_t mu sigma * np.random.randn(*img_t_minus_1.shape) return img_t # Lets check if ourforward process function is # doing what it is supposed to do on a sample image # 1. Load image using PIL (or any other library that you prefer) img Image.open(../images/cat.jpg) # 2. Resize the image to desired dimensions IMG_SIZE (128, 128) img img.resize(sizeIMG_SIZE) # 3. Define number of timesteps timesteps 100 # 4. Generate beta (variance schedule) beta_start 0.0001 beta_end 0.05 beta np.linspace(beta_start, beta_end, numtimesteps, dtypenp.float32) processed_images [] img_t np.asarray(img.copy(), dtypenp.float32) / 255. # 5. Run the forward process to obtain img after t timesteps for t in range(timesteps): img_t forward_process_ddpms(img_t_minus_1img_t, betabeta, tt) if t%200 or ttimesteps - 1: sample (img_t.clip(0, 1) * 255.0).astype(np.uint8) processed_images.append(sample) # 6. Plot and see samples at different timesteps _, ax plt.subplots(1, len(processed_images), figsize(15, 6)) for i, sample in enumerate(processed_images): ax[i].imshow(sample) ax[i].set_title(fTimestep: {i*20}) ax[i].axis(off) ax[i].grid(False) plt.suptitle(Forward process in DDPMs, y0.75) plt.show() plt.close()式中各项的说明如下图 5.DDPM前向扩散kernel说明具体来说给定初始数据点前向过程在步内逐步添加高斯噪声生成一系列噪声逐渐增大的噪声样本也称为潜在变量。每一步都根据一个方差进行控制。数据样本随着步伐的推进它逐渐失去原来的特征噪声特征变得更为明显。最终当相当于各向同性的高斯分布也就是完全为高斯噪声。4.重参数化过程图 6.马尔科夫链前向加噪与反向去噪示意图上述前向过程的一个很好的特性是我们可以采样对于任何时间步通过重参数化技巧以闭合形式呈现。结合上式1可得上式3中RV1与RV2是两个零均值方差分别为和的高斯分布。对于两个不同方差的高斯分布和相加视为两个高斯分布的卷积那么根据高斯分布的乘积与卷积原理可知此时形成新的高斯分布为相应的均方差为由此得到令且对于时间步长为相应的参数大小为def forward_process_ddpms_v2(orig_img, alpha_bar, t): Implements the efficient forward process of a DDPM model. Args: orig_img: Image at timestep t0 alpha_bar: The reparameterized version of beta t: Current timestep Returns: Image obtained at current timestep # 1. Obtain beta_t. Reshape it to have the same number of # dimensions as our image array alpha_bar_t alpha_bar[t].reshape(-1, 1, 1) # 2. Calculate mean and variance mu np.sqrt(alpha_bar_t) * orig_img sigma np.sqrt(1.0 - alpha_bar_t) # 3. Obtain image at timestep t img_t mu sigma * np.random.randn(*orig_img.shape) return img_t # 1. Define alpha and alpha_bar alpha 1.0 - beta alpha_bar np.cumprod(alpha) processed_images [img] # Image at 0th step orig_img np.asarray(img.copy(), dtypenp.float32) / 255. # 2. Run the forward pass for specific timesteps # We will use the timesteps we used in previous visualizations specific_timesteps [19, 39, 59, 79, 99] for step in specific_timesteps: img_t forward_process_ddpms_v2(orig_img, alpha_bar, step) img_t (img_t.clip(0, 1) * 255.0).astype(np.uint8) processed_images.append(img_t) # 3. Plot and see samples at different timesteps _, ax plt.subplots(1, len(processed_images), figsize(15, 6)) for i, sample in enumerate(processed_images): ax[i].imshow(sample) ax[i].set_title(fTimestep: {i*20}) ax[i].axis(off) ax[i].grid(False) plt.suptitle(Efficient Forward process in DDPMs, y0.75) plt.axis(off) plt.savefig(../plots/efficient_forward_process.png, pad_inches0, bbox_inchestight ) plt.show() plt.close()5.与随机梯度郎之万动力学朗之万动力学是一个物理学概念旨在对分子系统进行统计建模。结合随机梯度下降法随机梯度朗之万动力学stochastic gradient Langevin dynamicsSGLD,Welling Teh 2011可以从概率密度函数中生成样本。即仅使用概率密度函数的梯度项用于马尔可夫链的更新其中是步长大小当就趋向于.不同于标准的SGDSGLD方法在参数的更新中通过注入高斯噪声避免陷入局部最小值的解。6.反向过程 (Reverse Process)图 7.反向去噪过程示意图图 8.2D swiss roll数据训练扩散模型示意图反向过程也称为生成过程或者去噪过程是通过学习一个参数化的模型来近似反转前向过程从噪声开始逐步去噪以生成数据。整个反向过程假设为一个马尔可夫过程 关于这个公式6*的推导如下首先根据概率论基本链式法则再根据逆向过程为马尔可夫过程当前时刻状态只依赖上一个时刻那么上式简化为写成乘积形式就得到上述连乘结果。这里的多元高斯均值与协方差都是与时间有关的参数需要通过学习求得。需要指出的是是反向分布被称为反向扩散kernel是反向分布的可学习参数前向过程可以理解为将样本从数据流形中推出使其成为噪声。反向过程可以理解为通过去除噪声将样本推回流形。其实就是即前向过程的结束点就是反向过程的起点。从噪声样本开始可以有n多种途径到达数据样本。那么为了获得我们需要整合所有可能的路径即像上面那样计算概率密度是比较困难的。神经网络如下式7所示的反向过程足以预测均值和协方差矩阵但我们也需要以不同的方式构建相应的目标函数.7.优化目标与loss函数基于扩散的生成模型的训练目标相当于“最大化生成的样本在反向过程结束时的对数似然x属于原始数据分布”。我们将扩散模型中的转换函数定义为“高斯函数”。为了最大化高斯分布的对数似然需要尝试找到分布的参数 (,2 ) 使得生成的数据与原始数据属于同一数据分布的“似然”最大化。为了训练神经网络我们将损失函数 (L) 定义为目标函数的负值。因此目标函数的值越大损失越小反之亦然。作者从 VAE 中汲取灵感使用变分下界variational lower bound (VLB)重新定义训练目标也称为“证据下界Evidence lower bound”ELBO。具体来说在VAE中令x是观测变量z是隐变量那么对于扩散模型而言可以视为观测变量为隐变量那么注意这里之所以把负号写在外面是为了与直接优化log-likelihood的文献中分子分母形式上的一致。相应地利用 Jensen不等式上述定义的 loss 推导也可以表示为按照期望与KL 散度的定义上式9表示成如下形式根据bayes法则可知利用式11带入式10后改写可得展开式12中的求和项多项互消后可得在式13中利用期望的线性性质展开各项并重新调整了相应的下标。这为我们提供了一个将表达式L用KL散度表示的机会。现在可以具体实现这一转换。分析上式第二项可知计算两个分布的KL散度q是前向过程在反向过程是固定的而计算的是前向的终点也就是反向去噪的起点这个概率密度也是固定不动的视为常数项那么上式14改写为如下再结合上文分析再次写出如下两项结合这里的两个式子我们有其中视为是与无关的常数项对照标准高斯pdf形式也就是同时结合与均值和方差进一步参数化推导如下进一步的对前面的式4变换得到如下带入到上式18中得到由此得到如下结果再次分析上述式14上式loss函数可改写为若干KL散度与entropy项单独写出VLB loss中的每一项可简化表示分析式22可知1.其实就是即反向过程的起点也就是前向过程的终点这里是不变的。第一项也就是先验匹配项可以忽略2.第二项也就是去噪匹配项由式6与21可知比较的是两个高斯分布的差异3.第三项也就是重建项和迭代步数无关。KL中除了的每一项都是比较两个高斯分布的差异通过闭式解得到。是恒定的在训练期间可以忽略因为没有可学习的参数是高斯噪声。8.Loss进一步分析综合上述的分析反向条件分布是可计算得到的视为是真实分布与就是需要近似的真实参数而反向去噪迭代过程就是要近似条件概率分布.其中是模型训练得到的均值是训练得到的协方差。希望预测的真实均值如下因为在训练时作为输入可以重参数化高斯噪声项使其从时间步的输入预测结合上一节的loss分析损失函数对于两个Gaussian的KL散度参考 高斯分布的KL散度计算 可得因为协方差是固定的即那么 KL divergence 部分将KL散度项带入得到DDPM原文验证了省去权重项训练得到的扩散模型结果更优去权重项的最终简化形式如下9.训练算法 (Training Algorithm) 与采样算法 (Sampling Algorithm)训练就是最小化上述的随机采样随机采样时间步随机采样噪声计算梯度下降步骤以最小化其中当最后一步时。这本质上是朗之万动力学Langevin dynamics的一个步骤。参考资料Denoising Diffusion Probabilistic ModelsUnderstanding Diffusion Models: A Unified PerspectiveThe Latent: Code the Maths - A deep dive into DDPMsWhat are Diffusion Models? | LilLogthe-rise-of-diffusion-models