重生之我是去噪高手——diffusion model

diffusion model是如何运作的?

想象一下,你有一张清晰的图片。扩散模型的核心思想分为两个过程:

  1. 前向过程(Forward Process / Diffusion Process):逐步加噪
  2. 反向过程(Reverse Process / Denoising Process):逐步去噪(学习生成)

1. 前向过程(逐步加噪) - 破坏图像

  • 目标:
    把一张真实的、清晰的图片(来自你的训练数据集)逐步变成完全的随机噪声(通常是高斯噪声)。

  • 如何做:
    这个过程是固定的、预先定义好的,不需要学习。

    • 从原始图片 x 0 x_0 x0 开始。
    • 设定一个总的步数 T T T(比如 1000 步)。
    • 在每一步 t t t(从 1 到 T T T),我们向上一步的图片 x t − 1 x_{t-1} xt1 中加入少量的高斯噪声,得到 x t x_t xt
    • 加入的噪声量是根据一个预设的“噪声计划”(variance schedule)来控制的。通常,越往后的步骤加入的噪声(或绝对噪声)越多,也就是说信噪比越来越低。
    • 经过 T T T 步之后,原始图片 x 0 x_0 x0 基本上就变成了一个纯粹的噪声图像 x T x_T xT,与原始信息几乎无关。
  • 关键点:

    • 这个过程是一个马尔可夫链: x t x_t xt 只依赖于 x t − 1 x_{t-1} xt1
    • 由于高斯噪声的良好特性,我们可以直接计算出任意步骤 t t t 的噪声图像 x t x_t xt,只需要原始图像 x 0 x_0 x0 和噪声计划,不需要一步步迭代。这对于训练过程非常重要。

类比:
想象把一滴墨水滴入清水中,墨水会逐渐扩散(加噪),直到整杯水变成均匀的淡黑色(纯噪声)。

PS:

前向过程提供了问题-答案对,即噪声阶段和对映的噪声。这个可以为反向过程提供训练的数据。简单来说,前向过程就是故意弄脏图片,并且记录下是怎么弄脏的,目的是为了给 AI 提供学习“如何把脏图片变干净”的训练材料和学习目标。

马尔可夫链的核心思想是:“未来只取决于现在,与过去无关。”


2. 反向过程(逐步去噪) - 学习生成

  • 目标:
    从一个纯粹的随机噪声图像(与 x T x_T xT 分布相同)开始,逐步去除噪声,最终生成一张看起来真实、清晰的图片。

  • 挑战:
    直接反转加噪过程非常困难,因为每一步加噪都丢失了信息。

  • 解决方案:
    训练一个神经网络(通常是 U-Net 架构,特别擅长处理具有空间结构的数据)来预测每一步 被添加的噪声

  • 如何做:

    • 这个神经网络模型(我们称之为 ϵ θ \epsilon_\theta ϵθ,其中 θ \theta θ 是网络参数)的输入是:
      • 当前步骤 t t t 的噪声图像 x t x_t xt
      • 当前的步骤 t t t(通常会编码成一个向量,用以告诉网络当前处于哪个去噪阶段)。
    • 网络的 输出 是:预测在前向过程中,从 x t − 1 x_{t-1} xt1 得到 x t x_t xt 时加入的那个噪声 ϵ \epsilon ϵ
    • 有了这个预测的噪声 ϵ θ ( x t , t ) \epsilon_\theta(x_t, t) ϵθ(xt,t),我们就可以使用一个数学公式,从当前的 x t x_t xt 中“减去”这个预测的噪声(并加上一些必要的随机性),来估计出上一步稍微清晰一点的图像 x t − 1 x_{t-1} xt1
    • 这个过程从 t = T t = T t=T 开始,输入一个随机噪声 x T x_T xT,然后利用神经网络反复预测并去除噪声,一步步得到 x T − 1 x_{T-1} xT1, x T − 2 x_{T-2} xT2, …, 直到 x 0 x_0 x0。最终得到的 x 0 x_0 x0 就是模型生成的图片。
  • 关键点:

    • 这是模型需要 学习 的部分。
    • 学习的目标是让神经网络预测的噪声尽可能接近前向过程中实际添加的噪声。

类比:
想象观看墨水扩散的录像带并倒放。神经网络就像一个“物理学家”,它学习如何在每个时间点精确地把扩散开的墨水粒子“收回”一点点,最终恢复成一滴清晰的墨水。


训练过程(如何学习去噪)

模型是如何学会预测噪声的呢?

  1. 从训练数据集中随机抽取一张真实的图片 x 0 x_0 x0
  2. 随机选择一个时间步 t t t(在 1 到 T T T 之间)。
  3. 利用前向过程的公式,直接计算出在 t t t 时刻,向 x 0 x_0 x0 加入适量噪声后得到的噪声图像 x t x_t xt。同时,我们知道实际加入的噪声 ϵ \epsilon ϵ 是什么。
  4. x t x_t xt 和时间步 t t t 输入到神经网络 ϵ θ \epsilon_\theta ϵθ 中。
  5. 神经网络输出它 预测 的噪声 ϵ θ ( x t , t ) \epsilon_\theta(x_t, t) ϵθ(xt,t)
  6. 计算预测噪声 ϵ θ ( x t , t ) \epsilon_\theta(x_t, t) ϵθ(xt,t) 和实际噪声 ϵ \epsilon ϵ 之间的差异(例如,使用均方误差 L2 loss)。这个差异就是模型的“错误”或损失(loss)。
  7. 使用反向传播和优化算法(如 Adam)调整神经网络的参数 θ \theta θ,使得这个损失尽可能小。
  8. 重复以上步骤,使用大量的训练图片和不同的时间步 t t t

通过这个过程,神经网络逐渐学会了在任何噪声水平 t t t 下,从噪声图像 x t x_t xt 中准确地识别并预测出被添加的噪声。


生成新图片(Sampling)

训练完成后,如何生成一张全新的图片?

  1. 从一个标准高斯分布(纯随机噪声)中采样得到一个初始图像 x T x_T xT
  2. t = T t = T t=T 开始,逐步递减到 t = 1 t = 1 t=1
    • 将当前的图像 x t x_t xt 和时间步 t t t 输入到 训练好的 神经网络 ϵ θ \epsilon_\theta ϵθ 中,得到预测的噪声 ϵ θ ( x t , t ) \epsilon_\theta(x_t, t) ϵθ(xt,t)
    • 使用反向过程的公式,结合 x t x_t xt 和预测的噪声 ϵ θ ( x t , t ) \epsilon_\theta(x_t, t) ϵθ(xt,t),计算出上一步的图像 x t − 1 x_{t-1} xt1。(这个公式通常还会包含一个随机项,以增加生成的多样性)。
  3. t t t 减到 0 时,得到的 x 0 x_0 x0 就是最终生成的图像。

总结

  • Diffusion Model 通过一个 固定的加噪过程(前向)和一个 学习的去噪过程(反向)来工作。
  • 核心是训练一个神经网络来 预测 在加噪过程中每一步所添加的噪声。
  • 通过从纯噪声开始,反复使用这个神经网络预测并移除噪声,模型可以逐步“雕刻”出逼真的新数据样本。
  • 这种方法已被证明在图像生成、音频生成等领域能产生非常高质量和多样化的结果,尽管其生成过程(采样)通常比其他模型(如 GAN)要慢,因为它需要进行很多步迭代。目前也有很多研究在致力于加速这个采样过程。

diffusion model的数学原理

1. 前向过程 (Forward Process / Diffusion Process)

这是一个固定预定义的马尔可夫链,它逐渐向数据 x 0 x_0 x0(来自真实数据分布 q ( x 0 ) q(x_0) q(x0))添加高斯噪声,经过 T T T 步后得到近似纯噪声 x T x_T xT

  • 状态定义:
    x 1 , x 2 , … , x T x_1, x_2, \ldots, x_T x1,x2,,xT 是隐变量(latent variables),与原始数据 x 0 x_0 x0 具有相同的维度。

  • 转移概率:
    每一步从 x t − 1 x_{t-1} xt1 x t x_t xt 的转移被定义为一个条件高斯分布
    q ( x t ∣ x t − 1 ) = N ( x t ; 1 − β t x t − 1 , β t I ) q(x_t \mid x_{t-1}) = \mathcal{N}\Big(x_t; \sqrt{1 - \beta_t}\, x_{t-1},\, \beta_t\, I\Big) q(xtxt1)=N(xt;1βt xt1,βtI)
    其中:

    • β t \beta_t βt 是一个预先设定的(通常很小的)方差值,代表在第 t t t 步加入的噪声强度。
      β 1 < β 2 < ⋯ < β T \beta_1 < \beta_2 < \cdots < \beta_T β1<β2<<βT 构成了一个方差计划 (variance schedule)。
    • 1 − β t x t − 1 \sqrt{1 - \beta_t}\, x_{t-1} 1βt xt1 表示对上一步状态的轻微缩放。
    • β t I \beta_t\, I βtI 是加入的高斯噪声的协方差矩阵(其中 I I I 为单位矩阵)。

PS:整个过程类似于“要得到下一张更模糊的图片 x_t,先把当前图片 x_{t-1} 稍微‘弄暗’一点点(公式中的sqrt(1 - β_t) * x_{t-1}:这是正态分布的均值(μ),也就是 x_t 最可能变成的样子),然后再给它撒上一层‘强度’为 β_t 的随机‘雪花’(公式中的β_t * I:这是正态分布的方差(σ²),代表添加的噪声的“大小”或“散布程度”。)。” 这个过程重复 T 次。

  • 联合概率分布:
    整个前向过程的联合概率为
    q ( x 1 : T ∣ x 0 ) = ∏ t = 1 T q ( x t ∣ x t − 1 ) . q(x_{1:T} \mid x_0) = \prod_{t=1}^T q(x_t \mid x_{t-1}). q(x1:Tx0)=t=1Tq(xtxt1).

  • 重要特性 (采样 x t x_t xt 的闭式解):
    由于高斯分布的良好性质,我们可以直接从 x 0 x_0 x0 采样得到任意步骤 t t t x t x_t xt,而无需进行 t t t 次迭代。设定
    α t = 1 − β t , α ˉ t = ∏ s = 1 t α s . \alpha_t = 1 - \beta_t,\quad \bar{\alpha}_t = \prod_{s=1}^t \alpha_s. αt=1βt,αˉt=s=1tαs.
    那么,便有闭式解:
    q ( x t ∣ x 0 ) = N ( x t ; α ˉ t x 0 , ( 1 − α ˉ t ) I ) , q(x_t \mid x_0) = \mathcal{N}\Big(x_t; \sqrt{\bar{\alpha}_t}\, x_0,\, (1 - \bar{\alpha}_t)\, I\Big), q(xtx0)=N(xt;αˉt x0,(1αˉt)I),
    或者写成
    x t = α ˉ t x 0 + 1 − α ˉ t ε , ε ∼ N ( 0 , I ) . x_t = \sqrt{\bar{\alpha}_t}\, x_0 + \sqrt{1 - \bar{\alpha}_t}\, \varepsilon,\quad \varepsilon \sim \mathcal{N}(0, I). xt=αˉt x0+1αˉt ε,εN(0,I).

PS:“第 t 步的噪声图片 x_t,其实就是(原始图片 x₀ 褪色 t 步后的残影)加上 (一个标准噪声 ε 被放大 t 步对应倍数后的效果)。t 越小,x_t 越像 x₀;t 越大,x_t 越像纯噪声 ε。”


2. 反向过程 (Reverse Process / Denoising Process)

这部分是我们需要学习的过程。目标是从噪声
x T ∼ N ( 0 , I ) x_T \sim \mathcal{N}(0, I) xTN(0,I)
开始,逐步反向运行该过程,最终生成一个样本 x 0 x_0 x0,使其看起来像真实数据分布 q ( x 0 ) q(x_0) q(x0) 中的样本。

  • 目标:
    学习反向的转移概率 p ( x t − 1 ∣ x t ) p(x_{t-1} \mid x_t) p(xt1xt)

  • 挑战:
    直接计算真实后验 q ( x t − 1 ∣ x t ) q(x_{t-1} \mid x_t) q(xt1xt) 比较困难,因为它需要考虑整个数据集的信息。但如果同时条件化 x 0 x_0 x0,则后验 q ( x t − 1 ∣ x t , x 0 ) q(x_{t-1} \mid x_t, x_0) q(xt1xt,x0) 是可求解的(tractable)。

  • 真实的后验 (给定 x 0 x_0 x0):
    利用贝叶斯定理可以证明,
    q ( x t − 1 ∣ x t , x 0 ) = N ( x t − 1 ; μ ~ t ( x t , x 0 ) , β ~ t I ) , q(x_{t-1} \mid x_t, x_0) = \mathcal{N}\Big(x_{t-1}; \tilde{\mu}_t(x_t, x_0),\, \tilde{\beta}_t\, I\Big), q(xt1xt,x0)=N(xt1;μ~t(xt,x0),β~tI),
    其中均值和方差分别为
    μ ~ t ( x t , x 0 ) = α ˉ t − 1 β t 1 − α ˉ t x 0 + α t ( 1 − α ˉ t − 1 ) 1 − α ˉ t x t , \tilde{\mu}_t(x_t, x_0) = \frac{\sqrt{\bar{\alpha}_{t-1}}\, \beta_t}{1 - \bar{\alpha}_t}\, x_0 + \frac{\sqrt{\alpha_t}\,(1 - \bar{\alpha}_{t-1})}{1 - \bar{\alpha}_t}\, x_t, μ~t(xt,x0)=1αˉtαˉt1 βtx0+1αˉtαt (1αˉt1)xt,
    β ~ t = 1 − α ˉ t − 1 1 − α ˉ t β t . \tilde{\beta}_t = \frac{1 - \bar{\alpha}_{t-1}}{1 - \bar{\alpha}_t}\, \beta_t. β~t=1αˉt1αˉt1βt.

  • 模型近似:
    由于在生成时我们没有 x 0 x_0 x0 信息,因此使用一个神经网络 p θ p_\theta pθ 来近似反向转移概率:
    p θ ( x t − 1 ∣ x t ) = N ( x t − 1 ; μ θ ( x t , t ) , Σ θ ( x t , t ) ) . p_\theta(x_{t-1} \mid x_t) = \mathcal{N}\Big(x_{t-1}; \mu_\theta(x_t, t),\, \Sigma_\theta(x_t, t)\Big). pθ(xt1xt)=N(xt1;μθ(xt,t),Σθ(xt,t)).
    其中, μ θ \mu_\theta μθ Σ θ \Sigma_\theta Σθ 分别由神经网络根据输入 x t x_t xt 及时间步 t t t 预测得到。

  • 简化方差:
    在实际应用中,常将方差 Σ θ ( x t , t ) \Sigma_\theta(x_t, t) Σθ(xt,t) 设为固定值,而不是由网络学习。常见做法为:
    Σ θ ( x t , t ) = σ t 2 I , \Sigma_\theta(x_t, t) = \sigma_t^2\, I, Σθ(xt,t)=σt2I,
    其中 σ t 2 \sigma_t^2 σt2 可能选择为 β t \beta_t βt β ~ t \tilde{\beta}_t β~t。如此,我们主要需要学习的是均值 μ θ ( x t , t ) \mu_\theta(x_t, t) μθ(xt,t)

  • 生成过程:

    x T ∼ N ( 0 , I ) x_T \sim \mathcal{N}(0, I) xTN(0,I)
    开始,依次(从 t = T t = T t=T 1 1 1)采样
    x t − 1 ∼ p θ ( x t − 1 ∣ x t ) . x_{t-1} \sim p_\theta(x_{t-1} \mid x_t). xt1pθ(xt1xt).


3. 训练目标 (Learning Objective)

我们希望最大化训练数据 x 0 x_0 x0 的对数似然 log ⁡ p θ ( x 0 ) \log p_\theta(x_0) logpθ(x0)。直接优化此目标较为困难,因此与变分自编码器(VAE)类似,我们通过优化证据下界(Evidence Lower Bound, ELBO,也称 Variational Lower Bound, VLB)来间接训练模型。

PS:直接计算 p_θ(x₀) 这个概率极其困难。因为它涉及到 AI 可能通过的所有“去噪步骤”最终得到 x₀ 的所有可能路径,这太复杂了!

  • ELBO 推导:
    log ⁡ p θ ( x 0 ) ≥ L V L B = E q ( x 1 : T ∣ x 0 ) [ log ⁡ p θ ( x 0 : T ) q ( x 1 : T ∣ x 0 ) ] . \log p_\theta(x_0) \geq L_{\mathrm{VLB}} = \mathbb{E}_{q(x_{1:T}\mid x_0)} \left[ \log \frac{p_\theta(x_{0:T})}{q(x_{1:T}\mid x_0)} \right]. logpθ(x0)LVLB=Eq(x1:Tx0)[logq(x1:Tx0)pθ(x0:T)].
    通常写作:
    L V L B = E q [ log ⁡ p ( x T ) + ∑ t = 1 T log ⁡ p θ ( x t − 1 ∣ x t ) q ( x t ∣ x t − 1 ) ] , L_{\mathrm{VLB}} = \mathbb{E}_q \left[ \log p(x_T) + \sum_{t=1}^{T} \log \frac{p_\theta(x_{t-1}\mid x_t)}{q(x_t\mid x_{t-1})} \right], LVLB=Eq[logp(xT)+t=1Tlogq(xtxt1)pθ(xt1xt)],

PS:如果我们想办法把 ELBO (L_VLB) 的值尽量提高,那么我们也就间接地把真正的目标 log ⁡ p θ ( x 0 ) \log p_\theta(x_0) logpθ(x0) 提高了(至少不会让它变差)。所以,我们不去优化那个困难的 log ⁡ p θ ( x 0 ) \log p_\theta(x_0) logpθ(x0),而是优化相对容易处理的 ELBO (L_VLB)。

(其中 p ( x T ) p(x_T) p(xT) 项由于不依赖于参数 θ \theta θ 可忽略)进一步分解为:
L V L B = E q [ log ⁡ p θ ( x 0 ∣ x 1 ) ] − D K L ( q ( x T ∣ x 0 ) ∥ p ( x T ) ) − ∑ t = 2 T E q [ D K L ( q ( x t − 1 ∣ x t , x 0 ) ∥ p θ ( x t − 1 ∣ x t ) ) ] . L_{\mathrm{VLB}} = \mathbb{E}_q\Big[\log p_\theta(x_0\mid x_1)\Big] - D_{\mathrm{KL}}\big(q(x_T\mid x_0) \,\|\, p(x_T)\big) - \sum_{t=2}^{T} \mathbb{E}_q\Big[D_{\mathrm{KL}}\big(q(x_{t-1}\mid x_t, x_0) \,\|\, p_\theta(x_{t-1}\mid x_t)\big)\Big]. LVLB=Eq[logpθ(x0x1)]DKL(q(xTx0)p(xT))t=2TEq[DKL(q(xt1xt,x0)pθ(xt1xt))].

PS: p θ ( x 0 ∣ x 1 ) p_θ(x₀|x₁) pθ(x0x1):表示 AI 在去噪的最后一步(从稍微有点噪声的 x₁ 变成清晰的 x₀)时,把图片还原得有多好。

D K L ( q ( x T ∣ x 0 ) ∣ ∣ p ( x T ) ) D_KL(q(x_T|x₀) || p(x_T)) DKL(q(xTx0)∣∣p(xT)) (噪声匹配 - 训练时可忽略)这部分只跟固定的前向过程和我们对噪声的固定假设有关,跟 AI 的参数 θ 无关。既然跟我们要优化的 θ 无关,那么在训练 AI(优化 θ)时就可以忽略它。

Σ E q [ D K L ( q ( x t − 1 ∣ x t , x 0 ) ∣ ∣ p θ ( x t − 1 ∣ x t ) ) ] Σ E_q[D_KL(q(x_{t-1}|x_t, x₀) || p_θ(x_{t-1}|x_t))] ΣEq[DKL(q(xt1xt,x0)∣∣pθ(xt1xt))] (一步步去噪的匹配 - 核心部分!):

这是训练中最重要的部分。它是对所有中间去噪步骤(从 t=T 到 t=2)求和。

q ( x t − 1 ∣ x t , x 0 ) q(x_{t-1}|x_t, x_0) q(xt1xt,x0):这是如果我们有“作弊码”(知道原始清晰图片 x₀),从 x_t 回到 x_{t-1} 的“理想方式”或“正确答案”。我们知道它是一个精确的高斯分布 N ( μ ~ t , β ~ t I ) N(μ̃_t, β̃_t I) N(μ~t,β~tI)。这是我们每一步的目标。

p θ ( x t − 1 ∣ x t ) p_θ(x_{t-1}|x_t) pθ(xt1xt):这是我们的 AI 模型在第 t 步实际做的事情,它只看到当前的 x_t,尝试猜测 x_{t-1} 应该是什么样子。我们也把它设计成一个高斯分布 N ( μ θ , σ t 2 I ) N(μ_θ, σ_t² I) N(μθ,σt2I)。这是 AI 的预测。

D K L ( . . . ) D_KL(...) DKL(...):KL 散度是衡量这两个概率分布(理想的 q 和 AI 预测的 p_θ)有多么“不像”或“差异多大”。

目标:为了最大化 ELBO,我们需要在每一步都最小化这个 KL 散度。我们希望 AI 的预测 (p_θ) 尽可能地接近理想目标 (q)。

  • 关键洞察与简化:

    • 在上式中,项 D K L ( q ( x T ∣ x 0 ) ∥ p ( x T ) ) D_{\mathrm{KL}}\big(q(x_T\mid x_0) \,\|\, p(x_T)\big) DKL(q(xTx0)p(xT)) 不依赖于模型参数 θ \theta θ,因此可忽略。

    • log ⁡ p θ ( x 0 ∣ x 1 ) \log p_\theta(x_0\mid x_1) logpθ(x0x1) 为最后一步的重构项。

    • 核心在于最小化每一步的 KL 散度:
      D K L ( q ( x t − 1 ∣ x t , x 0 ) ∥ p θ ( x t − 1 ∣ x t ) ) . D_{\mathrm{KL}}\big(q(x_{t-1}\mid x_t, x_0) \,\|\, p_\theta(x_{t-1}\mid x_t)\big). DKL(q(xt1xt,x0)pθ(xt1xt)).
      我们知道:

      • q ( x t − 1 ∣ x t , x 0 ) q(x_{t-1}\mid x_t, x_0) q(xt1xt,x0) 是高斯分布 N ( μ ~ t , β ~ t I ) \mathcal{N}(\tilde{\mu}_t,\, \tilde{\beta}_t\, I) N(μ~t,β~tI)
      • 模型 p θ ( x t − 1 ∣ x t ) p_\theta(x_{t-1}\mid x_t) pθ(xt1xt) 为高斯分布 N ( μ θ ( x t , t ) , σ t 2 I ) \mathcal{N}(\mu_\theta(x_t, t),\, \sigma_t^2\, I) N(μθ(xt,t),σt2I)(此处方差固定)。

      最小化这两个固定方差高斯分布之间的 KL 散度,主要等价于最小化它们均值之间的平方误差:
      ∥ μ ~ t ( x t , x 0 ) − μ θ ( x t , t ) ∥ 2 , \|\tilde{\mu}_t(x_t, x_0) - \mu_\theta(x_t, t)\|^2, μ~t(xt,x0)μθ(xt,t)2,
      (忽略那些不依赖于 θ \theta θ 的比例因子与常数项)。

  • 参数化技巧 (Noise Prediction):

    • 虽然可以直接让神经网络预测均值 μ θ \mu_\theta μθ 以匹配 μ ~ t \tilde{\mu}_t μ~t,但 Ho et al.(DDPM 论文)提出了一种更稳定且效果更好的方法:让神经网络 ε θ ( x t , t ) \varepsilon_\theta(x_t, t) εθ(xt,t) 预测在第 t t t 步加入的噪声 ε \varepsilon ε
    • 回忆前向过程公式:
      x t = α ˉ t x 0 + 1 − α ˉ t ε . x_t = \sqrt{\bar{\alpha}_t}\, x_0 + \sqrt{1 - \bar{\alpha}_t}\, \varepsilon. xt=αˉt x0+1αˉt ε.
      反解可得:
      x 0 = x t − 1 − α ˉ t ε α ˉ t . x_0 = \frac{x_t - \sqrt{1 - \bar{\alpha}_t}\, \varepsilon}{\sqrt{\bar{\alpha}_t}}. x0=αˉt xt1αˉt ε.
    • x 0 x_0 x0 带入 μ ~ t ( x t , x 0 ) \tilde{\mu}_t(x_t, x_0) μ~t(xt,x0) 的表达式后,可以证明 μ ~ t \tilde{\mu}_t μ~t 可以表示为 x t x_t xt ε \varepsilon ε 的函数。
    • 若采用下面的参数化形式,
      μ θ ( x t , t ) = 1 α t ( x t − β t 1 − α ˉ t ε θ ( x t , t ) ) , \mu_\theta(x_t, t) = \frac{1}{\sqrt{\alpha_t}} \left( x_t - \frac{\beta_t}{\sqrt{1 - \bar{\alpha}_t}}\, \varepsilon_\theta(x_t, t) \right), μθ(xt,t)=αt 1(xt1αˉt βtεθ(xt,t)),
      则最小化 ∥ μ ~ t − μ θ ∥ 2 \|\tilde{\mu}_t - \mu_\theta\|^2 μ~tμθ2 便等价于(忽略不依赖于 θ \theta θ 的系数)最小化
      ∥ ε − ε θ ( x t , t ) ∥ 2 . \|\varepsilon - \varepsilon_\theta(x_t, t)\|^2. εεθ(xt,t)2.
  • 最终的简化目标函数:
    实际训练中,我们通常最小化以下期望损失:
    L s i m p l e ( θ ) = E t , x 0 , ε [ ∥ ε − ε θ ( α ˉ t x 0 + 1 − α ˉ t ε , t ) ∥ 2 ] , L_{\mathrm{simple}}(\theta) = \mathbb{E}_{t,\, x_0,\, \varepsilon} \Big[ \big\|\varepsilon - \varepsilon_\theta\Big(\sqrt{\bar{\alpha}_t}\, x_0 + \sqrt{1 - \bar{\alpha}_t}\, \varepsilon,\, t\Big) \big\|^2 \Big], Lsimple(θ)=Et,x0,ε[ εεθ(αˉt x0+1αˉt ε,t) 2],
    其中:

    • t t t { 1 , … , T } \{1, \ldots, T\} {1,,T} 中均匀采样;
    • x 0 x_0 x0 来自真实数据分布 q ( x 0 ) q(x_0) q(x0) 的采样;
    • ε ∼ N ( 0 , I ) \varepsilon \sim \mathcal{N}(0, I) εN(0,I) 为标准高斯噪声;
    • ε θ \varepsilon_\theta εθ 为神经网络(通常采用 U-Net 结构),输入噪声图像 x t x_t xt 和时间步 t t t,输出预测的噪声 ε \varepsilon ε
    • ∣ ∣ ε − ε θ ( . . . ) ∣ ∣ 2 ||ε - ε_θ(...) ||² ∣∣εεθ(...)2:计算“真实噪声 ε”和“AI 预测的噪声 ε_θ”之间的平方差(也就是误差)。

这个基于 L2 的损失函数在实践中表现良好,具有训练稳定性和实现简便性。


4. 采样 (Sampling / Generation)

在模型训练完成后,生成新样本的过程如下:

  1. 初始化
    从标准高斯分布中采样初始噪声:
    x T ∼ N ( 0 , I ) . x_T \sim \mathcal{N}(0, I). xTN(0,I).

  2. 反向采样过程
    t t t T T T 递减至 1 1 1

    • t > 1 t > 1 t>1,从 N ( 0 , I ) \mathcal{N}(0, I) N(0,I) 中采样随机噪声 z z z;若 t = 1 t = 1 t=1,令 z = 0 z = 0 z=0
    • 利用训练好的神经网络计算噪声预测:
      ε pred = ε θ ( x t , t ) . \varepsilon_{\text{pred}} = \varepsilon_\theta(x_t, t). εpred=εθ(xt,t).
    • 计算反向过程的均值:
      μ θ ( x t , t ) = 1 α t ( x t − β t 1 − α ˉ t ε pred ) . \mu_\theta(x_t, t) = \frac{1}{\sqrt{\alpha_t}} \left( x_t - \frac{\beta_t}{\sqrt{1 - \bar{\alpha}_t}}\, \varepsilon_{\text{pred}} \right). μθ(xt,t)=αt 1(xt1αˉt βtεpred).
    • 使用固定标准差 σ t \sigma_t σt(通常有 σ t 2 = β ~ t \sigma_t^2 = \tilde{\beta}_t σt2=β~t σ t 2 = β t \sigma_t^2 = \beta_t σt2=βt)进行采样:
      x t − 1 = μ θ ( x t , t ) + σ t z . x_{t-1} = \mu_\theta(x_t, t) + \sigma_t\, z. xt1=μθ(xt,t)+σtz.
  3. 最终生成的 x 0 x_0 x0 为模型生成的样本。


总结关键数学概念

  • 马尔可夫链:
    前向过程与反向过程均被建模为马尔可夫链。

  • 高斯分布:
    高斯分布作为噪声模型和转移概率的核心,凭借其在做线性变换与求和时的闭合性质,使得前向过程可以得到闭式解。

  • 贝叶斯定理:
    用于推导条件后验 q ( x t − 1 ∣ x t , x 0 ) q(x_{t-1}\mid x_t, x_0) q(xt1xt,x0)

  • 变分推断 (Variational Inference):
    通过优化 ELBO 来实现近似最大化对数似然,从而解决直接优化似然困难的问题。

  • KL 散度:
    作为优化目标的一部分,用于衡量两个概率分布之间的差异。

  • 参数化技巧 (Reparameterization Trick):
    虽然此处采用的是预测噪声而非直接采样,但基本思想相似,即将随机性(噪声 ε \varepsilon ε)与模型参数分离,使得整个目标函数可微。预测噪声 ε \varepsilon ε 成为对反向过程均值 μ θ \mu_\theta μθ 的一种有效参数化方式。


请添加图片描述
总结训练算法: 反复地:① 拿张真图 → ② 随机加噪声(记住加了啥噪声)→ ③ 让 AI 猜加了啥噪声 → ④ 对比真实噪声和 AI 的猜测 → ⑤ 根据差距调整 AI → 直到 AI 成为猜噪声高手。

总结采样算法: ① 从纯噪声开始 → ② 反复 T 次(从 T 到 1):(a) 让训练好的 AI 预测当前图片中的噪声 → (b) 从图片中减掉预测的噪声 → © 调整一下图片 → (d) 再加一点点新的随机噪声(最后一步除外)→ ③ 得到最终生成的图片。

一系列问答

1. p θ p_\theta pθ 是模型本身吗?还是模型生成出好图片的概率?

  • p θ p_\theta pθ 代表的是模型本身,更准确地说,是由参数 θ \theta θ 定义的概率模型
  • θ \theta θ (theta) 代表神经网络的所有可学习参数(权重、偏置等)。
  • p θ ( x 0 ) p_\theta(x_0) pθ(x0) 不是“生成好图片的概率”,而是这个模型认为某张真实的、清晰的图片 x 0 x_0 x0 出现的概率密度。你可以理解为,模型根据它学到的知识,判断 x 0 x_0 x0 这张图片有多么“合理”或“像它应该生成的东西”。
  • 我们的目标是调整参数 θ \theta θ,使得模型 p θ p_\theta pθ 对于所有真实的训练图片 x 0 x_0 x0 都给出尽可能高的概率密度值。也就是说,让模型觉得真实图片都是非常“合理”的。

2. ELBO 推导: L V L B L_{VLB} LVLB 为什么等于右边?

这里涉及两个等式,我们分开解释:

  • 第一个等式:

    L V L B = E q [ log ⁡ p θ ( x 0 : T ) q ( x 1 : T ∣ x 0 ) ] L_{VLB} = \mathbb{E}_q\left[\log\frac{p_\theta(x_{0:T})}{q(x_{1:T}\mid x_0)}\right] LVLB=Eq[logq(x1:Tx0)pθ(x0:T)]

    • 这是 ELBO 的标准定义,源自变分推断理论。它直接关联了我们想最大化的 log ⁡ p θ ( x 0 ) \log p_\theta(x_0) logpθ(x0) 和一个可以计算的量。
    • p θ ( x 0 : T ) p_\theta(x_{0:T}) pθ(x0:T):表示根据我们的模型 p θ p_\theta pθ(包括反向去噪过程 p θ ( x t − 1 ∣ x t ) p_\theta(x_{t-1}\mid x_t) pθ(xt1xt) 和最终噪声假设 p ( x T ) p(x_T) p(xT)),从噪声 x T x_T xT 一路生成到 x 0 x_0 x0 并经历中间状态 x 1 x_1 x1 x T − 1 x_{T-1} xT1整个完整路径的联合概率。
    • q ( x 1 : T ∣ x 0 ) q(x_{1:T}\mid x_0) q(x1:Tx0):表示根据固定的前向加噪过程 q q q,从清晰图片 x 0 x_0 x0 出发,生成噪声序列 x 1 x_1 x1 x T x_T xT 的联合概率。
    • log ⁡ ( ⋅ ) \log(\cdot) log():取对数。
    • E q ( ⋅ ) \mathbb{E}_q(\cdot) Eq():表示对所有可能的噪声序列(由 q ( x 1 : T ∣ x 0 ) q(x_{1:T}\mid x_0) q(x1:Tx0) 定义)求平均值(期望)
    • 这个公式的意义在于,它把难以计算的 log ⁡ p θ ( x 0 ) \log p_\theta(x_0) logpθ(x0) 与一个涉及模型 p θ p_\theta pθ 与已知过程 q q q 的表达式联系起来,并且知道前者总是大于等于后者(所以叫下界)。
  • 第二个等式(“通常写作”):

    L V L B = E q [ log ⁡ p ( x T ) + ∑ t = 1 T log ⁡ p θ ( x t − 1 ∣ x t ) q ( x t ∣ x t − 1 ) ] L_{VLB} = \mathbb{E}_q\left[\log p(x_T) + \sum_{t=1}^T \log\frac{p_\theta(x_{t-1}\mid x_t)}{q(x_t\mid x_{t-1})}\right] LVLB=Eq[logp(xT)+t=1Tlogq(xtxt1)pθ(xt1xt)]

    • 这个等式是通过对第一个等式中的 log ⁡ p θ ( x 0 : T ) q ( x 1 : T ∣ x 0 ) \log\frac{p_\theta(x_{0:T})}{q(x_{1:T}\mid x_0)} logq(x1:Tx0)pθ(x0:T) 进行代数展开和重新组合得到的。
    • 怎么推的?
      1. p θ ( x 0 : T ) p_\theta(x_{0:T}) pθ(x0:T) 写成因子连乘:
        p ( x T ) ⋅ p θ ( x T − 1 ∣ x T ) ⋯ p θ ( x 0 ∣ x 1 ) p(x_T) \cdot p_\theta(x_{T-1}\mid x_T) \cdots p_\theta(x_0\mid x_1) p(xT)pθ(xT1xT)pθ(x0x1)
      2. q ( x 1 : T ∣ x 0 ) q(x_{1:T}\mid x_0) q(x1:Tx0) 写成因子连乘:
        q ( x T ∣ x T − 1 ) ⋯ q ( x 1 ∣ x 0 ) q(x_T\mid x_{T-1}) \cdots q(x_1\mid x_0) q(xTxT1)q(x1x0)
      3. 利用 log ⁡ A B = log ⁡ A − log ⁡ B \log\frac{A}{B} = \log A - \log B logBA=logAlogB log ⁡ ( A ⋅ B ⋅ … ) = log ⁡ A + log ⁡ B + … \log(A\cdot B\cdot\ldots) = \log A + \log B + \ldots log(AB)=logA+logB+
      4. 经过整理,就可以把对整个序列的联合概率的对数,变成对每一步转移概率比值的对数求和,再加上初始噪声项 log ⁡ p ( x T ) \log p(x_T) logp(xT)
    • 这种形式更有用,因为它把复杂的整体概率分解成了一步一步的过程,更容易分析和优化。

3. KL 散度 (Kullback-Leibler Divergence)

  • 是什么?
    KL 散度是衡量**两个概率分布 P P P Q Q Q 有多“不像”**的一种方式。它的值 D K L ( P ∥ Q ) D_{KL}(P \parallel Q) DKL(PQ) 告诉你,如果你用分布 Q Q Q 来近似分布 P P P,你会损失多少信息,或者说 Q Q Q 相比于 P P P 有多少“意外之处”。
  • 如何衡量相似性?
    • KL 散度的值总是大于等于 0 0 0
    • 当且仅当两个分布 P P P Q Q Q 完全相同时,KL 散度等于 0 0 0
    • KL 散度的值越小,表示两个分布越相似、越接近;而值越大,则差异越大。
  • 通俗类比:
    • 想象 P P P 是某城市真实的地图,而 Q Q Q 是你画的一张草图
    • KL 散度 D K L ( P ∥ Q ) D_{KL}(P \parallel Q) DKL(PQ) 就好比在衡量你这张草图 Q Q Q 与真实地图 P P P 比较,有多么“不准确”或“误导人”。
    • 如果你的草图画得非常好,与真实地图几乎一致,那么 KL 散度就非常接近 0 0 0;如果画得很离谱,则 KL 散度会很大。
    • 注意:
      KL 散度具有不对称性,即 D K L ( P ∥ Q ) D_{KL}(P \parallel Q) DKL(PQ) 通常不等于 D K L ( Q ∥ P ) D_{KL}(Q \parallel P) DKL(QP)。在这个记号中, P P P 被视为基准(真实地图),而 Q Q Q 是要比较的对象(草图)。

4. E q E_q Eq 是什么意思? q q q 是什么意思?

  • E q E_q Eq
    是“期望 (Expectation)”符号,下标 q q q 表示这个期望是根据概率分布 q q q 来计算的。
  • q q q
    在 Diffusion Model 的语境中, q q q 指代的是由前向(加噪)过程定义的一系列概率分布:
    • q ( x 0 ) q(x_0) q(x0):真实清晰图片的分布(你的数据集)。
    • q ( x t ∣ x t − 1 ) q(x_t \mid x_{t-1}) q(xtxt1):从 x t − 1 x_{t-1} xt1 x t x_t xt 的单步加噪概率(固定的)。
    • q ( x 1 : T ∣ x 0 ) q(x_{1:T} \mid x_0) q(x1:Tx0):给定 x 0 x_0 x0,生成整个噪声序列 x 1 , … , x T x_1, \dots, x_T x1,,xT 的概率(固定的)。
    • q ( x t ∣ x 0 ) q(x_t \mid x_0) q(xtx0):给定 x 0 x_0 x0,得到第 t t t 步噪声图片 x t x_t xt 的概率(有闭式解,固定的)。
    • q ( x t − 1 ∣ x t , x 0 ) q(x_{t-1} \mid x_t, x_0) q(xt1xt,x0):给定 x t x_t xt x 0 x_0 x0,反推 x t − 1 x_{t-1} xt1 的概率(需要用到 x 0 x_0 x0,但也是基于 q q q 推导出来的)。
  • 所以, E q [ … ] E_q[\ldots] Eq[] 意味着在整个由前向过程定义的所有可能性(包括选择哪个 x 0 x_0 x0,以及基于 x 0 x_0 x0 生成的噪声序列 x 1 : T x_{1:T} x1:T)上求平均值

5. 最小化 KL 散度的过程是怎样的?

  • 目标是最小化
    D K L ( q ( x t − 1 ∣ x t , x 0 ) ∥ p θ ( x t − 1 ∣ x t ) ) D_{KL}(q(x_{t-1}\mid x_t, x_0) \parallel p_\theta(x_{t-1}\mid x_t)) DKL(q(xt1xt,x0)pθ(xt1xt))
    这里的 θ \theta θ 是我们唯一能调整的内容(仅存在于 p θ p_\theta pθ 中)。
  • 这个过程即梯度下降 (Gradient Descent)
    1. 计算损失:
      对于一个训练样本(包括 x 0 x_0 x0, t t t, ϵ \epsilon ϵ,从而得到 x t x_t xt 和目标分布 q q q),计算当前的 KL 散度值(或与之等价、但更容易计算的目标,例如后面提到的均值平方差)。这个值即表示当前的“误差”或“损失”。
    2. 计算梯度:
      计算该损失相对于模型参数 θ \theta θ 中每个参数的偏导数(梯度),这些梯度指明了参数该如何调整以使损失减少最快。
    3. 更新参数:
      将每个参数 θ \theta θ 沿着梯度的反方向调整一小步:
      θ 新 = θ 旧 − 学习率 × ∇ θ Loss \theta_{\text{新}} = \theta_{\text{旧}} - \text{学习率} \times \nabla_\theta \text{Loss} θ=θ学习率×θLoss
      这样便使得损失函数值略微减少。
    4. 重复:
      对大量不同的训练样本和时间步重复上述过程,参数 θ \theta θ 将逐步趋向于使 KL 散度(平均而言)最小化的状态。

6. 什么叫重构项?

  • “重构项”(Reconstruction Term)通常指损失函数中衡量模型从某种编码或加噪表示恢复出原始(或目标)数据的能力的部分。
  • 在 ELBO 的分解中
    L V L B = E q [ log ⁡ p θ ( x 0 ∣ x 1 ) ] − … L_{VLB} = \mathbb{E}_q\big[\log p_\theta(x_0\mid x_1)\big] - \ldots LVLB=Eq[logpθ(x0x1)]
    中, log ⁡ p θ ( x 0 ∣ x 1 ) \log p_\theta(x_0\mid x_1) logpθ(x0x1) 就是最后一步的重构项。它直接反映了模型从最后一个噪声状态 x 1 x_1 x1 中“重构”出清晰图像 x 0 x_0 x0 的效果(通过概率高低来度量)。
  • 更广义地看,每一个 KL 散度项
    D K L ( q ( … ) ∥ p θ ( … ) ) D_{KL}(q(\ldots) \parallel p_\theta(\ldots)) DKL(q()pθ())
    也可视为 t t t 步的“重构损失”,因为它衡量了模型反向过程 p θ p_\theta pθ 与理想反向过程 q q q 之间的差距。

7. 双竖线 ∣ ∣ || ∣∣ 是什么意思? p p p q q q 是概率分布吗?

  • 正解! p p p q q q 都代表概率分布
  • D K L ( P ∥ Q ) D_{KL}(P \parallel Q) DKL(PQ) 中,双竖线 ∣ ∣ || ∣∣ 只是 KL 散度的标准记号,用来分隔比较的两个概率分布 P P P Q Q Q。这符号本身没有其他独立的数学运算意义,仅是记号的一部分。

8. 应该如何最小化它们的平方误差?

  • 我们要最小化的目标为
    Loss = ∥ μ ~ t ( x t , x 0 ) − μ θ ( x t , t ) ∥ 2 \text{Loss} = \|\tilde{\mu}_t(x_t, x_0) - \mu_\theta(x_t, t)\|^2 Loss=μ~t(xt,x0)μθ(xt,t)2
  • 如何做? 这正是梯度下降的核心应用:
    1. 前向传播:
      • 给定 x t x_t xt t t t,将它们输入到神经网络 ϵ θ \epsilon_\theta ϵθ,得到输出 ϵ θ ( x t , t ) \epsilon_\theta(x_t, t) ϵθ(xt,t)
      • 利用 ϵ θ ( x t , t ) \epsilon_\theta(x_t, t) ϵθ(xt,t) x t x_t xt, t t t,通过 μ θ \mu_\theta μθ 的公式计算出 μ θ ( x t , t ) \mu_\theta(x_t, t) μθ(xt,t)
      • 同时,由于训练时有 x 0 x_0 x0,可以计算出目标均值 μ ~ t ( x t , x 0 ) \tilde{\mu}_t(x_t, x_0) μ~t(xt,x0)
    2. 计算损失:
      计算损失:
      Loss = ∥ μ ~ t ( x t , x 0 ) − μ θ ( x t , t ) ∥ 2 \text{Loss} = \|\tilde{\mu}_t(x_t, x_0) - \mu_\theta(x_t, t)\|^2 Loss=μ~t(xt,x0)μθ(xt,t)2
      (这里的 ∥ ⋅ ∥ 2 \|\cdot\|^2 2 表示向量各元素差的平方和)。
    3. 反向传播:
      • 利用微积分中的链式法则,计算 Loss \text{Loss} Loss 关于 μ θ \mu_\theta μθ 的梯度。
      • 再计算 μ θ \mu_\theta μθ 关于 ϵ θ ( x t , t ) \epsilon_\theta(x_t, t) ϵθ(xt,t) 的梯度。
      • 最终,计算 Loss \text{Loss} Loss 对神经网络内部所有参数 θ \theta θ 的梯度,这正是反向传播算法的工作。
    4. 参数更新:
      使用计算得到的梯度 ∇ θ Loss \nabla_\theta \text{Loss} θLoss 来更新 θ \theta θ
      θ 新 = θ 旧 − 学习率 × ∇ θ Loss \theta_{\text{新}} = \theta_{\text{旧}} - \text{学习率} \times \nabla_\theta \text{Loss} θ=θ学习率×θLoss

9. ϵ θ \epsilon_\theta ϵθ 具体是个什么东西?是模型输出的结果吗?

  • ϵ θ \epsilon_\theta ϵθ 是那个核心的神经网络本身。它是一个函数,其具体形式取决于内部的层、连接和参数 θ \theta θ 的设置。
  • 输入:
    它接受两个输入:当前的噪声图片 x t x_t xt以及当前的时间步 t t t(通常会编码为一个向量)。
  • 输出:
    它的输出是一个与输入图片 x t x_t xt 尺寸相同的张量,这个输出即是模型对噪声 ϵ \epsilon ϵ 的预测结果
  • 因此, ϵ θ ( x t , t ) \epsilon_\theta(x_t, t) ϵθ(xt,t) 就是神经网络模型针对输入 ( x t , t ) (x_t, t) (xt,t) 所计算出的具体输出值
    它并非一个概率,而是模型基于“为了得到 x t x_t xt,当初可能加入了什么噪声”这一问题给出的具体猜测(一个噪声向量/图像)。训练的目标正是使得 ϵ θ ( x t , t ) \epsilon_\theta(x_t, t) ϵθ(xt,t) 尽可能接近真实噪声 ϵ \epsilon ϵ

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/75755.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

华为项目管理“六步一法”方法论全解析:目标确认、项目活动分解与日事清系统协同

大家都知道&#xff0c;项目管理在现在各个行业里都是越来越重要了。 要是搞不好&#xff0c;项目就会拖沓&#xff0c;甚至走向失败。 今天咱们就来聊聊华为是怎么做项目管理的&#xff0c;比较知名的就是它们的“六步一法”。华为通过“六步一法”来进行项目管理&#xff0…

OpenCV 图形API(9)用于执行矩阵与标量之间的逐元素除法操作函数divC()

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 矩阵除以标量。 该函数 divC 将矩阵 src 的每个元素除以给定的标量值&#xff1a; dst(I) saturate(src(I)*scale/divisor) \texttt{dst(I) s…

单例模式(懒汉模式/饿汉模式)

相关概念参考&#xff1a;【C】C 单例模式总结&#xff08;5种单例实现方法&#xff09;_单例模式c实现-CSDN博客 #include<iostream>class LazySingle{ public:static LazySingle& getInstance(){static LazySingle instance;return instance;}void hello(){std::c…

RocketMQ初认识

ProducerCustomerNameServer: Broker的注册服务发现中心BrokerServer:主要负责消息的存储、投递和查询以及服务高可用保证 RocketMQ的集群部署&#xff1a; 单个master的分支多个Master 模式&#xff1a;集群中有多个 Master 节点&#xff0c;彼此之间相互独立。生产者可以将消…

Maven/Gradle的讲解

一、为什么需要构建工具? 在理解 Maven/Gradle 之前,先明确它们解决的问题: ​​依赖管理​​:项目中可能需要引入第三方库(如 Spring、JUnit 等),手动下载和管理这些库的版本非常麻烦。​​标准化构建流程​​:编译代码、运行测试、打包成 JAR/WAR 文件等步骤需要自动…

基于SSM的车辆管理系统的设计与实现(代码+数据库+LW)

摘要 当下&#xff0c;正处于信息化的时代&#xff0c;许多行业顺应时代的变化&#xff0c;结合使用计算机技术向数字化、信息化建设迈进。以前企业对于车辆信息的管理和控制&#xff0c;采用人工登记的方式保存相关数据&#xff0c;这种以人力为主的管理模式已然落后。本人结…

嵌入式硬件篇---JSON通信以及解析

文章目录 前言一、JSON特点语法简单数据格式灵活轻量化跨语言使用二、JSON数据结构对象数组三、JSON在单片机之间通信的应用数据封装与传输四、JSON示例代码五、JSON在上位机与单片机之间通信的应用数据交互六、JSON示例代码七、JSON解析与生成解析生成八、Python中的数据解析1…

【C#】.net core 6.0 依赖注入常见问题之一,在构造函数使用的类,都需要注入到容器里,否则会提示如下报错,让DeepSeek找找原因,看看效果

&#x1f339;欢迎来到《小5讲堂》&#x1f339; &#x1f339;这是《C#》系列文章&#xff0c;每篇文章将以博主理解的角度展开讲解。&#x1f339; &#x1f339;温馨提示&#xff1a;博主能力有限&#xff0c;理解水平有限&#xff0c;若有不对之处望指正&#xff01;&#…

《P1072 [NOIP 2009 提高组] Hankson 的趣味题》

题目描述 Hanks 博士是 BT&#xff08;Bio-Tech&#xff0c;生物技术) 领域的知名专家&#xff0c;他的儿子名叫 Hankson。现在&#xff0c;刚刚放学回家的 Hankson 正在思考一个有趣的问题。 今天在课堂上&#xff0c;老师讲解了如何求两个正整数 c1​ 和 c2​ 的最大公约数…

nginx的自动跳转https

mkdir /usr/local/nginx/certs/ 创建一个目录 然后用openssl生成证书 编辑nginx的配置文件 自动跳转成功 做一个优化&#xff0c;如果访问的时候后面加了其他的uri也一起自动跳转了

力扣刷题——508.出现次数最多的子树和

给你一个二叉树的根结点 root &#xff0c;请返回出现次数最多的子树元素和。如果有多个元素出现的次数相同&#xff0c;返回所有出现次数最多的子树元素和&#xff08;不限顺序&#xff09;。 一个结点的 「子树元素和」 定义为以该结点为根的二叉树上所有结点的元素之和&…

2025/4/2 心得

第一题 题目描述 给定1001个范围在[1,1000]的数字&#xff0c;保证只有1个数字重复出现2次&#xff0c;其余数字只出现1次。试用O(n)时间复杂度来求出出现2次的这个数字。 不允许用数组 输入格式 第一行&#xff1a;一个整数1001&#xff1b; 第二行&#xff1a;1001个用…

0基础 | 硬件 | NE555芯片 二

目录 “双稳态电路之按键开关LED” 版本一&#xff1a; 版本二&#xff1a; “单稳态电路之延时自动关” 版本一 “无稳态电路之延时自动开关” 版本一&#xff1a; 版本二 “双稳态电路之按键开关LED” 版本一&#xff1a; 按键1 使2脚输入低电平&#xff0c;则3输出…

Python实现链接KS3,并将文件数据上传到KS3

前言 本文是该专栏的第55篇,后面会持续分享python的各种干货知识,值得关注。 说到KS3,首先想到的是金山云提供的对象存储服务。 相信或多或少的同学,在工作项目中也会遇到KS3相关的需求。比如说,现在有大批量的数据文件需要通过Python,上传到KS3中。对此,需要怎么去做…

小白 解析thingsboard 规则链节点

目录 1、filter(筛选器)节点内容 1. Alarm Status Filter(报警状态过滤器) 2. Check Fields Presence(检查字段存在性过滤器) 3. Check Relation Presence(检查关系存在性过滤器) 4. Entity Type Filter(实体类型过滤器) 5. Message Type Filter(消息类型过滤器…

PgVectore的使用

PgVectore的使用 一、PgVector的安装 参照博客&#xff1a;https://blog.csdn.net/u012953777/article/details/147013691?spm1001.2014.3001.5501 二、PgVector的使用 1、创建表与插入数据​ ​​定义向量字段​​&#xff1a; CREATE TABLE items (id SERIAL PRIMARY …

python爬虫爬取淘宝热销(热门)男装商品信息(课程设计;提供源码、使用说明文档及相关文档;售后可联系博主)

TOC 本文仅为记录学习轨迹&#xff0c;如有侵权,联系删除 一、环境说明 使用前必须检查以下环境 &#xff08;1&#xff09;python编译环境 &#xff08;2&#xff09;python脚本执行所需要的库&#xff0c;具体看代码&#xff08;main.py&#xff09;import导入的部分库 &a…

C++ 排序(1)

以下是一些插入排序的代码 1.插入排序 1.直接插入排序 // 升序 // 最坏&#xff1a;O(N^2) 逆序 // 最好&#xff1a;O(N) 顺序有序 void InsertSort(vector<int>& a, int n) {for (int i 1; i < n; i){int end i - 1;int tmp a[i];// 将tmp插入到[0,en…

计算机视觉图像处理基础系列:滤波、边缘检测与形态学操作

计算机视觉图像处理基础系列&#xff1a;滤波、边缘检测与形态学操作 一、前言二、滤波&#xff1a;图像的精细化处理​2.1 滤波基础概念​2.1.1 滤波的本质​2.1.2 图像噪声来源与类型​ 2.2 线性滤波​2.2.1 均值滤波​2.2.2 高斯滤波​ 2.3 非线性滤波​2.3.1 中值滤波​ 三…

第八课:在SD中安装拓展插件

3种拓展安装方式教学 点击Extensions安装方式 经由内置列表查询安装&#xff0c;打开Available&#xff0c;输入链接&#xff0c;点击Load from:&#xff0c;然后筛选后点击Install通过链接安装&#xff0c;复制代码仓库地址&#xff0c;github/gitee&#xff0c;输入Install …