新闻型网站建设,赤水网站建设,发行商城小程序,网站域名 邮箱1. 从噪声到图像#xff1a;一个“猜猜看”的游戏 想象一下#xff0c;你收到了一张被严重高斯噪声污染的图片#xff0c;就像老式电视的雪花屏。你的任务是#xff0c;一步步地“猜”出它原本的样子。这听起来像是天方夜谭#xff0c;但扩散模型#xff08;Diffusion Mo…1. 从噪声到图像一个“猜猜看”的游戏想象一下你收到了一张被严重高斯噪声污染的图片就像老式电视的雪花屏。你的任务是一步步地“猜”出它原本的样子。这听起来像是天方夜谭但扩散模型Diffusion Model的核心——DDPMDenoising Diffusion Probabilistic Models的反向降噪过程干的就是这件事。它不像传统方法那样试图直接“修复”图像而是玩了一个巧妙的概率游戏如果我们知道一张图片是如何一步步被噪声淹没的那么我们就有可能沿着这条路径一步步地把它“猜”回来。这个过程本质上是一个基于贝叶斯定理的“逆推”游戏。前向过程也就是加噪过程是确定无疑的我们有一个清晰的数学公式告诉我们在第t步图像Xt是由上一步图像Xt-1加上一点特定方差的噪声zt得到的。这就像我们有一个精确的配方知道如何把一杯清水清晰图像变成一杯浑浊的泥水纯噪声。但反向过程呢我们只有一杯浑浊的泥水Xt需要猜出上一杯稍微清澈一点的水Xt-1是什么样子。这里的关键在于我们虽然不知道原始的清水X0是什么但我们有一个训练好的“侦探”——噪声预测模型。这个模型看过无数张图片从清晰变浑浊的过程它能够观察当前的泥水Xt然后“猜”出在这一步被加进去的噪声ε大概是什么样子。有了这个猜测的噪声ε再结合我们已知的加噪配方我们就能反过来“减”掉一部分噪声得到一个对Xt-1的合理猜测。这个“猜”和“减”的过程就是反向降噪采样。而支撑这个过程的数学骨架就是贝叶斯公式。它允许我们在已知结果Xt和部分先验知识加噪过程的情况下去推断原因Xt-1最可能的样子。接下来我们就一起像解一道应用题一样拆解这个从贝叶斯出发最终落地到一行行代码的奇妙旅程。2. 数学工具箱贝叶斯与正态分布在正式“破案”之前我们得先熟悉一下手头的几件关键工具。别担心我们只用到最核心的部分而且我会用最直白的方式解释。2.1 核心武器贝叶斯公式贝叶斯公式是概率论中一个非常强大的工具它描述了在已知一些证据或结果的情况下如何更新我们对某个假设或原因的信念。它的标准形式是P(原因 | 结果) [P(结果 | 原因) * P(原因)] / P(结果)翻译成我们扩散模型的语言就是P(上一张图 | 当前图) [P(当前图 | 上一张图) * P(上一张图)] / P(当前图)更精确地我们想知道在已知第t步的噪声图Xt和猜测的原始图X0时第t-1步的图Xt-1的概率分布。套用贝叶斯公式就是q(Xt-1 | Xt, X0) [q(Xt | Xt-1, X0) * q(Xt-1 | X0)] / q(Xt | X0)这个公式就是我们整个推导的起点。它的美妙之处在于等式右边的三项我们居然都能知道或者近似知道q(Xt | Xt-1, X0)这就是我们前向加噪的配方我们知道从Xt-1到Xt是怎么加噪声的所以这个条件概率是已知的。q(Xt-1 | X0)和q(Xt | X0)这表示从原始图X0直接到第t-1步或第t步的分布。由于前向过程每一步都是加高斯噪声所以从X0直接跳到任意一步t其结果也服从一个高斯分布这个可以通过重参数技巧推导出来其均值和方差我们也能计算。所以虽然左边的q(Xt-1 | Xt, X0)看起来很复杂在已知当前图和原始图时上一张图的分布但通过贝叶斯公式我们把它转化成了几个已知或可计算项的乘积与除法。2.2 得力助手高斯分布正态分布的性质我们的整个故事都发生在高斯分布的世界里。前向加的噪声是高斯噪声所以我们推导出的所有分布也都是高斯分布。这里需要记住高斯分布的两个关键特性概率密度函数一个均值为μ方差为σ²的高斯分布其概率密度函数PDF为f(x) (1 / sqrt(2πσ²)) * exp(-(x-μ)² / (2σ²))这个函数描述了一个随机变量取某个值x的可能性有多大。指数部分-(x-μ)²/(2σ²)决定了这个可能性的大小。重参数技巧这是机器学习中一个非常实用的技巧。如果我们想从一个高斯分布N(μ, σ²)中采样一个样本我们可以先从一个标准高斯分布N(0, 1)中采样一个随机数z然后通过线性变换得到我们想要的样本样本 μ σ * z。 在DDPM中这个技巧至关重要。因为采样生成过程本质上就是从一个个高斯分布中抽取样本重参数技巧让我们可以把随机性z和确定性的计算μ和σ分离开方便模型的训练和梯度的传播。有了贝叶斯公式作为“地图”高斯分布的性质作为“交通工具”我们就可以正式踏上反向降噪公式的推导之路了。3. 公式推导一步步“猜”出上一张图现在让我们把贝叶斯公式这个“地图”具体应用到我们的问题上。我们的目标是求出q(Xt-1 | Xt, X0)的具体形式也就是一个高斯分布的均值和方差。3.1 列出所有已知条件首先根据前向加噪过程我们有以下几个“已知事实”从X0直接到Xt-1q(Xt-1 | X0) ~ N( sqrt(ᾱ_t-1) * X0, (1 - ᾱ_t-1) * I )。这里ᾱ_t-1是前面所有步α的连乘是一个已知的系数。这个公式的意思是从原始图X0一步到位加上t-1步的累积噪声得到的分布。从X0直接到Xt同理q(Xt | X0) ~ N( sqrt(ᾱ_t) * X0, (1 - ᾱ_t) * I )。单步加噪q(Xt | Xt-1) ~ N( sqrt(α_t) * Xt-1, (1 - α_t) * I )。这就是我们最熟悉的那个加噪公式Xt sqrt(α_t)*Xt-1 sqrt(1-α_t)*zt的概率表达形式。注意这个分布与X0无关只依赖于Xt-1所以q(Xt | Xt-1, X0) q(Xt | Xt-1)。3.2 代入贝叶斯公式将上面的已知分布代入贝叶斯公式q(Xt-1 | Xt, X0) [q(Xt | Xt-1) * q(Xt-1 | X0)] / q(Xt | X0)由于等式右边三个都是高斯分布的概率密度函数PDF它们的乘积和商的结果经过一番计算虽然复杂但路径清晰最终仍然会是一个高斯分布的PDF。这是高斯分布一个非常好的性质。因此我们不需要直接计算复杂的积分只需要想办法把等式右边整理成高斯分布PDF的标准形式C * exp(-(x-μ)²/(2σ²))然后“对号入座”读出我们想要的均值μ和方差σ²。这个过程涉及大量的代数运算包括将三个高斯分布PDF的指数部分相加、合并同类项、配方等。原始文章中已经给出了详细的步骤。这里我跳过最繁琐的演算直接告诉你这个“对号入座”后得到的关键结果我们最终推导出q(Xt-1 | Xt, X0)服从一个高斯分布其均值和方差为均值 μ [ sqrt(α_t) * (1 - ᾱ_t-1) * Xt sqrt(ᾱ_t-1) * (1 - α_t) * X0 ] / (1 - ᾱ_t) 方差 σ² (1 - α_t) * (1 - ᾱ_t-1) / (1 - ᾱ_t)这个公式已经非常接近最终形式了它的物理意义非常直观在已知最终噪声图Xt和原始图X0的情况下上一时刻的图Xt-1最可能的样子均值μ是Xt和X0的一个加权平均。权重由我们预设的噪声调度参数α和ᾱ决定。3.3 引入噪声预测模型上面的公式还有一个问题它依赖于真实的原始图X0而我们生成时是不知道X0的这就是我们训练的噪声预测模型ε_θ大显身手的地方。还记得前向公式吗Xt sqrt(ᾱ_t) * X0 sqrt(1 - ᾱ_t) * ε。这里的ε就是第t步加入的真实噪声。我们可以把这个公式反过来用Xt和预测的噪声ε_θ来表达X0X0 ≈ (Xt - sqrt(1 - ᾱ_t) * ε_θ) / sqrt(ᾱ_t)这个近似非常关键。我们用模型预测的噪声ε_θ代替了未知的真实噪声ε从而得到了一个对原始图X0的估计值。虽然这个估计在早期t很大Xt很噪声时可能不准但随着反向过程一步步进行Xt越来越清晰这个估计会越来越准。现在我们把上面这个X0的估计式代入到之前推导出的均值μ的公式中。经过一系列代数化简主要是合并关于Xt的项一个奇迹发生了许多复杂的项相互抵消公式变得异常简洁均值 μ (1 / sqrt(α_t)) * [ Xt - ((1 - α_t) / sqrt(1 - ᾱ_t)) * ε_θ ]同时对于方差σ²论文作者通过实验发现使用简化形式σ² β_t其中β_t 1 - α_t与使用上面推导出的复杂形式在效果上差异不大且能使采样过程更稳定。因此我们最终采用方差 σ² β_t 1 - α_t至此我们得到了DDPM反向降噪采样的核心公式已知第t步的带噪图像Xt和噪声预测模型ε_θ则Xt-1的分布为q(Xt-1 | Xt) ~ N( μ, σ² I )其中μ (1 / sqrt(α_t)) * [ Xt - (β_t / sqrt(1 - ᾱ_t)) * ε_θ ]σ² β_t。4. 算法实现从公式到代码理论推导很美妙但最终我们要能把它写出来、跑起来。DDPM的反向采样算法清晰得就像一份烹饪食谱。4.1 采样算法步骤拆解假设我们已经训练好了一个噪声预测模型UNet_ε它能够接收第t步的图像Xt和时间步t输出预测的噪声ε_θ。同时我们有一系列预设好的噪声调度参数{α_t, ᾱ_t, β_t}这些在训练前就确定了。那么从随机噪声XT通常T1000生成一张图像X0的完整反向过程如下初始化从标准高斯分布中采样一张纯噪声图像XT ~ N(0, I)。循环迭代对于t T, T-1, ..., 1 a.输入模型将当前图像Xt和当前时间步t输入噪声预测模型UNet_ε得到预测的噪声ε_θ UNet_ε(Xt, t)。 b.计算均值根据公式计算高斯分布的均值μμ (1 / sqrt(α_t)) * ( Xt - (β_t / sqrt(1 - ᾱ_t)) * ε_θ )c.采样如果t 1我们需要从分布N(μ, β_t I)中采样Xt-1。使用重参数技巧z ~ N(0, I) # 采样一个标准高斯噪声 Xt-1 μ sqrt(β_t) * z如果t 1通常直接取均值不加噪声X0 μ。输出循环结束后X0即为生成图像。这个过程就像是一个精细的雕刻我们从一块完全随机的“石料”XT开始模型根据当前形状Xt猜测哪里是多余的“石屑”噪声ε_θ我们按照一个精确的计算公式μ凿掉一部分并引入一点点可控的随机性sqrt(β_t)*z得到下一步更精细的毛坯Xt-1。如此反复直至作品完成。4.2 代码示例与关键细节让我们用PyTorch风格的伪代码来看一下核心循环的实现这能让你对上面的步骤有更具体的感受。import torch def sample_ddpm(model, scheduler, batch_size, image_size, device): model: 训练好的噪声预测UNet scheduler: 存储了所有alpha, alpha_bar, beta的调度器 batch_size: 生成图像的数量 image_size: 图像尺寸 device: CPU or GPU # 1. 初始化从标准正态分布采样纯噪声 x_t torch.randn(batch_size, 3, image_size, image_size).to(device) # 2. 反向迭代采样 for t in reversed(range(1, scheduler.timesteps)): # 从T到1 # 获取当前时间步t对应的参数 alpha_t scheduler.alphas[t] alpha_bar_t scheduler.alpha_bars[t] beta_t scheduler.betas[t] # 将时间步t转换为模型需要的张量格式 t_batch torch.full((batch_size,), t, devicedevice, dtypetorch.long) # a. 预测噪声 predicted_noise model(x_t, t_batch) # model就是UNet_ε # b. 计算均值 μ # 公式: μ (1 / sqrt(α_t)) * [ x_t - (β_t / sqrt(1 - ᾱ_t)) * ε_θ ] mean_coeff 1 / torch.sqrt(alpha_t) noise_coeff beta_t / torch.sqrt(1 - alpha_bar_t) mean mean_coeff * (x_t - noise_coeff * predicted_noise) # c. 计算方差 σ²这里就是β_t variance beta_t # d. 采样 x_{t-1} if t 1: # 重参数技巧采样 mean sqrt(variance) * z noise torch.randn_like(x_t) # 采样随机噪声z x_t mean torch.sqrt(variance) * noise else: # t1时通常不加噪声 x_t mean # 3. 循环结束x_t 就是生成的图像 x_0 generated_images x_t return generated_images在实际的DDPM实现中有几个细节值得注意时间步嵌入模型UNet_ε需要知道当前是第几步所以时间步t会被转换成一种向量表示如正弦位置编码后输入到模型的各个层中。调度器alpha,alpha_bar,beta这些序列的设定对生成质量影响很大。通常beta被安排成从很小值线性或余弦增长到较大值这样前向过程初期加噪少后期加噪多。方差简化正如推导部分提到的代码中直接使用β_t作为方差而不是更复杂的那个推导式。这被证明是有效的简化。分类器自由引导在更高级的用法中我们可以在采样时通过调整条件信息的权重来更好地控制生成内容这只需要对预测的噪声ε_θ做一个小小的加权混合。从这一小段代码中你可以看到那些复杂的数学推导最终凝结成了清晰、可执行的几步操作。这就是理论指导实践的完美体现。当你运行这段代码看着噪声一步步演变成有意义的图像时你会对之前所有的数学直觉有更深的理解。