重生之我是去噪高手——diffusion model
diffusion model是如何运作的?
想象一下,你有一张清晰的图片。扩散模型的核心思想分为两个过程:
- 前向过程(Forward Process / Diffusion Process):逐步加噪
- 反向过程(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} xt−1 中加入少量的高斯噪声,得到 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} xt−1。
- 由于高斯噪声的良好特性,我们可以直接计算出任意步骤 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} xt−1 得到 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} xt−1。
- 这个过程从 t = T t = T t=T 开始,输入一个随机噪声 x T x_T xT,然后利用神经网络反复预测并去除噪声,一步步得到 x T − 1 x_{T-1} xT−1, x T − 2 x_{T-2} xT−2, …, 直到 x 0 x_0 x0。最终得到的 x 0 x_0 x0 就是模型生成的图片。
- 这个神经网络模型(我们称之为 ϵ θ \epsilon_\theta ϵθ,其中 θ \theta θ 是网络参数)的输入是:
-
关键点:
- 这是模型需要 学习 的部分。
- 学习的目标是让神经网络预测的噪声尽可能接近前向过程中实际添加的噪声。
类比:
想象观看墨水扩散的录像带并倒放。神经网络就像一个“物理学家”,它学习如何在每个时间点精确地把扩散开的墨水粒子“收回”一点点,最终恢复成一滴清晰的墨水。
训练过程(如何学习去噪)
模型是如何学会预测噪声的呢?
- 从训练数据集中随机抽取一张真实的图片 x 0 x_0 x0。
- 随机选择一个时间步 t t t(在 1 到 T T T 之间)。
- 利用前向过程的公式,直接计算出在 t t t 时刻,向 x 0 x_0 x0 加入适量噪声后得到的噪声图像 x t x_t xt。同时,我们知道实际加入的噪声 ϵ \epsilon ϵ 是什么。
- 将 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) 和实际噪声 ϵ \epsilon ϵ 之间的差异(例如,使用均方误差 L2 loss)。这个差异就是模型的“错误”或损失(loss)。
- 使用反向传播和优化算法(如 Adam)调整神经网络的参数 θ \theta θ,使得这个损失尽可能小。
- 重复以上步骤,使用大量的训练图片和不同的时间步 t t t。
通过这个过程,神经网络逐渐学会了在任何噪声水平 t t t 下,从噪声图像 x t x_t xt 中准确地识别并预测出被添加的噪声。
生成新图片(Sampling)
训练完成后,如何生成一张全新的图片?
- 从一个标准高斯分布(纯随机噪声)中采样得到一个初始图像 x T x_T xT。
- 从 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} xt−1。(这个公式通常还会包含一个随机项,以增加生成的多样性)。
- 当 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} xt−1 到 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(xt∣xt−1)=N(xt;1−βtxt−1,β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−βtxt−1 表示对上一步状态的轻微缩放。
- β t I \beta_t\, I βtI 是加入的高斯噪声的协方差矩阵(其中 I I I 为单位矩阵)。
- β t \beta_t βt 是一个预先设定的(通常很小的)方差值,代表在第 t t t 步加入的噪声强度。
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:T∣x0)=t=1∏Tq(xt∣xt−1). -
重要特性 (采样 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=1∏tα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(xt∣x0)=N(xt;αˉtx0,(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=αˉtx0+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) xT∼N(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(xt−1∣xt)。 -
挑战:
直接计算真实后验 q ( x t − 1 ∣ x t ) q(x_{t-1} \mid x_t) q(xt−1∣xt) 比较困难,因为它需要考虑整个数据集的信息。但如果同时条件化 x 0 x_0 x0,则后验 q ( x t − 1 ∣ x t , x 0 ) q(x_{t-1} \mid x_t, x_0) q(xt−1∣xt,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(xt−1∣xt,x0)=N(xt−1;μ~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αˉt−1βtx0+1−αˉtαt(1−αˉt−1)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−αˉt−1β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θ(xt−1∣xt)=N(xt−1;μθ(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) xT∼N(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). xt−1∼pθ(xt−1∣xt).
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:T∣x0)[logq(x1:T∣x0)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=1∑Tlogq(xt∣xt−1)pθ(xt−1∣xt)],
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θ(x0∣x1)]−DKL(q(xT∣x0)∥p(xT))−t=2∑TEq[DKL(q(xt−1∣xt,x0)∥pθ(xt−1∣xt))].
PS: p θ ( x 0 ∣ x 1 ) p_θ(x₀|x₁) pθ(x0∣x1):表示 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(xT∣x0)∣∣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(xt−1∣xt,x0)∣∣pθ(xt−1∣xt))] (一步步去噪的匹配 - 核心部分!):
这是训练中最重要的部分。它是对所有中间去噪步骤(从 t=T 到 t=2)求和。
q ( x t − 1 ∣ x t , x 0 ) q(x_{t-1}|x_t, x_0) q(xt−1∣xt,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θ(xt−1∣xt):这是我们的 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(xT∣x0)∥p(xT)) 不依赖于模型参数 θ \theta θ,因此可忽略。
-
log p θ ( x 0 ∣ x 1 ) \log p_\theta(x_0\mid x_1) logpθ(x0∣x1) 为最后一步的重构项。
-
核心在于最小化每一步的 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(xt−1∣xt,x0)∥pθ(xt−1∣xt)).
我们知道:- q ( x t − 1 ∣ x t , x 0 ) q(x_{t-1}\mid x_t, x_0) q(xt−1∣xt,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θ(xt−1∣xt) 为高斯分布 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=αˉtx0+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=αˉtxt−1−αˉ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)=αt1(xt−1−αˉ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,ε[ ε−εθ(αˉtx0+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)
在模型训练完成后,生成新样本的过程如下:
-
初始化
从标准高斯分布中采样初始噪声:
x T ∼ N ( 0 , I ) . x_T \sim \mathcal{N}(0, I). xT∼N(0,I). -
反向采样过程
对 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)=αt1(xt−1−αˉ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. xt−1=μθ(xt,t)+σtz.
-
最终生成的 x 0 x_0 x0 为模型生成的样本。
总结关键数学概念
-
马尔可夫链:
前向过程与反向过程均被建模为马尔可夫链。 -
高斯分布:
高斯分布作为噪声模型和转移概率的核心,凭借其在做线性变换与求和时的闭合性质,使得前向过程可以得到闭式解。 -
贝叶斯定理:
用于推导条件后验 q ( x t − 1 ∣ x t , x 0 ) q(x_{t-1}\mid x_t, x_0) q(xt−1∣xt,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:T∣x0)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θ(xt−1∣xt) 和最终噪声假设 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} xT−1 的整个完整路径的联合概率。
- q ( x 1 : T ∣ x 0 ) q(x_{1:T}\mid x_0) q(x1:T∣x0):表示根据固定的前向加噪过程 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:T∣x0) 定义)求平均值(期望)。
- 这个公式的意义在于,它把难以计算的 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=1∑Tlogq(xt∣xt−1)pθ(xt−1∣xt)]
- 这个等式是通过对第一个等式中的 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:T∣x0)pθ(x0:T) 进行代数展开和重新组合得到的。
- 怎么推的?
- 把 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θ(xT−1∣xT)⋯pθ(x0∣x1) - 把 q ( x 1 : T ∣ x 0 ) q(x_{1:T}\mid x_0) q(x1:T∣x0) 写成因子连乘:
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(xT∣xT−1)⋯q(x1∣x0) - 利用 log A B = log A − log B \log\frac{A}{B} = \log A - \log B logBA=logA−logB 和 log ( A ⋅ B ⋅ … ) = log A + log B + … \log(A\cdot B\cdot\ldots) = \log A + \log B + \ldots log(A⋅B⋅…)=logA+logB+…
- 经过整理,就可以把对整个序列的联合概率的对数,变成对每一步转移概率比值的对数求和,再加上初始噪声项 log p ( x T ) \log p(x_T) logp(xT)。
- 把 p θ ( x 0 : T ) p_\theta(x_{0:T}) pθ(x0:T) 写成因子连乘:
- 这种形式更有用,因为它把复杂的整体概率分解成了一步一步的过程,更容易分析和优化。
3. KL 散度 (Kullback-Leibler Divergence)
- 是什么?
KL 散度是衡量**两个概率分布 P P P 和 Q Q Q 有多“不像”**的一种方式。它的值 D K L ( P ∥ Q ) D_{KL}(P \parallel Q) DKL(P∥Q) 告诉你,如果你用分布 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(P∥Q) 就好比在衡量你这张草图 Q Q Q 与真实地图 P P P 比较,有多么“不准确”或“误导人”。
- 如果你的草图画得非常好,与真实地图几乎一致,那么 KL 散度就非常接近 0 0 0;如果画得很离谱,则 KL 散度会很大。
- 注意:
KL 散度具有不对称性,即 D K L ( P ∥ Q ) D_{KL}(P \parallel Q) DKL(P∥Q) 通常不等于 D K L ( Q ∥ P ) D_{KL}(Q \parallel P) DKL(Q∥P)。在这个记号中, 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(xt∣xt−1):从 x t − 1 x_{t-1} xt−1 到 x t x_t xt 的单步加噪概率(固定的)。
- q ( x 1 : T ∣ x 0 ) q(x_{1:T} \mid x_0) q(x1:T∣x0):给定 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(xt∣x0):给定 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(xt−1∣xt,x0):给定 x t x_t xt 和 x 0 x_0 x0,反推 x t − 1 x_{t-1} xt−1 的概率(需要用到 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(xt−1∣xt,x0)∥pθ(xt−1∣xt))
这里的 θ \theta θ 是我们唯一能调整的内容(仅存在于 p θ p_\theta pθ 中)。 - 这个过程即梯度下降 (Gradient Descent):
- 计算损失:
对于一个训练样本(包括 x 0 x_0 x0, t t t, ϵ \epsilon ϵ,从而得到 x t x_t xt 和目标分布 q q q),计算当前的 KL 散度值(或与之等价、但更容易计算的目标,例如后面提到的均值平方差)。这个值即表示当前的“误差”或“损失”。 - 计算梯度:
计算该损失相对于模型参数 θ \theta θ 中每个参数的偏导数(梯度),这些梯度指明了参数该如何调整以使损失减少最快。 - 更新参数:
将每个参数 θ \theta θ 沿着梯度的反方向调整一小步:
θ 新 = θ 旧 − 学习率 × ∇ θ Loss \theta_{\text{新}} = \theta_{\text{旧}} - \text{学习率} \times \nabla_\theta \text{Loss} θ新=θ旧−学习率×∇θLoss
这样便使得损失函数值略微减少。 - 重复:
对大量不同的训练样本和时间步重复上述过程,参数 θ \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θ(x0∣x1)]−…
中, log p θ ( x 0 ∣ x 1 ) \log p_\theta(x_0\mid x_1) logpθ(x0∣x1) 就是最后一步的重构项。它直接反映了模型从最后一个噪声状态 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(P∥Q) 中,双竖线 ∣ ∣ || ∣∣ 只是 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 - 如何做? 这正是梯度下降的核心应用:
- 前向传播:
- 给定 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)。
- 计算损失:
计算损失:
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 表示向量各元素差的平方和)。 - 反向传播:
- 利用微积分中的链式法则,计算 Loss \text{Loss} Loss 关于 μ θ \mu_\theta μθ 的梯度。
- 再计算 μ θ \mu_\theta μθ 关于 ϵ θ ( x t , t ) \epsilon_\theta(x_t, t) ϵθ(xt,t) 的梯度。
- 最终,计算 Loss \text{Loss} Loss 对神经网络内部所有参数 θ \theta θ 的梯度,这正是反向传播算法的工作。
- 参数更新:
使用计算得到的梯度 ∇ θ 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 ϵ。
相关文章:
重生之我是去噪高手——diffusion model
diffusion model是如何运作的? 想象一下,你有一张清晰的图片。扩散模型的核心思想分为两个过程: 前向过程(Forward Process / Diffusion Process):逐步加噪反向过程(Reverse Process / Denois…...
FfreeRTOS有阻塞作用的API
在 FreeRTOS 中,阻塞 API 是指那些会导致调用任务进入阻塞状态(Blocked State)的函数,即任务会暂时让出 CPU,直到某个条件满足(如超时、信号量可用、队列数据到达等)。以下是常见的阻塞 API 分类及示例: 1. 任务延迟(延时) vTaskDelay() 使任务阻塞指定的时间(以系统…...
app逆向专题二:app逆向流程
app逆向专题二:app逆向流程 一、app逆向说明二、拿到APP应用的apk三、使用工具进行查壳四、有壳需要先进行脱壳,拿到dex文件进行反编译五、使用Jadx-Gui或其他工具进行反编译,分析源码;六、根据app的抓包情况拿到加密的关键词参数…...
VMware 安装 Ubuntu 全流程实战指南:从零搭建到深度优化
在软件开发、系统测试以及技术学习等诸多场景中,使用虚拟机安装操作系统是一种灵活且高效的方式。Ubuntu 作为一款优秀的开源操作系统,在 VMware 虚拟机上的安装与优化备受关注。接下来,将为大家带来 VMware 安装 Ubuntu 的全流程实战指南&am…...
论文阅读笔记——RDT-1B: A DIFFUSION FOUNDATION MODEL FOR BIMANUAL MANIPULATION
RDT-1B 论文 模型表达与泛化能力:由于双臂操作中动作空间维度是单臂空间的两倍,传统方法难以建模其多模态分布。 数据:双臂数据少且不同机器人的物理结构和动作空间差异(如关节数、运动范围)导致数据分布不一致&#x…...
如何一天背300到500个单词
买一本有结构分析或词源注释的目标词汇书。 买一盒口香糖。 准备一摞空白的A4纸。 找一间用于冥想的黑屋子(眼晴闭上就可以了)。 将要背诵的单词进行分组: 5个一小组10个一中组50个一大组100个一个基本包或单元。给自己一个约定,比如背完一中组或一大组单词,嚼一粒口香糖…...
vs环境中编译osg以及osgQt
1、下载 OpenSceneGraph 获取源代码 您可以通过以下方式获取 OSG 源代码: 官网下载:https://github.com/openscenegraph/OpenSceneGraph/releases 使用 git 克隆: git clone https://github.com/openscenegraph/OpenSceneGraph.git 2、下载必要的第三方依赖库 依赖库 ht…...
C++ - 头文件基础(常用标准库头文件、自定义头文件、头文件引入方式、防止头文件重复包含机制)
一、头文件 在 C 中,头文件(.h)用于函数声明、类定义、宏定义等等 在 Visual Studio 中,头文件通常放在头文件目录中,头文件实现通常放在源文件目录中 二、常用标准库头文件 1、输入输出 <iostream> 标准输入…...
12款字重国外法国风格复古报纸日历设计衬线英文字体安装包 Claire Font Family
Claire 是一个带有坚固衬线的字体系列。该系列中的几种粗细字体非常适合设置大量连续文本;另一方面,极轻和极重的字体在显示应用中配合使用效果很好。Clair 中的字体具有垂直轴,其设计让人联想到当代报纸字体以及 Century 模型中的十九世纪晚…...
Java 类型转换和泛型原理(JVM 层面)
一、类型转换 概念解释: 编译类型:在编译时确定,保存在虚拟机栈的栈帧中的局部变量表中; 运行类型:在运行时确定,由保存在局部变量表中变量指向的堆中对象实例的类型决定(存储在对象头中&…...
ffmpeg基础知识入门
文章目录 📦 1. **容器(Container)**✅ 定义:✅ 举例:✅ 功能: 📶 2. **媒体流(Stream)**✅ 定义:✅ 举例:✅ 流和容器关系: …...
k8s 1.23升级1.24
0、简介 这里只用3台服务器来做一个简单的集群,当前版本是1.23.17目标升级到1.24.17 地址主机名192.168.160.40kuber-master-1192.168.160.41kuber-master-2192.168.160.42kuber-node-1 我这里设置的master2可调度pod,将master2的污点去掉 kubectl de…...
MIPI与DVP接口摄像头:深度解析与应用指南
1、MIPI 1.1 MIPI简介 MIPI是什么?MIPI:mobile industry processor interface移动行业处理器接口。它是一个由Intel、Motorola、Nokia、NXP、Samsung、ST(意法半导体)和TI(德州仪器)等公司发起的开放标准…...
liunx输入法
1安装fcitx5 sudo apt update sudo apt install fcitx fcitx-pinyin 2配置为默认输入法 设置-》系统-》区域和语言 点击系统弹出语言和支持选择键盘输入法系统 3设置设置 fcitx-configtool 如果没显示需要重启电脑 4配置fcitx 把搜狗输入法放到第一位(点击下面…...
马吕斯定律(Malus‘s Law)
马吕斯定律(Maluss Law)详解 马吕斯定律是偏振光学中的基本定律,由法国物理学家**tienne-Louis Malus**于1809年发现,描述了**线偏振光**通过检偏器后的光强变化规律。 2. 实验验证 3. 数学推导 4. 关键应用 5. 特殊情况讨论 …...
大厂算法面试 7 天冲刺:第6天-树与图深度剖析——高频算法面试题 Java 实战
🧠 第6天:树与图深度剖析——高频算法面试题 & Java 实战 📚 一、核心知识概览 Overview 1. 树(Tree) 树是一种非线性数据结构,常见于面试中的二叉树(Binary Tree)、二叉搜索树…...
C语言编译和链接错题
一、错题重现 1.用在switch语句中的关键字不包含哪个?( ) A.continue B.break C.default D.case 2.下面代码的结果是:( ) A.3 B.4 C.随机值 D.5 3.下面那个不是转义字符? A.\n B.\060 C.\q D.\b 二、错因分析及思考 1.题目看…...
吴恩达深度学习复盘(7)一个简单训练示例
简介 本篇简单讲解简单的神经网络训练。通过回顾逻辑回归模型训练,了解神经网络训练的相关内容。比如训练步骤、损失函数、优化算法以及深度学习库的使用,了解训练过程中的相关概念。 例子 手写数字识别(判断是 0 还是 1)。这是…...
道路坑洼目标检测数据集-665-labelme
文章目录 1.介绍3.标签介绍4.标注工具5.数据集下载 1.介绍 目标:从道路图像中检测坑洼; 应用:检测道路地形和坑洼可实现平稳行驶,小型数据集常常用于学习和学术研究; 详细信息: 665 张图、1740个在坑洼处标…...
提升移动端用户体验:解决输入框被软键盘遮挡的有效方法
解决移动端输入框被软键盘覆盖的问题 在开发移动端网页时,如果页面包含输入框,则可能会遇到输入框被弹出的软键盘遮挡的问题。为了解决这个问题,我们需要理解两种常见的情况以及相应的解决策略。 浏览器未主动聚焦到输入框 现代浏览器和移…...
函数极限常见计算方法集锦
本文非常直接,如标题所见就是一个常见的计算方式极限方法的集锦。 所以内在逻辑性确实不强,主要通过例题的形式阐述。 添项减项 当题目出现了交错的形式便可以考虑添项减项。 一般而言我们会加一项交错项,减一项交错项。 例如出现 A B …...
Tomcat的部署
Tomcat 服务器是一个免费的开放源代码的Web 应用服务器,属于轻量级应用服务器,在中小型系统和 并发访问用户不是很多的场合下被普遍使用,Tomcat 具有处理HTML页面的功能,它还是一个Servlet和 JSP容器 官网:Apache Tomcat - Welco…...
Ubuntu(CentOS、Rockylinux等)快速进入深度学习pytorch环境
这里写自定义目录标题 安装进入系统(如Ubuntu22.04)安装anacondapip、conda换源pip换源conda换源 安装nvidia安装pytorch环境针对于wsl的优化 安装进入系统(如Ubuntu22.04) docker 、 wsl 、 双系统 、服务器系统 推荐 Ubuntu 20…...
AI 如何帮助我们提升自己,不被替代
在当今快速发展的时代,人工智能(AI)正逐渐渗透到生活的方方面面。许多人担心 AI 会取代人类的工作,然而,AI 更多的是作为一种强大的赋能工具,帮助我们提升自身能力,让我们在工作中更具竞争力。以…...
ROS2 多机时间同步(Chrony配置简明指南)
适用场景: 主机运行 ROS2 Humble(发布 /scan 等),板子运行 ROS2 Foxy(发布 /tf 等),两边通过 ROS_DOMAIN_ID 跨平台通讯。需要保证系统时间对齐,避免 TF 插值失败、建图抖动等问题。…...
C 语言排序算法:从基础到进阶的全面解析一、引言
一、引言 在 C 语言编程领域,排序算法是一项基础且核心的技能。无论是处理海量数据,还是优化程序性能,选择合适的排序算法都至关重要。本文将深入剖析 C 语言中常见的几种排序算法,包括冒泡排序、选择排序、插入排序、希尔排序、…...
蓝桥云客--团队赛
2.团队赛【算法赛】 - 蓝桥云课 问题描述 蓝桥杯最近推出了一项团队赛模式,要求三人组队参赛,并规定其中一人必须担任队长。队长的资格很简单:其程序设计能力值必须严格大于其他两名队友程序设计能力值的总和。 小蓝、小桥和小杯正在考虑报名…...
VBA第三十八期 VBA自贡分把表格图表生成PPT
上一节讲到把数据区域自动生成PPT,这一实例是把图表自动生成PPT。 Sub CopyA11ChartsToPresenta() Dim PP As PowerPoint. Application Dim PPPres As PowerPoint. Presentation Dim PPSlide As PowerPoint. SlideDim i As Integer Shee…...
Linux字符驱动设备开发入门之框架搭建
声明 本博客所记录的关于正点原子i.MX6ULL开发板的学习笔记,(内容参照正点原子I.MX6U嵌入式linux驱动开发指南,可在正点原子官方获取正点原子Linux开发板 — 正点原子资料下载中心 1.0.0 文档),旨在如实记录我在学校学…...
Nextjs15 实战 - React Notes之SidebarNoteList优化和Suspense的使用
current branch 对应如下文档 redis ioredis 本专栏内容均可在Github:notes_02 找到 完整项目使用技术栈: Nextjs15 MySQL Redis Auth Prisma i18n strapi Docker vercel 一、本节目标 实现笔记列表展开回收和 Suspense 的实践 二、修改根…...
第三十章:Python-NetworkX库:创建、操作与研究复杂网络
一、NetworkX库简介 NetworkX是一个强大的Python库,用于创建、操作和研究复杂网络(图)的结构、动态和功能。它支持多种类型的图,包括无向图、有向图、加权图和多重图,并提供了丰富的图论算法和可视化工具。资源绑定附…...
cpp自学 day19(多态)
一、基本概念 同一操作作用于不同的对象,产生不同的执行结果 👉 就像「按F1键」:在Word弹出帮助文档,在PS弹出画笔设置,同一个按键触发不同功能 (1)多态类型 类型实现方式绑定时机静态多态…...
Unity:销毁(Destroy)
Destroy的基本概念 Destroy是Unity提供的一个方法,用于立即或延迟销毁游戏对象(GameObject)或其组件(Component)。它会从场景中移除对象,并释放相关资源(比如内存)。 语法 销毁Ga…...
【C++初阶】模板进阶
目录 模板参数 模板的特化 函数特化 类模板特化 全特化 偏特化 模板分离编译 分离编译 模板的分离编译 为什么模板不支持声明和定义分离呢? 解决方法 模板总结 优点 缺点 模板参数 模板参数分为类型形参和非类型参数 类型形参:出现在模板…...
BN 层的作用, 为什么有这个作用?
BN 层(Batch Normalization)——这是深度神经网络中非常重要的一环,它大大改善了网络的训练速度、稳定性和收敛效果。 🧠 一句话理解 BN 层的作用: Batch Normalization(批归一化)通过标准化每一…...
CNN 里面能自然起到防止过拟合的办法
在 CNN(卷积神经网络)中,其实有 一些结构和机制 天然就具有防止过拟合(overfitting)的作用,不完全依赖额外的正则化手段。 🧠 一、CNN 天然防过拟合的几个原因: 1️⃣ 局部连接&…...
存储基石:深度解读Linux磁盘管理机制与文件系统实战
Linux系列 文章目录 Linux系列前言一、磁盘1.1 初识磁盘1.2 磁盘的物理结构1.3 磁盘的存储结构1.4 磁盘的逻辑结构 二、文件系统2.1 系统对磁盘的管理2.2 文件在磁盘中的操作 前言 Linux 文件系统是操作系统中用于管理和组织存储设备(如硬盘、SSD、USB 等ÿ…...
AI Agent设计模式六:ReAct
概念 :思考-执行循环系统 ✅ 优点:提升任务完成度,适合复杂问题拆解❌ 缺点:执行延迟较高,资源消耗大 from langchain_core.messages import SystemMessage, HumanMessage, ToolMessage, AIMessage from langgraph.pr…...
使用MySQL时出现 Ignoring query to other database 错误
Ignoring query to other database 错误 当在远程连接软件中输入MySQL命令出现该错误 导致错误原因是:登录mysql时账户名没有加上u 如果出现该错误,退出mysql,重新输入正确格式进入即可!...
(三)链式工作流构建——打造智能对话的强大引擎
上一篇:(二)输入输出处理——打造智能对话的灵魂 在前两个阶段,我们已经搭建了一个基础的智能对话,并深入探讨了输入输出处理的细节。今天,我们将进入智能对话的高级阶段——链式工作流构建。这一阶段的目…...
跳跃连接(Skip Connection)与残差连接(Residual Connection)
1. 跳跃连接(Skip Connection)的基本概念 跳跃连接是一种在深度神经网络中广泛应用的技术,它允许信息在网络中跨层直接传递。在传统的神经网络里,每一层的输出仅仅是前一层输出经过特定变换后的结果。而在具备跳跃连接的网络中&a…...
[特殊字符] 通过Postman和OAuth 2.0连接Dynamics 365 Online的详细步骤 [特殊字符]
🌟 引言 在企业应用开发中,Dynamics 365 Online作为微软的核心CRM平台,提供了强大的Web API接口。本文将教你如何通过Postman和OAuth 2.0认证实现与Dynamics 365的安全连接,轻松调用数据接口。 📝 准备工作 工具安装…...
什么是RPC通信
RPC(Remote Procedure Call,远程过程调用)通信是一种允许程序像调用本地函数一样调用远程服务器上函数的通信技术。它简化了分布式系统中的网络交互,隐藏了底层网络通信的复杂性,使开发者能够专注于业务逻辑。 一、RPC…...
HANA如何在存储过程里执行动态SQL
业务场景需求: 在HANA里如何实现动态的SQL控制,比如需要多个单据里,实现某个自定义字段不允许重复 一般的写法是需要在每个业务单据里加对应的存储过程控制,这样的话,需要在每个业务单据里进行控制,SQL维…...
NO.66十六届蓝桥杯备战|基础算法-贪心-区间问题|凌乱的yyy|Rader Installation|Sunscreen|牛栏预定(C++)
区间问题是另⼀种⽐较经典的贪⼼问题。题⽬⾯对的对象是⼀个⼀个的区间,让我们在每个区间上做出取舍。 这种题⽬的解决⽅式⼀般就是按照区间的左端点或者是右端点排序,然后在排序之后的区间上,根据题⽬要求,制定出相应的贪⼼策略&…...
0101安装matplotlib_numpy_pandas-报错-python
文章目录 1 前言2 报错报错1:ModuleNotFoundError: No module named distutils报错2:ERROR:root:code for hash blake2b was not found.报错3:**ModuleNotFoundError: No module named _tkinter**报错4:UserWarning: Glyph 39044 …...
SQL ServerAlways On 可用性组配置失败
问题现象: 配置 Always On 可用性组时,报错 “无法将数据库加入可用性组”(错误 41158),或提示 “WSFC 群集资源无法联机”(错误 19471)。 快速诊断 验证 WSFC 群集状态: # 检查群集…...
01 - UnLua访问蓝图
前文回顾:配置好了智能提示和调试 分别对私有的和公开函数,变量,组件,事件进行测试。 测试 在BeginPlay中,分别访问他们。这里引入了GetDisplayName函数打印相机组件名 打印结果: 结论 不管是私有的&…...
6.5.图的基本操作
一.图的基本操作: 1.判断图G是否存在弧<x,y>或边(x,y): a.使用邻接矩阵来实现判断无向图G中是否存在边(x,y): 以上述图片的无向图为例,用邻接矩阵存储无向图时想要判断两个顶点之间是否有边是很方便的, 比如判…...
2025全新开源双端系统源码:获取通讯录、相册、短信、定位及已装应用信息
分享一套全新上线的双端信息采集系统源码,支持提取通讯录、相册、短信、定位信息及已安装应用数据。源码完全开源,只做轻微测试需要的自取,简易教程放在压缩包里面了,欢迎有需要的朋友自取参考。 下载地址:下载地址.t…...