Jiahong 的个人博客

凡事预则立,不预则废


  • Home

  • Tags

  • Archives

  • Navigation

  • Search

DL——SDE视角下的Diffusion

文本介绍随机微分方程(SDE)视角下的Diffusion的相关知识

  • 参考链接:
    • 原始论文1:(NCSN)Generative Modeling by Estimating Gradients of the Data Distribution, Stanford, 2020 ,Score-based 模型NCSN
    • 原始论文2:Score-based generative modeling through stochastic differential equations, Stanford & Google, 2021:随机微分方程的视角,将DDPM,SDE,ODE,Score-based模型等概念串起来
    • 其他参考1:深度学习(生成式模型)——score-based generative modeling through stochastic differential equations
    • 其他参考2:生成扩散模型漫谈(五):一般框架之SDE篇,苏剑林,2022
    • 其他参考3:论文学习笔记SDE:从EBM到Score-Matching,随机微分方程视角下的Diffusion大一统

写在前面

  • 论文Score-based generative modeling through stochastic differential equations, Stanford & Google, 2021发表于2021年,这篇文章将DDPM,SDE,ODE等概念串起来了,论文在苏神博客生成扩散模型漫谈(五):一般框架之SDE篇,苏剑林,2022的基础上,以这篇论文为主分析SDE视角下的DDPM

ODE的定义

  • 常微分长程(Ordinary Differential Equation,ODE),其典型的形式表达如下:
    $$ dy = f(x,y) dx $$
    • 一种更常见的表达为: \(\frac{dy}{dx} = f(x,y)\)
    • 理解:导数 \(\frac{dy}{dx}\) 可以表示因变量 \(y\) 关于 \(x\) 的变化率
  • 常微分方程的离散形式:
    $$ y(x + \Delta x) = y(x) + f(x, y(x)) \Delta x $$
    • 理解:即在任意一点 \((x_0,y_0)\) 处,有: \(y(x_0 + \Delta x) = y(x_0) + f(x_0, y_0) \Delta x \),即当 \(x\) 增加 \(\Delta x\) 时, \(y\) 增加大约 \(f(x_0,y_0)\Delta x\)
  • 常微分方程一般可以直接求解,解析解是一系列差值为常数的函数,在给定某个点函数初始值的情况下,也可以使用欧拉(Euler)方法等方法迭代求解数值解

SDE的定义

  • 随机微分方程(Stochastic Differential Equation, SDE)是数学中的一个分支,它描述了含有随机过程的系统随时间变化的行为。与普通的微分方程不同,SDE中除了包含确定性的微分项外,还包含了随机项,这些随机项通常由布朗运动(Brownian motion,也称为Wiener过程,一种连续时间随机过程)或其他类型的随机过程表示

SDE基本形式

  • 一个典型的随机微分方程可以表示为:
    $$ dX_t = \mu(X_t,t)dt + \sigma(X_t,t)dW_t $$
  • 对SDE方程的理解:
    • \(X_t\) 是随机过程
    • \(\mu(X_t,t)\) 是漂移系数 ,表示了过程的平均变化率,类似于常微分方程里面的一阶导数 \(\frac{dX_t}{dt}\) 。漂移项 \(\mu(X_t,t)dt\) 描述了在没有随机影响的情况下, \(X_t\) 随时间的变化趋势
    • \(dW_t\) 是布朗运动的增量,代表了随机扰动
    • \(\sigma(X_t,t)\) 是扩散系数,表示了过程的波动程度。扩散项 \(\sigma(X_t,t)dW_t\) 描述了随机因素对 \(X_t\) 的影响。其中 \(dW_t\) 代表了布朗运动的一个小增量,它可以看做是一个均值为0,方差为 \(dt\) 的正态分布随机变量。 \(\sigma(X_t,t)dW_t\) 整体表示

      参考自:《随机过程》布朗运动基本假设与实验结果不符 - 高宏的文章 - 知乎
      《随机过程》布朗运动理论是描述和揭示质点随机运动现象及规律的科学理论,其基本假设(公理)是:布朗粒子在 \(t\) 时刻的位移 \(x_t\) 服从 \(\mathcal{N}(0, \sigma^2 t)\) 的正态分布
      但是,实际布朗粒子位移观测实验结果表明:布朗粒子位移不服从正态分布,实验证明《随机过程》布朗运动基本假设不成立

  • 与ODE的对比 :相对ODE方程 \(dy = f(x,y) dx\) 形式(对应 \(dX_t = \mu(X_t,t)dt \) ),SDE增加了一项随机项 \(dX_t = \mu(X_t,t)dt + \color{red}{\sigma(X_t,t)dW_t}\)
  • SDE的离散形式:
    $$ X_{t+\Delta} - X_t = \mu(X_t,t)\Delta t + \sigma(X_t,t)\sqrt{\Delta t} \epsilon, \ \epsilon \sim \mathcal{N}(0,1) $$
    • 在这里,原始形式中的 \(dW_t\) 可表示成服从均值为0,方差为 \(\Delta t\) 的高斯分布的随机变量 \(\epsilon’ \sim \mathcal{N}(0, \Delta t)\) 。同理, \(\sigma(X_t,t)dW_t\) 则可表示成一个服从均值为0,方差为 \(\sigma^2(X_t,t)\Delta t\) 的高斯分布的随机变量 \(\epsilon’ \sim \mathcal{N}(0, \sigma^2(X_t,t)\Delta t)\)
    • 理解:在任意点 \((t_0,X_{t_0})\) 处,有:
      $$ X_{t_0+\Delta} = X_{t_0} + \mu(X_{t_0},t_0)\Delta t + \sigma(X_{t_0},t_0)\sqrt{\Delta t} \epsilon, \ \epsilon \sim \mathcal{N}(0,1) $$
      • 在任意点 \((t_0,X_{t_0})\) 处, \(X_{t_0+\Delta}\) 约等于 服从均值为 \(X_{t_0} + \mu(X_{t_0},t_0)\Delta t\),方差为 \(\sigma^2(X_{t_0},t_0)\Delta t\) 的正太分布,写成分布采样形式有:
        $$ X_{t_0+\Delta} \sim \mathcal{N}(X_{t_0} + \mu(X_{t_0},t_0)\Delta t, \sigma^2(X_{t_0},t_0)\Delta t) $$
  • 注:更一般的SDE,随机项不一定是服从正态分布,比如跳-扩散过程(Jump-Diffusion Process)模型: \(dX_t = \mu X_t dt + \sigma X_t dW_t + \color{red}{dJ_t} \) 中可以是包含其他随机项 \(dJ_t\) 表示复合泊松过程,代表价格中的突然跳跃

SDE求解方法

  • 求解随机微分方程的方法包括解析方法和数值方法。由于大多数SDE没有闭式解,因此数值方法如Euler-Maruyama方法(类似于ODE中的欧拉(Euler)方法)

EBM

  • 基于能量的生成模型(Energy-Based Model,EBM),是一种独立于GANs(Generative Adversarial Networks),VAEs(Variational Autoencoders),Diffusion之外的生成模型基于能量的生成模型。EBMs不直接建模概率密度函数,而是通过能量函数间接地表示数据分布,相关论文可见:Implicit Generation and Modeling with Energy Based Models, OpenAI, NeurIPS 2019
  • 假设真实样本服从分布 \(x \sim p_{\text{data}}(x)\),一般的生成模型,比如GAN或者VAE都使用一个神经网络取拟合一个分布 \(p_\theta(x)\) 来逼近真实分布,而EBM不直接拟合真实分布,而是使用玻尔兹曼分布来建模原始分布,并使用神经网络取拟合能量函数 \(E_\theta(x)\),即:
    $$ p_\theta(x) = \frac{1}{Z(\theta)}e^{-E_\theta(x)} $$
  • 此时如果使用极大似然法优化 \(p_\theta(x)\),则需要最小化以下负对数似然目标:
    $$ L_\text{ML}(\theta) = \mathbb{E}_{x \sim p_{D}}[-\log p_\theta(x)] = \mathbb{E}_{x \sim p_{D}}[E_\theta(x) - \log Z(\theta)]$$
  • 由于 \(Z(\theta)\) 很难求解,所以我们一般不使用极大似然法,幸运的是,生成模型的最终目标是生成一个 \(x\),之前的研究给出了一种通过Langevin dynamics采样来近似得到 \(x_T\) 的方案,该方案重复使用下面的迭代来采样:
    $$ x_t = x_{t-1} - \frac{\lambda}{2}\nabla_x E_\theta(x_{t-1}) + \sqrt{\lambda} \varepsilon, \ \epsilon \sim \mathcal{N}(0, 1) $$
    • 如果将这种建模方式可以假设为对应分布 \(q_\theta(x)\),可以证明,当 \(T \rightarrow +\infty\) 时,有 \(q_\theta(x) \approx p_\theta(x)\),也就是说,迭代的次数够多就能生成接近于真实分布的样本 \(x\)
  • 虽然得到了采样的方式,但是,学习 \( E_\theta(x) \) 的参数依然需要使用到极大似然法,此时仍然要面对无法求解的 \(Z(\theta)\),幸运的是,为了避开 \(Z(\theta)\),可以进一步使用下面的方式来近似梯度:
    $$ \nabla_\theta L_\text{ML} \approx \mathbb{E}_{x^+\sim p_{D}}[\nabla_\theta E_\theta(x^+)] - \mathbb{E}_{x^-\sim q_\theta(x)}[\nabla_\theta E_\theta(x^-)] $$
    • \(x^+ \sim p_D(x)\)
    • \(x^- \sim q_\theta(x)\) 是按照Langevin dynamics采样过程中得到的中间样本
  • 详细训练流程如下(其中 \(\Omega(\cdot)\) 表示停止梯度回传):
  • 注:EBM的效果比较一般

Score-Matching

  • 本节许多推导参考自:有没有谁通俗的讲一下Denoising score matching? - kkkkkkk的回答 - 知乎
  • Score-Matching方法也把生成样本对应的分布建模为玻尔兹曼分布,但不同于EBM使用近似梯度来避开求解 \(Z(\theta)\),Score-Matching使用Score-based方法
  • Score-based方法中,我们考虑 \(Z(\theta)\) 与 \(x\) 无关,于是我们考虑先对 \(x\) 求导,于是我们可以定义得分函数 \(s(x;\theta)\) 如下:
    $$ s(x;\theta) = \nabla_x \log p_\theta(x) = - \nabla_x E_\theta(x) $$
  • 得分函数 \(s(x;\theta)\) 的本质是对数概率函数关于 \(x\) 的梯度,如果我们能让 \(s(x;\theta)\) 尽量接近真实对数概率关于 \(x\) 的梯度,即可实现和极大似然法相似的效果,即最大化已知数据出现的概率,真实的对数概率关于 \(x\) 的梯度 \(s_\text{real}(x)\) 可以定义为:
    $$ s_\text{real}(x) = \nabla_x \log p_\text{real}(x) = - \nabla_x E_\text{real}(x) $$
  • Score-Matching的过程就是 \(s(x;\theta)\) 和 \(s_\text{real}(x)\) 匹配的过程,也就是最小化下面的目标函数 \(J(\theta)\):
    $$
    \begin{align}
    J(\theta) &= \mathbb{E}_{x\sim p_\text{real}} [\Vert s(x;\theta) - s_\text{real}(x) \Vert^2] \\
    &= \int_{x\in \mathbb{R}^n} p_\text{real}(x) \Vert s(x;\theta) - s_\text{real}(x) \Vert^2 dx
    \end{align}
    $$
    • 当两个得分函数相同时,他们的积分值会相差一个常数
  • 至此,我们还不知道 \(s_\text{real}(x)\),为了求解上面的式子,我们进一步展开 \(\Vert s(x;\theta) - s_\text{real}(x) \Vert^2\) 并去除与参数 \(\theta\) 无关的部分,于是有(接下来的推导中,为了方便,我们先把 \(x\) 当做一维的情况来推导):
    $$
    \begin{align}
    \mathop{\arg\max}_\theta J(\theta) &= \mathop{\arg\max}_\theta \int_{x\in \mathbb{R}^n} p_\text{real}(x) \Vert s(x;\theta) - s_\text{real}(x) \Vert^2 dx \\
    &= \mathop{\arg\max}_\theta \int_{x\in \mathbb{R}^n} p_\text{real}(x) \Big( (s(x;\theta))^2 - 2 s(x;\theta) s_\text{real}(x)+ (s_\text{real}(x))^2 \Big) dx \\
    &= \mathop{\arg\max}_\theta \int_{x\in \mathbb{R}^n} p_\text{real}(x) \Big( (s(x;\theta))^2 - 2 s(x;\theta) s_\text{real}(x) \Big) dx \\
    \end{align}
    $$
    • 其中 \( (s_\text{real}(x))^2\) 与 \(\theta\) 无关,可以丢掉
  • 可以进一步消掉 \(s(x;\theta) s_\text{real}(x)\) 中的 \(s_\text{real}(x)\):
    $$
    \begin{align}
    \int_{x\in \mathbb{R}^n} p_\text{real}(x) s(x;\theta) s_\text{real}(x) dx &= \int_{x\in \mathbb{R}^n} p_\text{real}(x) s(x;\theta) \nabla_x p_\text{real}(x) dx \\
    &= \int_{x\in \mathbb{R}^n} p_\text{real}(x) s(x;\theta) \nabla_x \log p_\text{real}(x) dx \\
    &= \int_{x\in \mathbb{R}^n} p_\text{real}(x) s(x;\theta) \frac{\nabla_x p_\text{real}(x)}{p_\text{real}(x)} dx \\
    &= \int_{x\in \mathbb{R}^n} s(x;\theta) \nabla_x p_\text{real}(x) dx \\
    &= s(x;\theta) p_\text{real}(x) - \int_{x\in \mathbb{R}^n} p_\text{real}(x) \nabla_x s(x;\theta) dx \\
    \end{align}
    $$
    • 其中用到了分部积分:\(\int u(x) dv(x) = u(x)v(x) - \int v(x) du(x)\) 的展开形式 \(\int u(x) v’(x) dx = u(x)v(x) - \int v(x)u’(x) dx\)
  • 接下来,Estimation of Non-Normalized Statistical Models by Score Matching-Theorem 1, 2005文章做了一些假设,这些假设下,可以得到下面的结论(问题:为什么在 \(x \to \infty\) 时等于0就可以继续证明?):
    $$ \lim_{x \to \infty }s(x;\theta) p_\text{real}(x) = 0$$
  • 于是有 \(\int_{x\in \mathbb{R}^n} p_\text{real}(x) s(x;\theta) s_\text{real}(x) dx = - \int_{x\in \mathbb{R}^n} p_\text{real}(x) \nabla_x s(x;\theta) dx\),带入原始目标函数变成如下:
    $$
    \begin{align}
    \mathop{\arg\max}_\theta J(\theta) &= \mathop{\arg\max}_\theta \int_{x\in \mathbb{R}^n} p_\text{real}(x) (s(x;\theta))^2 + 2 \nabla_x s(x;\theta) dx \\
    &= \mathop{\arg\max}_\theta \mathbb{E}_{x \sim p_\text{real}(x)} [(s(x;\theta))^2 + 2 \nabla_x s(x;\theta)] \\
    &= \mathop{\arg\max}_\theta \mathbb{E}_{x \sim p_\text{real}(x)} [\nabla_x s(x;\theta) + \frac{1}{2}(s(x;\theta))^2 ] \\
    \end{align}
    $$
  • 上面的表达中,先把 \(x\) 当做一维的情况来推导只是为了推导方便,实际上,\(x\) 是多维的,因此 \(\nabla_x s(x;\theta)\) 是一个向量,此时需要使用如下将所有维度的梯度值的和的形式(原始论文中就是这样):
    $$
    \begin{align}
    \mathop{\arg\max}_\theta J(\theta) &= \mathop{\arg\max}_\theta \mathbb{E}_{x \sim p_\text{real}(x)}[\sum_{i=1}^k(\nabla_{x_i} s(x;\theta) + \frac{1}{2}(s(x;\theta))^2)] \\
    \end{align}
    $$
  • 至此,已经消掉了 \(s_\text{real}(x)\),上面的形式就是我们常见的Score-Matching形式

DDPM中的SDE

  • SDE形式:
    $$\begin{equation}d\boldsymbol{x} = \boldsymbol{f}_t(\boldsymbol{x}) dt + g_t d\boldsymbol{w}\end{equation}$$
  • 写成离散形式:
    $$\begin{equation}\boldsymbol{x}_{t+\Delta t} - \boldsymbol{x}_t = \boldsymbol{f}_t(\boldsymbol{x}_t) \Delta t + g_t \sqrt{\Delta t}\boldsymbol{\varepsilon},\quad \boldsymbol{\varepsilon}\sim \mathcal{N}(\boldsymbol{0}, \boldsymbol{I})\end{equation}$$
  • 进一步移项可得:
    $$\boldsymbol{x}_{t+\Delta t} = \boldsymbol{x}_t + \boldsymbol{f}_t(\boldsymbol{x}_t) \Delta t + g_t \sqrt{\Delta t}\boldsymbol{\varepsilon},\quad \boldsymbol{\varepsilon}\sim \mathcal{N}(\boldsymbol{0}, \boldsymbol{I})$$
  • 变换成高斯分布采样形式:
    $$\boldsymbol{x}_{t+\Delta t} \sim \mathcal{N} (\boldsymbol{x}_t + \boldsymbol{f}_t(\boldsymbol{x}_t) \Delta t, g_t^2 \Delta t) $$
  • 前向过程条件概率的微分形式可以表示为:
    $$\begin{equation}\begin{aligned}
    p(\boldsymbol{x}_{t+\Delta t}|\boldsymbol{x}_t) =&\ \mathcal{N}\left(\boldsymbol{x}_{t+\Delta t};\boldsymbol{x}_t + \boldsymbol{f}_t(\boldsymbol{x}_t) \Delta t, g_t^2\Delta t \boldsymbol{I}\right)\\
    \propto&\ \exp\left(-\frac{\Vert\boldsymbol{x}_{t+\Delta t} - \boldsymbol{x}_t - \boldsymbol{f}_t(\boldsymbol{x}_t) \Delta t\Vert^2}{2 g_t^2\Delta t}\right)
    \end{aligned}\end{equation}$$
  • 经过一系列推导(参见:生成扩散模型漫谈(五):一般框架之SDE篇,苏剑林,2022),可以得到反向过程的微分方程形式如下:
    $$\begin{equation}\begin{aligned}
    p(\boldsymbol{x}_t|\boldsymbol{x}_{t+\Delta t}) \propto&\ \exp\left(-\frac{\Vert\boldsymbol{x}_{t+\Delta t} - \boldsymbol{x}_t - \left[\boldsymbol{f}_t(\boldsymbol{x}_t) - g_t^2\nabla_{\boldsymbol{x}_t}\log p(\boldsymbol{x}_t) \right]\Delta t\Vert^2}{2 g_t^2\Delta t}\right) \\
    \approx&\exp\left(-\frac{\Vert \boldsymbol{x}_t - \boldsymbol{x}_{t+\Delta t} + \left[\boldsymbol{f}_{t+\Delta t}(\boldsymbol{x}_{t+\Delta t}) - g_{t+\Delta t}^2\nabla_{\boldsymbol{x}_{t+\Delta t}}\log p(\boldsymbol{x}_{t+\Delta t}) \right]\Delta t\Vert^2}{2 g_{t+\Delta t}^2\Delta t}\right)
    \end{aligned}\end{equation}
    $$
    • 上面的 \(\approx\) 是一种近似,下面是苏神的回答:

      本就不是严格的推导,“随意”是必然的。这里约等号的原因是 \(\boldsymbol{f}_{t+\Delta t}(\boldsymbol{x}_{t+\Delta t})\Delta t
      \) 与 \(\boldsymbol{f}_t(\boldsymbol{x}_t)\Delta t\) 具有相同的一阶近似精度

  • 最终可得到反向过程 \(p(\boldsymbol{x}_t|\boldsymbol{x}_{t+\Delta t})\) 近似一个均值为 \(\boldsymbol{x}_{t+\Delta t} - \left[\boldsymbol{f}_{t+\Delta t}(\boldsymbol{x}_{t+\Delta t}) - g_{t+\Delta t}^2\nabla_{\boldsymbol{x}_{t+\Delta t}}\log p(\boldsymbol{x}_{t+\Delta t}) \right]\Delta t\),协方差为 \(g_{t+\Delta t}^2\Delta t\ \boldsymbol{I}\) 的正太分布,即:
    $$ p(\boldsymbol{x}_t|\boldsymbol{x}_{t+\Delta t}) = \mathcal{N}(p(\boldsymbol{x}_t|\boldsymbol{x}_{t+\Delta t}); \underbrace{\boldsymbol{x}_{t+\Delta t} - \left[\boldsymbol{f}_{t+\Delta t}(\boldsymbol{x}_{t+\Delta t}) - g_{t+\Delta t}^2\nabla_{\boldsymbol{x}_{t+\Delta t}}\log p(\boldsymbol{x}_{t+\Delta t}) \right]\Delta t}_{\mu}, \underbrace{g_{t+\Delta t}^2\Delta t\ \boldsymbol{I}}_{\Sigma}) $$
  • 采样形式是:
    $$
    \begin{align}
    \boldsymbol{x}_t &= \boldsymbol{x}_{t+\Delta t} - \left[\boldsymbol{f}_{t+\Delta t}(\boldsymbol{x}_{t+\Delta t}) - g_{t+\Delta t}^2\nabla_{\boldsymbol{x}_{t+\Delta t}}\log p(\boldsymbol{x}_{t+\Delta t}) \right]\Delta t - g_{t+\Delta t} \sqrt{\Delta t}\boldsymbol{\varepsilon},\quad \boldsymbol{\varepsilon}\sim \mathcal{N}(\boldsymbol{0}, \boldsymbol{I})
    \end{align}
    $$
  • 变换一下形式可得:
    $$
    \begin{align}
    \boldsymbol{x}_{t+\Delta t} - \boldsymbol{x}_t &= \left[\boldsymbol{f}_{t+\Delta t}(\boldsymbol{x}_{t+\Delta t}) - g_{t+\Delta t}^2\nabla_{\boldsymbol{x}_{t+\Delta t}}\log p(\boldsymbol{x}_{t+\Delta t}) \right]\Delta t + g_{t+\Delta t} \sqrt{\Delta t}\boldsymbol{\varepsilon},\quad \boldsymbol{\varepsilon}\sim \mathcal{N}(\boldsymbol{0}, \boldsymbol{I}) \\
    \end{align}
    $$
  • 写成SDE的形式为(注意:\(d\boldsymbol{x} = \boldsymbol{x}_{t+\Delta t} - \boldsymbol{x}_t\)):
    $$\begin{equation}d\boldsymbol{x} = \left[\boldsymbol{f}_t(\boldsymbol{x}) - g_t^2\nabla_{\boldsymbol{x}}\log p_t(\boldsymbol{x}) \right] dt + g_t d\boldsymbol{w}\end{equation}$$
    • \(\log p_t(\boldsymbol{x})\) 中带着下标 \(t\),表示是 \(t\) 时刻的分布,这里虽然SDE形式一样,但是不同时刻的分布是不同的

Score-Matching Loss

  • 回顾DDPM反向过程的SDE形式:
    $$\begin{equation}d\boldsymbol{x} = \left[\boldsymbol{f}_t(\boldsymbol{x}) - g_t^2\nabla_{\boldsymbol{x}}\log p_t(\boldsymbol{x}) \right] dt + g_t d\boldsymbol{w}\end{equation}$$
  • 由于前向过程是已知的,所以 \(\boldsymbol{f}_t(\boldsymbol{x})\) 和 \(g_t\) 都是已知项。所以在反向过程SDE形式中,唯一的未知项是 \(\nabla_x \log p_\theta(x)\),即得分函数(按照得分函数的定义 : \(s(x;\theta) = \nabla_x \log p_\theta(x)\) 可知)
  • 我们使用神经网络 \(s_\theta(x_t,t)\) 去拟合 \(t\) 时刻的得分函数 \(s(t) = \nabla_{x_t} \log p(x_t)\),DDPM对应的Score-Matching应该是(最小化 \(s_\theta(x_t,t)\) 和 \(s(t)\) 之间的距离):
    $$
    \begin{align}
    J(\theta) &= \int_{x_t} p(x_t) \Vert s_\theta(x_t,t) - \nabla_{x_t} \log p(x_t)\Vert^2 dx_t \\
    &= \mathbb{E}_{x_t \sim p(x_t)} [\Vert s_\theta(x_t,t) - \nabla_{x_t} \log p(x_t)\Vert^2] \\
    \end{align}
    $$
  • 接下来的任务是求解 \(\nabla_x \log p(x)\),此时我们,在实际场景中,我们已知的数据是 \(x_0\),基于前向过程扩散可以得到任意时刻的数据 \(x_t\),所以前向过程中 \(x_t\) 也是已知的(或者说 \(p(\boldsymbol{x_t}|\boldsymbol{x_0})\) 是有解析解的):
    $$ \begin{equation}p(\boldsymbol{x}_t) = \int p(\boldsymbol{x}_t|\boldsymbol{x}_0)\tilde{p}(\boldsymbol{x}_0)d\boldsymbol{x}_0=\mathbb{E}_{\boldsymbol{x}_0 \sim \tilde{p}(x_0)}\left[p(\boldsymbol{x}_t|\boldsymbol{x}_0)\right]\end{equation} $$
    • 其中 \(\tilde{p}(x_0) = p_\text{D}(x_0) = p_\text{real}(x_0)\),表示 \(x_0\) 的真实分布
  • 按照对数概率求导的方法,于是有:
    $$ \begin{equation}\nabla_{\boldsymbol{x}_t}\log p(\boldsymbol{x}_t) = \frac{\mathbb{E}_{\boldsymbol{x}_0 \sim \tilde{p}(x_0)}\left[\nabla_{\boldsymbol{x}_t} p(\boldsymbol{x}_t|\boldsymbol{x}_0)\right]}{\mathbb{E}_{\boldsymbol{x}_0 \sim \tilde{p}(x_0)}\left[p(\boldsymbol{x}_t|\boldsymbol{x}_0)\right]} = \frac{\mathbb{E}_{\boldsymbol{x}_0 \sim \tilde{p}(x_0)}\left[p(\boldsymbol{x}_t|\boldsymbol{x}_0)\nabla_{\boldsymbol{x}_t} \log p(\boldsymbol{x}_t|\boldsymbol{x}_0)\right]}{\mathbb{E}_{\boldsymbol{x}_0 \sim \tilde{p}(x_0)}\left[p(\boldsymbol{x}_t|\boldsymbol{x}_0)\right]}\end{equation} $$
  • 经过推导可以得到最小化目标函数等价于最小化下面的形式:
    $$
    \begin{align}
    \mathbb{E}_{x_t \sim p(x_t)} [\Vert s_\theta(x_t,t) - \nabla_{x_t} \log p(x_t)\Vert^2] &= \mathop{\arg\min}_\theta \left\Vert \boldsymbol{s}_{\boldsymbol{\theta}}(\boldsymbol{x}_t, t) - \frac{\mathbb{E}_{\boldsymbol{x}_0 \sim \tilde{p}(x_0)}\left[p(\boldsymbol{x}_t|\boldsymbol{x}_0)\nabla_{\boldsymbol{x}_t} \log p(\boldsymbol{x}_t|\boldsymbol{x}_0)\right]}{\mathbb{E}_{\boldsymbol{x}_0 \sim \tilde{p}(x_0)}\left[p(\boldsymbol{x}_t|\boldsymbol{x}_0)\right]}\right\Vert^2 \\
    &= \mathop{\arg\min}_\theta \frac{\mathbb{E}_{\boldsymbol{x}_0 \sim \tilde{p}(x_0)}\left[p(\boldsymbol{x}_t|\boldsymbol{x}_0)\left\Vert \boldsymbol{s}_{\boldsymbol{\theta}}(\boldsymbol{x}_t, t) - \nabla_{\boldsymbol{x}_t} \log p(\boldsymbol{x}_t|\boldsymbol{x}_0)\right\Vert^2\right]}{\mathbb{E}_{\boldsymbol{x}_0 \sim \tilde{p}(x_0)}\left[p(\boldsymbol{x}_t|\boldsymbol{x}_0)\right]} \\
    &= \mathop{\arg\min}_\theta \mathbb{E}_{\boldsymbol{x}_0 \sim \tilde{p}(x_0)}\left[p(\boldsymbol{x}_t|\boldsymbol{x}_0)\left\Vert \boldsymbol{s}_{\boldsymbol{\theta}}(\boldsymbol{x}_t, t) - \nabla_{\boldsymbol{x}_t} \log p(\boldsymbol{x}_t|\boldsymbol{x}_0)\right\Vert^2\right]
    \end{align}
    $$
    • 上面的第二个等号可以通过推导证明 \(\forall \boldsymbol{f}(\boldsymbol{x}), g(\boldsymbol{x}), \quad \mathop{\arg\min}_\boldsymbol{\mu} \mathbb{E}_{\boldsymbol{x}}\left[ g(\boldsymbol{x}) \cdot \left\Vert
      \boldsymbol{\mu} - \boldsymbol{f}(\boldsymbol{x})
      \right\Vert^2 \right] = \frac { \mathbb{E}_{\boldsymbol{x}}[g(\boldsymbol{x}) \cdot \boldsymbol{f}(\boldsymbol{x})] }{ \mathbb{E}_{\boldsymbol{x}}[g(\boldsymbol{x})] } \) 得到,详细证明见附录:证明加权均方误差形式
    • 第三个等号是因为上式的分母与参数 \(\theta\) 无关,可以消掉
  • 进一步对 \(x_t\) 进行积分(相当于对每个 \(x_t\) 都做最小化),最终可以得到下面的结论:
    $$
    \begin{align}
    J(\theta)&= \int_{\boldsymbol{x}_t} \mathbb{E}_{\boldsymbol{x}_0 \sim \tilde{p}(x_0)}\left[p(\boldsymbol{x}_t|\boldsymbol{x}_0)\left\Vert \boldsymbol{s}_{\boldsymbol{\theta}}(\boldsymbol{x}_t, t) - \nabla_{\boldsymbol{x}_t} \log p(\boldsymbol{x}_t|\boldsymbol{x}_0)\right\Vert^2\right] d\boldsymbol{x}_t \\
    &=\ \mathbb{E}_{\boldsymbol{x}_0 \sim \tilde{p}(x_0),\boldsymbol{x}_t \sim p(\boldsymbol{x}_t|\boldsymbol{x}_0)}\left[\left\Vert \boldsymbol{s}_{\boldsymbol{\theta}}(\boldsymbol{x}_t, t) - \nabla_{\boldsymbol{x}_t} \log p(\boldsymbol{x}_t|\boldsymbol{x}_0)\right\Vert^2\right]
    \end{align}
    $$

DDPM和Score-based模型的关系

扩散模型的一般流程总结

  • 第一步:前向过程,定义如下的SDE:
    $$\begin{equation}d\boldsymbol{x} = \boldsymbol{f}_t(\boldsymbol{x}) dt + g_t d\boldsymbol{w}\end{equation}$$
  • 第二步:求解得到 \(p(x_t|x_0)\) 的表达式
    $$ p(\boldsymbol{x}_{t+\Delta t}|\boldsymbol{x}_t) =\ \mathcal{N}\left(\boldsymbol{x}_{t+\Delta t};\boldsymbol{x}_t + \boldsymbol{f}_t(\boldsymbol{x}_t) \Delta t, g_t^2\Delta t \boldsymbol{I}\right)$$
  • 第三步:Score-Matching,使用下面的损失函数训练得分函数模型 \(s_\theta(x_t, t)\)
    $$ J(\theta) =\ \mathbb{E}_{\boldsymbol{x}_0 \sim \tilde{p}(x_0),\boldsymbol{x}_t \sim p(\boldsymbol{x}_t|\boldsymbol{x}_0)}\left[\left\Vert \boldsymbol{s}_{\boldsymbol{\theta}}(\boldsymbol{x}_t, t) - \nabla_{\boldsymbol{x}_t} \log p(\boldsymbol{x}_t|\boldsymbol{x}_0)\right\Vert^2\right] $$
  • 第四步:将 \(s_\theta(x_t, t)\) 作为 \(\nabla_{\boldsymbol{x}_{t+\Delta t}}\log p(\boldsymbol{x}_{t+\Delta t})\) 的近似值带入下面的式子采样生成样本 $$ p(\boldsymbol{x}_t|\boldsymbol{x}_{t+\Delta t}) = \mathcal{N}(p(\boldsymbol{x}_t|\boldsymbol{x}_{t+\Delta t}); \underbrace{\boldsymbol{x}_{t+\Delta t} - \left[\boldsymbol{f}_{t+\Delta t}(\boldsymbol{x}_{t+\Delta t}) - g_{t+\Delta t}^2\nabla_{\boldsymbol{x}_{t+\Delta t}}\log p(\boldsymbol{x}_{t+\Delta t}) \right]\Delta t}_{\mu}, \underbrace{g_{t+\Delta t}^2\Delta t\ \boldsymbol{I}}_{\Sigma}) $$
  • 在DDPM中,有 \(t+\Delta t = t+1\),即 \(x_{t+\Delta t} = x_{t+1}\)

DDPM损失函数与Score-Based损失函数的区别

  • 正太分布 \(\mathbf{x} \sim \mathcal{N}(\mathbf{\mu}, \sigma^2 \boldsymbol{I})\) 的梯度计算如下:
    $$\nabla_{\mathbf{x}}\log p(\mathbf{x}) = \nabla_{\mathbf{x}} \Big(-\frac{1}{2\sigma^2}(\mathbf{x} - \boldsymbol{\mu})^2 \Big) = - \frac{\mathbf{x} - \boldsymbol{\mu}}{\sigma^2} = - \frac{\boldsymbol{\epsilon}}{\sigma}$$
  • 结合 \(q(\mathbf{x}_t \vert \mathbf{x}_0) \sim \mathcal{N}(\sqrt{\bar{\alpha}_t} \mathbf{x}_0, (1 - \bar{\alpha}_t)\boldsymbol{I})\),可得:
    $$
    \mathbf{s}_\theta(\mathbf{x}_t, t)
    \approx \nabla_{\mathbf{x}_t} \log q(\mathbf{x}_t)
    = \mathbb{E}_{q(\mathbf{x}_0)} [\nabla_{\mathbf{x}_t} q(\mathbf{x}_t \vert \mathbf{x}_0)]
    = \mathbb{E}_{q(\mathbf{x}_0)} \Big[ - \frac{\boldsymbol{\epsilon}_\theta(\mathbf{x}_t, t)}{\sqrt{1 - \bar{\alpha}_t}} \Big]
    = - \frac{\boldsymbol{\epsilon}_\theta(\mathbf{x}_t, t)}{\sqrt{1 - \bar{\alpha}_t}}
    $$
  • Score-based模型中用神经网络建模并学习 \(\mathbf{s}_\theta(\mathbf{x}_t, t) \),DDPM中神经网络建模并学习 \(\boldsymbol{\epsilon}_\theta(\mathbf{x}_t, t)\)

附录:玻尔兹曼分布

  • 玻尔兹曼分布(Boltzmann distribution),也称为吉布斯分布(Gibbs distribution),是统计力学中的一个核心概念,它描述了在热力学平衡状态下,一个系统处于各种可能状态的概率。该分布给出了粒子占据某个量子态的概率与该状态的能量以及系统的温度之间的关系
  • 玻尔兹曼分布可以表示为:
    $$ p_i \propto e^{-\frac{\varepsilon_i}{kT}} $$
    • \( p_i \) 是系统处于状态 \( i \) 的概率
    • \( \varepsilon_i \) 是状态 \( i \) 的能量
    • \( k \) 是玻尔兹曼常数
    • \( T \) 是系统的绝对温度(热力学温度)
    • 符号 \( \propto \) 表示正比例关系
    • 实际使用中概率可以定义为: \(p_i = \frac{1}{Q}e^{-\frac{\varepsilon_i}{kT}}\),其中\(Q\)是归一化因子,用于确保概率和为1
  • 这意味着,在较高的温度下,不同能量状态之间的概率差异会减小;而在较低的温度下,低能量状态将比高能量状态更有可能被占用
  • 更一般的情况下,我们所说的玻尔兹曼分布,形式上有所变化,更像是Softmax形式,比如假定能量函数为 \(\{E_i\}_{i=1}^N\),玻尔兹曼分布可以定义为 \(p_i \propto e^{\frac{1}{\beta} E_i}\):
    $$ p_i = \frac{e^{\frac{1}{\beta} E_i}}{\sum_i e^{\frac{1}{\beta} E_i}} $$
    • \(\frac{1}{\beta}\) 是温度系数

附录:Langevin dynamics方法

  • Langevin dynamics 是一种用于模拟分子系统中粒子运动的方法,它结合了经典力学和随机过程。这种方法得名于法国物理学家保罗·朗之万(Paul Langevin),他提出了描述布朗运动的方程

附录:证明加权均方误差形式

注:以下证明参考自生成扩散模型漫谈(五):一般框架之SDE篇,shyoshyo评论

  • 目标是证明:
    $$ \begin{aligned}
    \forall \boldsymbol{f}(\boldsymbol{x}), g(\boldsymbol{x}), \quad \mathop{\arg\min}_\boldsymbol{\mu} \mathbb{E}_{\boldsymbol{x}}\left[ g(\boldsymbol{x}) \cdot \left\Vert
    \boldsymbol{\mu} - \boldsymbol{f}(\boldsymbol{x})
    \right\Vert^2 \right] = \frac { \mathbb{E}_{\boldsymbol{x}}[g(\boldsymbol{x}) \cdot \boldsymbol{f}(\boldsymbol{x})] }{ \mathbb{E}_{\boldsymbol{x}}[g(\boldsymbol{x})] }
    \end{aligned}
    $$
  • 证明过程:
    $$\begin{aligned}
    \mathop{\arg\min}_\boldsymbol{\mu} \mathbb{E}_{\boldsymbol{x}}\left[ g(\boldsymbol{x}) \cdot \left\Vert
    \boldsymbol{\mu} - \boldsymbol{f}(\boldsymbol{x})
    \right\Vert^2 \right] = & \mathop{\arg\min}_\boldsymbol{\mu} \mathbb{E}_{\boldsymbol{x}}\left[ g(\boldsymbol{x}) \cdot \left( \left\Vert
    \boldsymbol{\mu} \right\Vert^2 - 2 \boldsymbol{\mu} \cdot \boldsymbol{f}(\boldsymbol{x}) + \left\Vert
    \boldsymbol{ \boldsymbol{f}(\boldsymbol{x})} \right\Vert^2 \right) \right] \\
    = & \mathop{\arg\min}_\boldsymbol{\mu} \mathbb{E}_{\boldsymbol{x}}\left[ g(\boldsymbol{x}) \cdot \left( \left\Vert
    \boldsymbol{\mu} \right\Vert^2 - 2 \boldsymbol{\mu} \cdot \boldsymbol{f}(\boldsymbol{x}) \right) \right] \\
    = & \mathop{\arg\min}_\boldsymbol{\mu} \left( \left\Vert
    \boldsymbol{\mu} \right\Vert^2 \cdot \mathbb{E}_{\boldsymbol{x}}\left[ g(\boldsymbol{x}) \right] - 2 \boldsymbol{\mu} \cdot \mathbb{E}_{\boldsymbol{x}}\left[ g(\boldsymbol{x})\cdot\boldsymbol{f}(\boldsymbol{x}) \right] \right) \\
    = & \mathop{\arg\min}_\boldsymbol{\mu} \left( \left\Vert
    \boldsymbol{\mu} \right\Vert^2 - 2 \boldsymbol{\mu} \cdot \frac{\mathbb{E}_{\boldsymbol{x}}\left[ g(\boldsymbol{x})\cdot\boldsymbol{f}(\boldsymbol{x}) \right]}{\mathbb{E}_{\boldsymbol{x}}\left[ g(\boldsymbol{x}) \right]} \right) \\
    = & \mathop{\arg\min}_\boldsymbol{\mu} \left( \left\Vert
    \boldsymbol{\mu} \right\Vert^2 - 2 \boldsymbol{\mu} \cdot \frac{\mathbb{E}_{\boldsymbol{x}}\left[ g(\boldsymbol{x})\cdot\boldsymbol{f}(\boldsymbol{x}) \right]}{\mathbb{E}_{\boldsymbol{x}}\left[ g(\boldsymbol{x}) \right]} +
    \left\Vert \frac{\mathbb{E}_{\boldsymbol{x}}\left[ g(\boldsymbol{x})\cdot\boldsymbol{f}(\boldsymbol{x}) \right]}{\mathbb{E}_{\boldsymbol{x}}\left[ g(\boldsymbol{x}) \right]}\right\Vert^2 \right) \\
    = & \mathop{\arg\min}_\boldsymbol{\mu} \left\Vert
    \boldsymbol{\mu} - \frac{\mathbb{E}_{\boldsymbol{x}}\left[ g(\boldsymbol{x})\cdot\boldsymbol{f}(\boldsymbol{x}) \right]}{\mathbb{E}_{\boldsymbol{x}}\left[ g(\boldsymbol{x}) \right]}\right\Vert^2 \\
    = & \frac{\mathbb{E}_{\boldsymbol{x}}\left[ g(\boldsymbol{x})\cdot\boldsymbol{f}(\boldsymbol{x}) \right]}{\mathbb{E}_{\boldsymbol{x}}\left[ g(\boldsymbol{x}) \right]}
    \end{aligned}
    $$

DL——xDeepFM

文本介绍xDeepFM的理论介绍,包括阅读论文后自己的理解

  • 上篇博客参考: DeepFM
  • 原始论文: xDeepFM: Combining Explicit and Implicit Feature Interactions for Recommender Systems, KDD 2018

xDeepFM结构图

  • 显然, 上图中除了 CIN 部分以外,其他跟 DeepFM 基本是相同的, 所以我们论文主要讲述 CIN 组件部分, 其他的嵌入层等可参考我之前的博客DeepFM

CIN组件

Compressed Interaction Network

  • 论文中首先提出的就是这个CIN网络(Compressed Interaction Network)
  • 结构图如下:
  • 理解
    • 每个隐藏层都与一个池化操作连接到一起
    • 特征阶数与网络层数相关
    • 可以与 RNN 对应着看, 当前网络层由上一个隐藏层和一个额外输入确定
    • 确切的说: CIN 中当前层输入是前一层的隐藏层 + 原来的特征向量

DL——对比学习


整体说明

  • TLDR:对比学习(Contrastive Learning)是自监督学习中的一种方法,其核心思想是通过学习数据样本之间的相似性和差异性 ,使得相似样本在表示空间(embedding space)中靠近,不相似样本相互远离,从而学习一个表示空间
  • 对比学习的目标是:学习一个表示空间(embedding space),使得在这个表示空间中,满足下面的条件
    • 正样本对(相似的样本)的表示距离尽可能近
    • 负样本对(不相似的样本)的表示距离尽可能远
  • 注:通过这种对比机制,模型无需人工标注即可从数据中自动学习有意义的特征表示

详细方法说明

正负样本构造

  • 正样本 :同一数据的不同增强视图(如裁剪、旋转、颜色变换后的同一图像),或语义相似的样本
  • 负样本 :随机选择的其他数据样本,或显式定义的 dissimilar 样本
    • 常用的策略有:同一batch内的其他样本、动态队列(历史batch中的样本)等
    • 一些特殊的模型,比如BYOL(Bootstrap Your Own Latent)提出了 免负样本策略 ,详情见附录

常用损失函数

  • InfoNCE Loss(Noise Contrastive Estimation):
    $$
    \mathcal{L} = -\log \frac{\exp(sim(q, k_+) / \tau)}{\sum_{i=0}^K \exp(sim(q, k_i) / \tau)}
    $$
    • \(q\):查询样本的表示
    • \(k_+\):正样本表示,\(k_i\) 为负样本表示
    • \(\tau\):温度系数,控制分布的尖锐程度
    • \(sim(\cdot)\):相似度函数(如余弦相似度)
  • Triplet Loss :(三元组损失)
    $$
    \mathcal{L} = \max(d(a, p) - d(a, n) + \text{margin}, 0)
    $$
    • \(a\):锚点(Anchor)样本
    • \(p\):为正(Positive)样本
    • \(n\):为负(Negative)样本
    • 三元组损失的含义也就是 \(<a,p,n>\) 三元组
    • \(\text{margin}\) 是超参数,用于控制正负样本之间的最小间隔

模型网络架构

  • 通常使用双分支网络,两个分支可共享权重或不共享

对比学习的优势

  • 无监督/自监督:无需人工标注,利用数据自身结构学习
  • 迁移能力强:预训练的表示可泛化到下游任务(如分类、检测)
  • 鲁棒性:通过数据增强学习到不变性特征(如CV中的光照、旋转不变性)

应用场景

  • 计算机视觉:图像分类(SimCLR)、目标检测(MoCo)
  • 自然语言处理:句子表示学习(SimCSE)
  • 多模态学习:图文匹配(CLIP)、视频-文本对齐

附录:BYOL 的免负样本策略

  • 原始论文:Bootstrap Your Own Latent A New Approach to Self-Supervised Learning, NeurIPS 2020, Google DeepMind
  • 比如BYOL(Bootstrap Your Own Latent)提出了 免负样本策略 ,其中Target网络的参数通过指数移动平均(EMA)从Online网络缓慢更新(动量更新),模型学习目标是最小化同一图像的不同增强视图(正样本对,分别输入Target网络和Online网络中)的表示距离
  • BYOL模型的整体架构图如下:
  • 一种更容易理解的架构图:

附录:NCE 和 InfoNCE 损失

  • InfoNCE 和 NCE 的核心区别可以一句话概括为:
    • NCE 用“二分类”把真实样本从 K 个噪声里挑出来;
    • InfoNCE 用“K+1 类 Softmax”把真实样本从 K 个负样本里挑出来,并直接最大化互信息下界
  • 下面给出各自的损失函数(公式均为单样本版本,可简单批平均得到最终损失)

Noise Contrastive Estimation (NCE)

  • 目标:估计归一化常数 Z,同时学习打分函数 \(s_\theta(x)\)
  • NCE 损失(对一条真实样本 \(x\) 和 K 条噪声 \(x’\sim q\)):
    $$
    \mathcal L_{\text{NCE} } = -\log \frac{e^{s_\theta(x)} }{e^{s_\theta(x)} + K e^{s_\theta(x’)}/Z} - \sum_{k=1}^K \log \frac{e^{s_\theta(x’_k)}/Z}{e^{s_\theta(x)} + K e^{s_\theta(x’_k)}/Z}
    $$
    • 实际实现时通常把 Z 也当可学习参数,上式退化为二分类交叉熵:
      • 正类 logits 为 \(s_\theta(x)-\log Z\)
      • 负类 logits 为 \(s_\theta(x’)-\log Z\)

InfoNCE

  • InfoNCE 又称“对比预测编码”损失(Contrastive Predictive Coding Loss),也可简称为 CPC Loss
  • 目标:最大化互信息 \(I(x; c)\) 的下界,其中 \(c\) 为上下文/表征
  • 对一条正样本 \((x, c)\) 和 K 条负样本 \(\{(x’_k, c)\}\):
    $$
    \mathcal L_{\text{InfoNCE} } = -\log \frac{e^{f(x,c)/\tau} }{\displaystyle e^{f(x,c)/\tau} + \sum_{k=1}^K e^{f(x’_k,c)/\tau} }
    $$
    • 这里 \(f(\cdot,\cdot)\) 是兼容函数(通常用内积或余弦相似度),\(\tau>0\) 为温度超参
    • 当 \(K\rightarrow\infty\) 时,该损失给出的下界趋于真实的互信息,因此得名 InfoNCE

互信息 与 InfoNCE 的关联

  • 互信息衡量了两个分布的依赖程度,当两个分布完全独立,他们的互信息为 0,当两个分布完全依赖,他们的互信息为其中一个分布的熵
  • InfoNCE 损失的设计目标是最大化互信息的下界 ,而非直接计算互信息
  • 当负样本数量 \(K\rightarrow\infty\) 时,InfoNCE 损失对应的下界会收敛到真实的互信息 \(I(X;Y)\),这也是该损失函数命名的核心原因

DL——条件扩散模型

文本介绍Conditional Diffusion的相关知识

  • 参考链接:
    • 生成扩散模型漫谈(九):条件控制生成结果:论文的证明大多参考自苏神的博客
    • What are Diffusion Models?:Lilian Weng的博客
    • Diffusion Models Beat GANs on Image Synthesis, OpenAI, 2021:第一篇条件扩散模型的文章,Classifier Guidance 方法;
      • 文章附录:Supplemental中有相关推导
      • 实现讲解:sunlin-ai.github.io/guided-diffusion
    • Classifier-Free Diffusion Guidance, Google Research, Brain team, 2022:第一篇使用Classifier-free Guidance方法的文章
    • Score-based generative modeling through stochastic differential equations, Stanford & Google, 2021:随机微分方程的视角
    • 【笔记】扩散模型(五):Classifier-Free Guidance 理论推导与代码实现

整体概述

  • 在图像生成领域,条件一般可以分成类别标签或者是一段文本
  • 从方法上来看,条件控制生成的方式主要分两种:Classifier Guidance 和 Classifier-free Guidance
    • Classifier Guidance :先训练无条件的模型,训练后在生成时引入条件分类器(Classifier)。这种方式灵活,无需重新训练,但是生成效果较差
    • Classifier-free Guidance:训练时引入条件,生成时无需Classifier。这种方式需要重新训练Diffusion模型,但生成效果更好些

前置推导

  • 正太分布 \(\mathbf{x} \sim \mathcal{N}(\mathbf{\mu}, \sigma^2 \boldsymbol{I})\) 的梯度计算如下:
    $$\nabla_{\mathbf{x}}\log p(\mathbf{x}) = \nabla_{\mathbf{x}} \Big(-\frac{1}{2\sigma^2}(\mathbf{x} - \boldsymbol{\mu})^2 \Big) = - \frac{\mathbf{x} - \boldsymbol{\mu}}{\sigma^2} = - \frac{\boldsymbol{\epsilon}}{\sigma}$$
  • 结合 \(q(\mathbf{x}_t \vert \mathbf{x}_0) \sim \mathcal{N}(\sqrt{\bar{\alpha}_t} \mathbf{x}_0, (1 - \bar{\alpha}_t)\boldsymbol{I})\),可得:
    $$
    \mathbf{s}_\theta(\mathbf{x}_t, t)
    \approx \nabla_{\mathbf{x}_t} \log q(\mathbf{x}_t)
    = \mathbb{E}_{q(\mathbf{x}_0)} [\nabla_{\mathbf{x}_t} q(\mathbf{x}_t \vert \mathbf{x}_0)]
    = \mathbb{E}_{q(\mathbf{x}_0)} \Big[ - \frac{\boldsymbol{\epsilon}_\theta(\mathbf{x}_t, t)}{\sqrt{1 - \bar{\alpha}_t}} \Big]
    = - \frac{\boldsymbol{\epsilon}_\theta(\mathbf{x}_t, t)}{\sqrt{1 - \bar{\alpha}_t}}
    $$
    • 其中 \(\mathbf{s}_\theta(\mathbf{x}_t, t) \) 是Noise Conditional Score Network (NCSN),详情参见论文:(NCSN)Generative Modeling by Estimating Gradients of the Data Distribution, Stanford, 2020

Classifier Guidance 方法

Classifier Guidance Diffusion的直观理解

  • 参考自:通俗理解Classifier Guidance 和 Classifier-Free Guidance 的扩散模型

    2021年OpenAI在「Diffusion Models Beat GANs on Image Synthesis」中提出Classifier Guidance,使得扩散模型能够按类生成。后来「More Control for Free! Image Synthesis with Semantic Diffusion Guidance」把Classifier Guidance推广到了Semantic Diffusion,使得扩散模型可以按图像、按文本和多模态条件来生成,例如,风格化可以通过content和style两者共同进行引导,这些都是通过梯度引导来实现

    • Classifier Guidance可以通过Score function(问题:Score function是什么?)直观地解释,用贝叶斯定理将条件生成概率进行对数分解:
      $$
      \begin{align}
      \nabla_{x_t} \log p(x_t|y) &= \nabla_{x_t} \log \Big( \frac{p(x_t)p(y|x_t)}{p(y)}\Big) \\
      &= \nabla_{x_t} \log p(x_t) + \nabla_{x_t} \log p(y|x_t) - \nabla_{x_t} \log p(y) \\
      &= \underbrace{\nabla_{x_t} \log p(x_t)}_{\text{unconditional score}} + \underbrace{\nabla_{x_t} \log p(y|x_t)}_{\text{classifier gradient}}
      \end{align}
      $$
    • 从上式可以看到,Classifier Guidance条件生成只需额外添加一个classifier的梯度来引导。从成本上看,Classifier Guidance 需要训练噪声数据版本的classifier网络,推理时每一步都需要额外计算classifier的梯度
  • 以上是简单的理解,推导不严谨,论文接下来对DDPM和DDIM对应的Classifier Guidance Diffusion方法进行详细推导

Conditional Diffusion Process

  • 本小节相关推导参考自:Diffusion Models Beat GANs on Image Synthesis, OpenAI, 2021——Supplemental

    • 其他参考:深度学习(生成式模型)——Classifier Guidance Diffusion
  • 条件扩散模型相关定义 :

    • 参考普通扩散模型的前向过程 \(q(x_{t+1}|x_{t})\) 和后向过程为 \(q(x_{t}|x_{t+1})\)
    • 定义带条件的扩散模型的前向过程 \(\hat{q}(x_{t+1}|x_{t}, y)\) 和后向过程为 \(\hat{q}(x_t|x_{t+1}, y)\)
  • 设定:条件扩散模型的前向过程与普通扩散模型的前向过程一致,与条件无关
    $$
    \begin{align}
    \hat{q}(x_0) &:= q(x_0) \\
    \hat{q}(y|x_0) &:= \text{Known labels per sample} \\
    \hat{q}(x_{t+1}|x_t,y) &:= q(x_{t+1}|x_t) \\
    \hat{q}(x_{1:T}|x_0,y) &:= \prod_{t=1}^T \hat{q}(x_{t}|x_{t-1}, y) \\
    \end{align}
    $$

    • 直观理解:上式表名前向过程中对 \(x_0\) 如何增加噪音(\(\epsilon \sim \mathcal{N}(0,1)\))确实与 \(x_0\) 类别无关
  • 进一步地,我们可以推导得到,前向过程中的每一步加噪都与条件无关(以下内容详细推导可见论文:Diffusion Models Beat GANs on Image Synthesis, OpenAI, 2021——Supplemental):
    $$
    \begin{align}
    \hat{q}(x_{t+1}|x_{t}) &= \hat{q} (x_{t+1}|x_{t},y) \\
    \hat{q}(x_{1:T}|x_0) &= q(x_{1:T}|x_0) \\
    \hat{q}(x_t) &= q(x_t) \\
    \hat{q}(y|x_t, x_{t+1}) &= \hat{q}(y|x_t) \\
    \hat{q}(x_{t}|x_{t+1}) &= q(x_{t}|x_{t+1}) \\
    \end{align}
    $$

    • 注意,其中: \(\hat{q}(x_{t}|x_{t-1})\) 中不含有条件,实际是一个边际分布(或边缘分布):
      • \(\hat{q}(x_{t}|x_{t-1}) = \mathbb{E}_{y}[\hat{q}(x_{t}, y|x_{t-1})]\)
      • 同理有: \(\hat{q}(x_t) = \mathbb{E}_{y}[\hat{q}(x_t,y)] = \mathbb{E}_{y}[\mathbb{E}_{x_{0:t-1}}[\hat{q}(y,x_0,\cdots,x_{t})]]\)
      • 或: \(\hat{q}(x_t) = \mathbb{E}_{x_{0:t-1}}[\hat{q}(x_0,\cdots,x_{t})] = \mathbb{E}_{x_{0:t-1}}[\mathbb{E}_{y}[\hat{q}(y,x_0,\cdots,x_{t})]]\)
    • 关于 \(\hat{q}(y|x_t, x_{t+1}) = \hat{q}(y|x_t)\) 的理解:因为 \(x_{t+1}\) 是 \(x_t\) 增加前向噪音得到的,而前向过程不依赖于条件,该式子的证明如下:
      $$
      \begin{align}
      \hat{q}(y|x_{t},x_{t+1}) &= \frac{\hat{q}(y,x_{t},x_{t+1})}{\hat{q}(x_{t},x_{t+1})} = \frac{\hat{q}(x_{t+1}|y,x_{t})\hat{q}(y|x_{t})\hat{q}(x_{t})}{\hat{q}(x_{t+1}|x_{t})\hat{q}(x_{t})} \\
      &= \hat{q} (x_{t+1}|x_{t}, y) \frac{\hat{q}(y|x_{t})}{\hat{q}(x_{t+1}|x_{t})} \\
      &= \hat{q} (x_{t+1}|x_{t}) \frac{\hat{q}(y|x_{t})}{\hat{q}(x_{t+1}|x_{t})}\\
      &= \hat{q}(y|x_{t}) \\
      \end{align}
      $$
      • 其他补充说明 :因为前向过程与条件无关 ,可以理解为已知 \(x_t\) 时,条件 \(y\) 就与反向过程的前一步 \(x_{t+1}\) 无关了,故可以消掉 \(x_{t+1}\) ;但由于反向过程依赖条件 \(y\),不能消掉 \(x_t\),即 \(\hat{q}(y|x_t, x_{t+1}) \neq \hat{q}(y|x_{t+1})\),可理解为在相同的 \(x_{t+1}\) 下, \(x_t\) 与条件 \(y\) 相关( \(x_{t+1}\) 想通的条件下不同的条件 \(y\) 会生成不同的 \(x_t\) )
    • 关于 \(\hat{q}(x_{t}|x_{t+1}) = q(x_{t}|x_{t+1})\) 的理解:,该式子的证明如下:
      $$
      \begin{align}
      \hat{q}(x_{t}|x_{t+1}) &= \frac{\hat{q}(x_{t+1}|x_{t})\hat{q}(x_{t})}{\hat{q}(x_{t+1})} = \frac{q(x_{t+1}|x_{t})q(x_{t})}{q(x_{t+1})} = q(x_t|x_{t+1})
      \end{align}
      $$
  • 接下来我们到了最终目标:推导条件扩散模型的反向过程
    $$
    \begin{align}
    \hat{q}(x_{t}|x_{t+1},y) &= \frac{\hat{q}(x_{t},x_{t+1},y)}{\hat{q}(x_{t+1},y)} = \frac{\hat{q}(y|x_{t},x_{t+1})\hat{q}(x_{t}|x_{t+1})\hat{q}(x_{t+1})}{\hat{q}(y|x_{t+1})\hat{q}(x_{t+1})} \\
    &= \frac{\hat{q}(y|x_{t},x_{t+1})\hat{q}(x_{t}|x_{t+1})}{\hat{q}(y|x_{t+1})} \\
    &= \frac{\hat{q}(y|x_{t})\hat{q}(x_{t}|x_{t+1})}{\hat{q}(y|x_{t+1})} \\
    &= \frac{q(x_{t}|x_{t+1})\hat{q}(y|x_{t})}{\hat{q}(y|x_{t+1})} \\
    \end{align}
    $$

  • 至此,在已知 \(x_{t+1}\) 时,在条件 \(y\) 下,为了采样生成 \(x_t\),我们可以按照带条件的后向过程的概率 \(\hat{q}(x_{t}|x_{t+1},y) = \frac{q(x_{t}|x_{t+1})\hat{q}(y|x_{t})}{\hat{q}(y|x_{t+1})}\) 采样来实现。其中 \(\hat{q}(y|x_{t+1})\) 与 \(x_t\) 无关,可以设置为常数;于是可按照下面的形式采样(这里使用 \(\frac{1}{Z}\) 更容易理解):
    $$ x_t \sim \frac{1}{Z} q(x_{t}|x_{t+1})\hat{q}(y|x_{t}) $$

    • 具体场景下, \(q(x_{t}|x_{t+1})\) 是无条件的Diffusion后向过程,可以通过无条件的Diffusion网络 \(p_\theta(x_{t}|x_{t+1})\) 来实现; \(\hat{q}(y|x_{t})\) 则可通过在扰动后的数据集 \(x_t \sim q(x_t)\) 上训练一个分类器(Classifier)来实现;故最终采样形式可以表示如下形式:

Classifier Guidance DDPM

  • 本小节相关推导参考自:Diffusion Models Beat GANs on Image Synthesis, OpenAI, 2021——Supplemental,论文附录有其他相关推导可做参考

  • 推导过程:

    • 推导过程中使用到一个技巧,在高斯分布相关的推导中,将指数函数临时取对数来进行推导,推导完成后得到的仍然可以看做一个高斯分布的指数部分(在论文附录中提供的另一种推导方法没有使用到这个点)
  • 其他说明:在Diffusion Models Beat GANs on Image Synthesis, OpenAI, 2021中,作者发现,在分类器上增加一个梯度缩放参数 \(s\) (gradient scale \(s\) )可以更好的调节生成效果:
    $$
    \begin{equation}\boldsymbol{x}_{t-1} = \boldsymbol{\mu}(\boldsymbol{x}_t) \color{red}{+} {\color{red}{\underbrace{ \color{black}{s} \sigma_t^2 \nabla_{\boldsymbol{x}_t} \log p(\boldsymbol{y}|\boldsymbol{x}_t)}_{\text{新增项}}}} + \sigma_t\boldsymbol{\varepsilon},\quad \boldsymbol{\varepsilon}\sim \mathcal{N}(\boldsymbol{0},\boldsymbol{I})\end{equation}
    $$

    • 当 \(s > 1\) 时,生成过程中将更多由Classifier主导,提升生成结果和条件 \(y\) 的相关性,降低生成结果的多样性(没有改变方差,实际上多样性不会变化吧?);反之,则会降低生成结果的相关性,增加多样性
    • 关于 \(s\) 这个参数还有更多理解和推导,讨论详情可见:生成扩散模型漫谈(九):条件控制生成结果:
      • \(s\) 可以理解为在概率函数上的指数,用来控制图片的聚焦程度, \(s\) 越大,下面的条件概率 \(\tilde{p}(\boldsymbol{y}|\boldsymbol{x}_t)\) 越趋近于one-hot
        $$\begin{equation}\tilde{p}(\boldsymbol{y}|\boldsymbol{x}_t) = \frac{p^{s}(\boldsymbol{y}|\boldsymbol{x}_t)}{Z(\boldsymbol{x}_t)},\quad Z(\boldsymbol{x}_t)=\sum_{\boldsymbol{y}} p^{s}(\boldsymbol{y}|\boldsymbol{x}_t)\end{equation}$$
  • 其他证明方式见附录

Classifier Guidance DDIM

  • 本小节相关推导参考自:Diffusion Models Beat GANs on Image Synthesis, OpenAI, 2021——Supplemental,论文附录有其他相关推导可做参考

  • 推导过程:

    • 上图第一个公式中的梯度证明见论文的“前置推导”
    • 推导过程中使用了一个技巧,通过求解梯度的相似形式来对比得到最终结果
    • 公式(58)中 \(p_\theta(x_t)p_\phi(y|x_t)\) 没有直接来源,但可以从下面的推导看出,\(\nabla_{x_t} \log (p_\theta(x_t)p_\phi(y|x_t)) = \nabla_{x_t} \log p(x_t|y)\)
      $$
      \begin{align}
      \nabla_{x_t} \log p(x_t|y) &= \nabla_{x_t} \log p(x_t) +\nabla_{x_t} \log p(y|x_t) - \nabla_{x_t} \log p(y) \\
      &= \nabla_{x_t} \log p(x_t) +\nabla_{x_t} \log p(y|x_t) \\
      &= \nabla_{x_t} \log (p(x_t)p(y|x_t)) \\
      \end{align}
      $$
  • 其他说明,这里也可以在分类器的梯度上增加一个权重 \(w\),调节条件相关性和多样性:
    $$ \hat{\boldsymbol{\epsilon}}_\theta(\mathbf{x}_t, t) = \boldsymbol{\epsilon}_\theta(x_t, t) - \sqrt{1 - \bar{\alpha}_t} w \nabla_{\mathbf{x}_t} \log p_\phi(y \vert \mathbf{x}_t) $$

  • 其他证明方式见附录

基于Classifier Guidance的DDPM和DDIM的采样过程

  • Classifier Guidance DDPM和DDIM下伪代码如下:

    • 其中 \(\Sigma\) 表示协方差矩阵,有不同的实现方式,IDDPM中,使用了 \(\mathbf{\Sigma}_\theta(\mathbf{x}_t, t) = \exp(\mathbf{v} \log \beta_t + (1-\mathbf{v}) \log \tilde{\beta}_t)\), \(\mathbf{v}_{\theta}(x_t, t)\) 维度是与 \(\mathbf{x}_t\) 相同的,(详情见improved_diffusion源码:模型定义和improved_diffusion源码:向量使用)
    • 问题:矩阵 \(\Sigma\) 和梯度向量相乘的结果是向量,这里梯度向量是列向量才能相乘

Classifier-free Guidance

  • Classifier-free Guidance的方法直接讲条件添加到原始Diffusion模型中,从而使得模型在训练时就能感知到条件,因此,在采样(生成)时,不需要额外训练Classifier了
  • 一个直观的解释是:
    • 在原始分布 \(p(x_{t-1}|x_t)\) 增加条件 \(y\),则原始分布变成 \(p(x_{t-1}|x_t,y)\)
      $$
      \begin{equation}
      p(\boldsymbol{x}_{t-1}|\boldsymbol{x}_t, \boldsymbol{y}) = \mathcal{N}(\boldsymbol{x}_{t-1}; \boldsymbol{\mu}(\boldsymbol{x}_t, \boldsymbol{y}),\sigma_t^2\boldsymbol{I})
      \end{equation}$$
    • 接着,在训练时,噪声网络上也增加输入 \(y\),即 \(\epsilon_\theta(x_t, y, t)\)
    • 最后,可以使用下面的式子来实现加权
      $$\begin{equation}\tilde{\boldsymbol{\epsilon}}_{\boldsymbol{\theta}}(\boldsymbol{x}_t, \boldsymbol{y}, t) = (1 + w)\boldsymbol{\epsilon}_{\boldsymbol{\theta}}(\boldsymbol{x}_t, \boldsymbol{y}, t) - w \boldsymbol{\epsilon}_{\boldsymbol{\theta}}(\boldsymbol{x}_t, t)\end{equation}
      $$
      • 其中,无条件的 \(\epsilon_\theta(x_t, t)\) 通过设置一个特定的条件 \(\varnothing\) 获得,即 \(\epsilon_\theta(x_t, t) = \epsilon_\theta(x_t, \varnothing, t)\)
      • \(w\) 也叫做 guidance scale,用于调整生成条件相关性和多样性
  • 接下来我们介绍详细推导过程,首先,回顾条件概率转换:
    $$
    \begin{align}
    \nabla_{x_t} \log p(x_t|y) &= \nabla_{x_t} \log \Big( \frac{p(x_t)p(y|x_t)}{p(y)}\Big) \\
    &= \nabla_{x_t} \log p(x_t) + \nabla_{x_t} \log p(y|x_t) - \nabla_{x_t} \log p(y) \\
    &= \underbrace{\nabla_{x_t} \log p(x_t)}_{\text{unconditional score}} + \underbrace{\nabla_{x_t} \log p(y|x_t)}_{\text{classifier gradient}}
    \end{align}
    $$
  • 于是有:
    $$ \nabla_{\mathbf{x}_t} \log p(y \vert \mathbf{x}_t) = \nabla_{\mathbf{x}_t} \log p(\mathbf{x}_t \vert y) - \nabla_{\mathbf{x}_t} \log p(\mathbf{x}_t) $$
  • 进一步地,有(以下推导来自What are Diffusion Models?的推导):
    $$
    \begin{aligned}
    \nabla_{\mathbf{x}_t} \log p(y \vert \mathbf{x}_t)
    &= \nabla_{\mathbf{x}_t} \log p(\mathbf{x}_t \vert y) - \nabla_{\mathbf{x}_t} \log p(\mathbf{x}_t) \\
    &= - \frac{1}{\sqrt{1 - \bar{\alpha}_t}}\Big( \boldsymbol{\epsilon}_\theta(\mathbf{x}_t, t, y) - \boldsymbol{\epsilon}_\theta(\mathbf{x}_t, t) \Big) \\
    \end{aligned}
    $$
  • 回顾DDIM Classifier Guidance里面的推导有:
    $$
    \begin{aligned}
    \bar{\boldsymbol{\epsilon}}_\theta(\mathbf{x}_t, t, y)
    &= \boldsymbol{\epsilon}_\theta(\mathbf{x}_t, t, y) - \sqrt{1 - \bar{\alpha}_t} \ w \nabla_{\mathbf{x}_t} \log p(y \vert \mathbf{x}_t) \\
    &= \boldsymbol{\epsilon}_\theta(\mathbf{x}_t, t, y) + w \big(\boldsymbol{\epsilon}_\theta(\mathbf{x}_t, t, y) - \boldsymbol{\epsilon}_\theta(\mathbf{x}_t, t) \big) \\
    &= (w+1) \boldsymbol{\epsilon}_\theta(\mathbf{x}_t, t, y) - w \boldsymbol{\epsilon}_\theta(\mathbf{x}_t, t)
    \end{aligned}
    $$
  • 采样时,利用将DDPM或者DDIM中的 \(\boldsymbol{\epsilon}_\theta(\mathbf{x}_t, t)\) 替换为 \(\bar{\boldsymbol{\epsilon}}_\theta(\mathbf{x}_t, t, y)\), 正常采样即可
  • 总结一下,Classifier-free Guidance方法的训练流程和采样流程如下:

Classifier-free Guidance和Classifier Guidance谁更好?

  • GLIDE: Towards Photorealistic Image Generation and Editing with Text-Guided Diffusion Models, OpenAI, 2022对CLIP Guidance和Classifier-free Guidance两种策略进行实验,结果发现Classifier-free Guidance效果更好

    The guided diffusion model, GLIDE (Nichol, Dhariwal & Ramesh, et al. 2022), explored both guiding strategies, CLIP guidance and classifier-free guidance, and found that the latter is more preferred. They hypothesized that it is because CLIP guidance exploits the model with adversarial examples towards the CLIP model, rather than optimize the better matched images generation.


附录:DDPM和DDIM加入条件以后的采样形式为什么不同呢?

  • 可以证明,在设置DDPM中协方差矩阵 \(\Sigma\) 使用固定值后,DDPM和DDIM的Classifier Guidance 形式基本是非常相似的,都可以看做是用梯度 \(\nabla_{x_t}\log p_\phi(y|x_t)\) 对 \(\mathbf{\epsilon}_\theta(x_t, t)\) 进行修正【有时间时可以详细推导一下】

  • 补充对比:

    • 带条件的训练形式:

    • 原始DDPM采样形式
      $$ x_{t-1} = \frac{1}{\sqrt{\alpha_t}}\Big( x_t - \frac{1-\alpha_t}{\sqrt{1-\bar{\alpha}_t}}\epsilon_\theta(x_t, t) \Big) + \sigma_t z $$

    • 原始DDIM采样形式
      $$x_s = \sqrt{\bar{\alpha}_s}\left(\frac{x_k-\sqrt{1-\bar{\alpha}_k}\epsilon_{\theta}(x_k,k)}{\sqrt{\bar{\alpha}_k}}\right) + \sqrt{1-\bar{\alpha}_s-a_1\sigma_k^2}\epsilon_{\theta}(x_k,k) + a_2\sigma_k \epsilon$$


附录:其他推导-Classifier Guidance DDPM

  • 下面的推导参考苏神生成扩散模型漫谈(九):条件控制生成结果的推导
  • 在推导过程中,在原始分布 \(p(x_{t-1}|x_t)\) 增加条件 \(y\),则原始分布变成 \(p(x_{t-1}|x_t,y)\)
  • 根据贝叶斯公式有:
    $$\begin{equation}p(\boldsymbol{x}_{t-1}|\boldsymbol{x}_t, \boldsymbol{y}) = \frac{p(\boldsymbol{x}_{t-1}|\boldsymbol{x}_t)p(\boldsymbol{y}|\boldsymbol{x}_{t-1}, \boldsymbol{x}_t)}{p(\boldsymbol{y}|\boldsymbol{x}_t)}\label{eq:bayes-1}\end{equation}$$
  • 由于前向过程与条件无关, \(x_t\) 是由 \(x_{t-1}\) 加上与条件无关的噪声得到的,所以 \(p(\boldsymbol{y}|\boldsymbol{x}_{t-1}, \boldsymbol{x}_t) = p(\boldsymbol{y}|\boldsymbol{x}_{t-1})\),这在前文已经得到证明
  • 于是有:
    $$ \begin{equation}p(\boldsymbol{x}_{t-1}|\boldsymbol{x}_t, \boldsymbol{y}) = \frac{p(\boldsymbol{x}_{t-1}|\boldsymbol{x}_t)p(\boldsymbol{y}|\boldsymbol{x}_{t-1})}{p(\boldsymbol{y}|\boldsymbol{x}_t)} = p(\boldsymbol{x}_{t-1}|\boldsymbol{x}_t) \exp({\log p(\boldsymbol{y}|\boldsymbol{x}_{t-1}) - \log p(\boldsymbol{y}|\boldsymbol{x}_t)})\label{eq:bayes-2}\end{equation} $$
  • 接下来我们要求解 \(\log p(\boldsymbol{y}|\boldsymbol{x}_{t-1}) - \log p(\boldsymbol{y}|\boldsymbol{x}_t)\) 这一项,首先做一下近似,当 \(T\) 足够大时,有 \(x_t\) 和 \(x_{t-1}\) 非常接近,故而可以用泰勒展开来近似:
    $$ \begin{equation}\log p(\boldsymbol{y}|\boldsymbol{x}_{t-1}) - \log p(\boldsymbol{y}|\boldsymbol{x}_t)\approx (\boldsymbol{x}_{t-1} - \boldsymbol{x}_t)\cdot\nabla_{\boldsymbol{x}_t} \log p(\boldsymbol{y}|\boldsymbol{x}_t)\end{equation}$$
    • 其中 \(\nabla_{\boldsymbol{x}_t} \log p(\boldsymbol{y}|\boldsymbol{x}_t)\) 是一种简写形式,实际上有 \(\nabla_{\boldsymbol{x}_t} \log p(\boldsymbol{y}|\boldsymbol{x}_t) = \nabla_{\boldsymbol{x}} \log p(\boldsymbol{y}|\boldsymbol{x})\vert_{\boldsymbol{x} = \boldsymbol{x}_t}\),表示函数在 \(\boldsymbol{x}_t\) 处的梯度
  • 假设 \(p(\boldsymbol{x}_{t-1}|\boldsymbol{x}_t)=\mathcal{N}(\boldsymbol{x}_{t-1};\boldsymbol{\mu}(\boldsymbol{x}_t),\sigma_t^2\boldsymbol{I})\propto \exp({-\frac{\Vert \boldsymbol{x}_{t-1} - \boldsymbol{\mu}(\boldsymbol{x}_t)\Vert^2}{2\sigma_t^2}})\),则有
    $$
    \begin{aligned}
    p(\boldsymbol{x}_{t-1}|\boldsymbol{x}_t, \boldsymbol{y}) =&\ p(\boldsymbol{x}_{t-1}|\boldsymbol{x}_t) \exp({\log p(\boldsymbol{y}|\boldsymbol{x}_{t-1}) - \log p(\boldsymbol{y}|\boldsymbol{x}_t)}) \\
    \propto&\ \exp\Big({-\frac{\Vert \boldsymbol{x}_{t-1} - \boldsymbol{\mu}(\boldsymbol{x}_t)\Vert^2}{2\sigma_t^2} + (\boldsymbol{x}_{t-1} - \boldsymbol{x}_t)\cdot\nabla_{\boldsymbol{x}_t} \log p(\boldsymbol{y}|\boldsymbol{x}_t)}\Big) \\
    \propto&\ \exp\Big(\frac{-\Vert \boldsymbol{x}_{t-1} - \boldsymbol{\mu}(\boldsymbol{x}_t) - \sigma_t^2 \nabla_{\boldsymbol{x}_t} \log p(\boldsymbol{y}|\boldsymbol{x}_t)\Vert^2}{2\sigma_t^2}\Big)
    \end{aligned}
    $$
    • 其中 \(\exp\Big({-\frac{\Vert \boldsymbol{x}_{t-1} - \boldsymbol{\mu}(\boldsymbol{x}_t)\Vert^2}{2\sigma_t^2} + (\boldsymbol{x}_{t-1} - \boldsymbol{x}_t)\cdot\nabla_{\boldsymbol{x}_t} \log p(\boldsymbol{y}|\boldsymbol{x}_t)}\Big) \propto\ \exp\Big(\frac{-\Vert \boldsymbol{x}_{t-1} - \boldsymbol{\mu}(\boldsymbol{x}_t) - \sigma_t^2 \nabla_{\boldsymbol{x}_t} \log p(\boldsymbol{y}|\boldsymbol{x}_t)\Vert^2}{2\sigma_t^2}\Big) \) 是指数中配方后,略去了与 \(\boldsymbol{x}_{t-1}\) 无关的项,所以使用的是“正比于”(在指数部分,包括 \(\boldsymbol{x}_{t}\) 也与 \(\boldsymbol{x}_{t-1}\) 无关,可以略去,因为分布仅留下与 \(\boldsymbol{x}_{t-1}\) 相关的部分即可,注:标准的正太分布概率密度函数为 \(p(x) = \frac{1}{\sqrt{2\pi}\sigma} \exp(-\frac{(x-\mu)^2}{2\sigma^2}) \propto \exp(-\frac{(x-\mu)^2}{2\sigma^2})\),只关注与 \(x\) 有关的项即可)
  • 将上面的形式转换成正太分布,有:
    $$ \mathcal{N}(\boldsymbol{x}_{t-1};\boldsymbol{\mu}(\boldsymbol{x}_t) + \sigma_t^2 \nabla_{\boldsymbol{x}_t} \log p(\boldsymbol{y}|\boldsymbol{x}_t),\sigma_t^2\boldsymbol{I})$$
  • 也就是说按照下面形式采样即可实现条件的加入:
    $$
    \begin{equation}\boldsymbol{x}_{t-1} = \boldsymbol{\mu}(\boldsymbol{x}_t) \color{red}{+} {\color{red}{\underbrace{\sigma_t^2 \nabla_{\boldsymbol{x}_t} \log p(\boldsymbol{y}|\boldsymbol{x}_t)}_{\text{新增项}}}} + \sigma_t\boldsymbol{\varepsilon},\quad \boldsymbol{\varepsilon}\sim \mathcal{N}(\boldsymbol{0},\boldsymbol{I})\end{equation}
    $$
  • 在原始论文Diffusion Models Beat GANs on Image SynthesisClassifier Guidance DDPM的采样形式为:
    $$\begin{equation}\sigma_t^2 \nabla_{\boldsymbol{x}_t} \log p(\boldsymbol{y}|\boldsymbol{x}_t)|_{\boldsymbol{x}_t=\boldsymbol{\mu}(\boldsymbol{x}_t)}\end{equation}$$
    • 这个形式与论文推导结果不同,生成扩散模型漫谈(九):条件控制生成结果中指出两者差不多(问题:零阶近似是指在 \(x_t=\mu(x_t)\) 处进行泰勒展开吗?需要进一步理解):

      论文中梯度项在 \(\boldsymbol{\mu}(\boldsymbol{x}_t)\) 处的结果而非 \(\boldsymbol{x}_t\) 处,而一般情况下 \(\boldsymbol{\mu}(\boldsymbol{x}_t)\) 的零阶近似正是 \(\boldsymbol{x}_t\),所以两者结果是差不多的

    • 理解:梯度的位置决定了建模价值模型时使用 \(\boldsymbol{x}_t\) 还是 \(\boldsymbol{\mu}(\boldsymbol{x}_t)\),直观上理解,应该是在 \(\boldsymbol{\mu}(\boldsymbol{x}_t)\) 上进行梯度偏移,所以应该是在 \(\boldsymbol{\mu}(\boldsymbol{x}_t)\) 的梯度才对
      • Diffuser中代码实现比较奇怪,与论文伪代码不同:这部分实现的Diffuser详细代码可见Diffuser源码-采样函数
      • 其他代码实现参考:

附录:其他推导-Classifier Guidance DDIM

本小节推导主要参考自What are Diffusion Models?

  • 由[(NCSN)Generative Modeling by Estimating Gradients of the Data Distribution, Stanford, 2020]和[Score-based generative modeling through stochastic differential equations, Stanford & Google, 2021]可以知道,只需要求得目标分布的对数概率梯度即可按照该梯度进行采样,原始分布的对数概率梯度为(详细证明见论文“前置推导”):
    $$ \nabla_{\mathbf{x}_t} \log q(\mathbf{x}_t) = - \frac{1}{\sqrt{1 - \bar{\alpha}_t}} \boldsymbol{\epsilon}_\theta(\mathbf{x}_t, t) $$
  • 增加条件以后的联合概率梯度为(此时的 \(\nabla_{\mathbf{x}_t} \log q(\mathbf{x}_t, y)\) 与 \(\nabla_{\mathbf{x}_t} \log q(\mathbf{x}_t\vert y)\) 是等价的,因为 \(\nabla_{\mathbf{x}_t}\log q(y)=0\) ):
    $$
    \begin{aligned}
    \nabla_{\mathbf{x}_t} \log q(\mathbf{x}_t, y)
    &= \nabla_{\mathbf{x}_t} \log q(\mathbf{x}_t) + \nabla_{\mathbf{x}_t} \log q(y \vert \mathbf{x}_t) \\
    &\approx - \frac{1}{\sqrt{1 - \bar{\alpha}_t}} \boldsymbol{\epsilon}_\theta(\mathbf{x}_t, t) + \nabla_{\mathbf{x}_t} \log f_\phi(y \vert \mathbf{x}_t) \\
    &= - \frac{1}{\sqrt{1 - \bar{\alpha}_t}} (\boldsymbol{\epsilon}_\theta(\mathbf{x}_t, t) - \sqrt{1 - \bar{\alpha}_t} \nabla_{\mathbf{x}_t} \log f_\phi(y \vert \mathbf{x}_t))
    \end{aligned}
    $$
  • 对照两个概率的梯度形式,可以得到 \(\boldsymbol{\epsilon}_\theta(\mathbf{x}_t, t)\) 变成如下形式即可将 \(q(\mathbf{x}_t)\) 替换为带条件的 \(q(\mathbf{x}_t, y)\):
    $$\bar{\boldsymbol{\epsilon}}_\theta(\mathbf{x}_t, t) = \boldsymbol{\epsilon}_\theta(x_t, t) - \sqrt{1 - \bar{\alpha}_t} \nabla_{\mathbf{x}_t} \log f_\phi(y \vert \mathbf{x}_t)$$
  • 为了权衡Classifier Guidance的强度,可以添加一个权重 \(w\):
    $$ \bar{\boldsymbol{\epsilon}}_\theta(\mathbf{x}_t, t) = \boldsymbol{\epsilon}_\theta(x_t, t) - \sqrt{1 - \bar{\alpha}_t} w \nabla_{\mathbf{x}_t} \log f_\phi(y \vert \mathbf{x}_t) $$

附录:问题汇总

  • Classifier Guidance方法在训练Classifier时,需要包含随机扰动后的数据吧?
  • DDPM推导时(附录和正文)得到了两种不同的梯度位置 \(x_t\) 和 \(\mu_t\),实现时应该是用哪个呢?
  • Classifier Guidance方法训练过程中有哪些需要注意的?
  • Classifier-free Guidance方法训练过程中有哪些需要注意的?

DL——梯度检查点技术

  • 参考链接:
    • 原始论文 Training Deep Nets with Sublinear Memory Cost, MIT, 2016:论文以这篇文章的内容为主进行介绍,后续会补充一些 transformer 场景下的梯度检查点技术

整体总结

  • 梯度检查点(Gradient Checkpointing)技术广泛应用于当前大规模深度学习模型训练中,能有效降低显存的使用
  • 梯度检查点技术也叫做 重计算(re-materialization)技术
  • Training Deep Nets with Sublinear Memory Cost, MIT, 2016这篇文章的核心贡献是:
    • 提出并系统化了一种 “用计算换内存”的通用方法(在自动微分领域也被称为梯度检查点技术)
    • 通过分段和重计算,巧妙地将深度学习训练过程中的内存瓶颈从 \(O(n)\) 降低到 \(O(\sqrt{n})\),甚至理论上的 \(O(\log n)\),极大地拓展了论文使用现有硬件能够训练的模型规模和深度

核心问题:为什么训练深度网络如此消耗内存?

  • 在训练神经网络时,标准的训练流程包含两个步骤:
    • 前向传播 (Forward Pass) :
      • 输入数据从网络的第一层开始,逐层计算,直到最后一层得到输出
      • 在这个过程中,每一层的输出(称为“激活”或“特征图”)都需要被保存下来
    • 反向传播 (Backward Pass) :
      • 计算输出的损失(预测值与真实值的差距),然后从最后一层开始,反向逐层计算梯度
      • 为了计算某一层参数的梯度,通常需要用到该层在前向传播时产生的激活值
  • 问题出现:
    • 为了进行反向传播,必须在内存中保留网络中每一层的激活值
    • 如果一个网络有 \(n\) 层,那么内存消耗就大致与 \(n\) 成正比 ,即内存成本为 \(O(n)\)
    • 对于现在动辄成百上千层的深度模型(如 ResNet),这笔内存开销会迅速占满顶配 GPU 的几十 GB 显存,从而限制了探索更深、更复杂模型的能力

传统内存优化方法(治标不治本)

  • 论文首先提到了一些已有的内存优化技术,这些技术主要通过分析计算图 (Computation Graph) 来实现
    • 原地操作 (In-place Operation) :
      • 如果一个操作的输入值在后续计算中不再需要,那么其输出可以直接覆盖输入的内存空间
      • 例如,y = relu(x),如果 x 后面用不到了,y 的结果可以直接写在 x 的内存里
    • 内存共享 (Memory Sharing) :
      • 分析所有变量的“生命周期”,将生命周期不重叠的变量共享同一块内存
  • 这些方法能将内存占用降低2到3倍,但无法改变内存消耗随网络层数线性增长的趋势,当网络深到一定程度时,内存瓶颈依然存在

梯度检查点:用计算换内存 (Trade Computation for Memory)

  • 既然保存所有中间结果是内存消耗的根源,那么论文提出的核心思想非常直接:
    • 不保存所有中间结果,只保存其中一部分
    • 当反向传播需要用到某个被丢弃的中间结果时,再临时重新计算它
  • 这是一种典型的“用时间换空间”的策略
    • 虽然会增加一些计算量(因为需要重新执行部分前向计算),但可以极大地降低内存峰值

工作原理一:\(O(\sqrt{n})\) 内存成本算法(实用策略)

  • 这是论文提出的主要实用算法
  • \(O(\sqrt{n})\) 内存成本算法原理如下:
    • 1)分段 (Segmenting) :将一个包含 \(n\) 层的网络链条,切分成 \(k\) 个小段(segment)
    • 2)前向传播 :在正常的前向传播过程中,只保存每个分段的最终输出 ,而丢弃每个分段内部的所有中间激活值
    • 3)反向传播 :
      • 当反向传播进行到第 \(i\) 段时,由于计算该段的梯度需要其内部的激活值(这些值已经被丢弃了),算法会执行一次“局部前向传播”:
        • 利用保存的第 \(i-1\) 段的输出作为输入,重新计算一次第 \(i\) 段的前向传播,以得到所有需要的激活值
      • 计算完梯度后,这些临时重新计算的激活值可以立即被丢弃

关键推导:为什么是 \(O(\sqrt{n})\)?

  • 内存成本分析:假设网络总共有 \(n\) 层,被均匀地切分成 \(k\) 段,那么每一段的长度就是 \(n/k\)层
  • 总内存成本主要由两部分构成:
    • 1)段间内存 (Inter-segment Memory) :用于存储 \(k\) 个分段的输出,以便在反向传播时作为“检查点”(checkpoint)
      • 这部分的成本是 \(O(k)\)
    • 2)段内内存 (Intra-segment Memory) :在对任何一段进行反向传播时,需要临时重新计算并存储该段内部的所有激活值
      • 由于所有段中最大的内存开销决定了峰值,这部分的成本是 \(O(n/k)\)
  • 因此,总的内存成本可以表示为:
    $$\text{Cost}(n, k) = O(k) + O(n/k)$$
  • 为了让总成本最低,论文需要让这两部分达到一个平衡。一个简单的优化方法是让它们的量级相等(实际上等价于导数为 0 的推导):
    $$k \approx \frac{n}{k} \implies k^2 \approx n \implies k = \sqrt{n}$$
  • 当选择 \(k=\sqrt{n}\) 时,总内存成本为:
    $$\text{Cost} = O(\sqrt{n}) + O(n/\sqrt{n}) = O(\sqrt{n}) + O(\sqrt{n}) = O(\sqrt{n})$$
  • 至此,我们就成功地将内存成本从线性 \(O(n)\) 降到了亚线性 \(O(\sqrt{n})\)
  • 作为代价,整个训练过程大约需要额外进行一次完整的前向传播计算(因为每个分段都被重新计算了一次),使得训练时间增加了约 30%
    • 问题:30% 的计算时间怎么来的呢?
    • 回答:反向传播的时间复杂度大约是前向传播的 2~3 倍,折合计算以后大致能算出这个数字(增加了一次前向传播计算),详情见附录

工作原理二:\(O(\log n)\) 内存成本算法(理论极限)

  • 论文进一步展示,通过递归 (Recursion) 的方式,可以实现更低的内存成本
  • 我们可以把一个分段本身看作一个“超级操作符”
  • 对这个超级操作符内部的计算,作者同样可以再次应用分段和重计算的策略

关键推导:\(O(\log n)\) 的递推关系

  • 让 \(g(n)\) 表示训练一个 \(n\) 层网络所需的内存
  • 假设将这个网络分成 \(k+1\) 个子问题,每个子问题的规模是 \(n/(k+1)\)
  • 为了连接这些子问题,需要存储 \(k\) 个中间结果
  • 那么,\(g(n)\) 可以表示为递推公式:
    $$g(n) = k + g\left(\frac{n}{k+1}\right)$$
    • 这是一个典型的对数关系
    • \(k\) 是存储这 \(k\) 个结果的成本
    • \(g\left(\frac{n}{k+1}\right)\) 是解决其中一个子问题所需的成本
    • 注:这里使用 \(k+1\) 或 \(k\) 不影响最终结果
  • 通过解这个递推公式,我们可以得到:
    $$g(n) = k \cdot \log_{k+1}(n)$$
  • 作为一个特例,如果每次只将问题一分为二,即只存储一个中间结果(\(k=1\)),那么递推关系变为 \(g(n) = 1 + g(n/2)\),解得:
    $$g(n) = \log_2(n)$$
    • 注:简单理解一下,展开 \(g(n)\) 后,大致共有 \(\log_2(n)\) 个 1
  • 这揭示了一个终极的理论可能性:
    • 训练一个 \(n\) 层网络的内存成本可以降低到 \(O(\log n)\)
    • 不过,这种方法的计算开销会大得多(需要 \(O(\log n)\) 次额外的前向传播,因此在实践中不如 \(O(\sqrt{n})\) 策略常用

实验效果与结论

  • 作者通过在深度残差网络 (ResNet) 和长短期记忆网络 (LSTM) 上的实验,验证了该方法的有效性
    • 对于一个 1000层 的 ResNet,标准优化方法需要 48GB 显存,而使用亚线性算法后仅需 7GB
    • 在 LSTM 上,该方法同样带来了 超过4倍 的内存节省
    • 代价是训练速度降低了大约30%,这对于能够训练原本无法训练的模型来说,是一个非常值得的交换

Transformer 中的梯度检查点

  • Transformer中的梯度检查点(Gradient Checkpointing)与上述论文中的基本原理上是完全相同的 ,但其应用方式和带来的收益上,针对Transformer 的结构有更多特点
  • 无论是用于CNN、RNN还是Transformer,梯度检查点的核心思想始终是:
    • 目标 :打破模型训练时内存消耗与网络深度(层数)之间的线性关系
    • 方法 :在前向传播时,不再保存所有中间层的激活值,而是只保存少数几个关键节点(检查点)
    • 代价 :在反向传播时,当需要用到被丢弃的激活值时,就从最近的一个检查点开始,重新进行一小段前向计算来恢复它们
    • 权衡 :本质上都是“用计算换内存”的策略

针对 Transformer 结构的应用说明

  • Transformer的独特结构使得梯度检查点的应用非常直接,且效果尤其显著
  • 1. 应用位置非常明确
    • 一个标准的 Transformer 模型是由一个个完全相同的 Transformer Block 堆叠而成的
      • 每个块通常包含一个多头自注意力(Multi-Head Self-Attention)层和一个前馈神经网络(Feed-Forward Network, FFN)层
    • 最自然、最常见的应用方式就是 将每一个Transformer块作为一个分段(Segment)
      • 前向传播时 :
        • 当数据流经第 \(i\) 个Transformer块时,只保留送入这个块的输入(也就是第 \(i-1\) 块的输出)
        • 在块内部计算过程中产生的所有中间结果,例如注意力分数矩阵(Attention Scores)、注意力权重(Attention Weights)、FFN层的中间激活等,计算完毕后立即被丢弃
      • 反向传播时 :
        • 当反向传播回第 \(i\) 个块时,算法会利用之前保存的输入,重新执行一次该块的前向计算,从而得到计算梯度所必需的那些中间结果
  • 2. 带来的收益为何对 Transformer 尤其显著
    • 梯度检查点能极大缓解Transformer在两个维度上的内存压力:
    • 深度(层数 \(L\)) :
      • 现代的大型语言模型(如GPT、LLaMA)可以有几十甚至上百层
      • 如果没有梯度检查点,内存消耗会随着层数 \(L\) 线性暴增。梯度检查点将这个成本从 \(O(L)\) 降到了 \(O(\sqrt{L})\) ,使得训练极深的Transformer 成为可能
    • 序列长度(Sequence Length \(S\)) :这是Transformer最独特的内存瓶颈
      • 注意力矩阵的二次方开销 :
        • 自注意力机制的核心是计算一个注意力分数矩阵,其大小为 (序列长度 x 序列长度)
        • 这意味着内存开销与序列长度成二次方关系 ,即 \(O(S^2)\)
        • 当序列很长时(例如4096、8192甚至更长),这个矩阵会变得异常巨大
      • 梯度检查点的作用 :
        • 梯度检查点不能改变单次注意力计算需要 \(O(S^2)\) 内存峰值的事实
        • 但它能确保不必同时在内存中保留每一层的这个巨大矩阵
        • 在没有检查点的情况下,内存中需要为 \(L\) 个注意力矩阵的激活值(或其相关值)分配空间
        • 有了检查点,在任何时候,只需要为当前正在重计算的那一个块的注意力矩阵分配内存
        • 这极大地降低了总体的内存占用

附录:梯度检查点技术增加了多少训练成本?

  • 论文中 “训练时间增加了约30%” 这个数字主要是一个经验性的测量结果 ,来源于作者在特定硬件上进行的基准测试,并且这个结果也与理论上的计算开销分析相符

实验测量结果(经验来源)

  • 作者在论文的第5.4节 (Impact on Training Speed) 和 图7 专门讨论了这个问题
    • 测试方法 :
      • 作者在单个 Titan X GPU 上对不同的内存分配策略进行了速度基准测试
      • 测量了在 ResNet 和 LSTM 两种模型上,处理一个批次(batch)数据所需的实际运行时间(秒)
    • 对比对象 :
      • 比较了采用标准内存优化(论文中称为 “sharing”)的策略和采用亚线性内存成本(”sublinear plan”)策略的速度
    • 测量结论 :
      • 实验结果图表(图7)直观地显示,”sublinear plan” 的时间成本曲线始终在 “sharing” 曲线之上
      • 论文在图7的说明文字和正文中明确指出,使用亚线性内存方案会带来“大约30%的额外运行时成本”

理论计算分析(理论支撑)

  • 训练一个批次的主要计算量如下:
    • 标准训练流程 :包含一次完整的前向传播(Forward Pass)和一次完整的反向传播(Backward Pass):
      $$ 总计算量 \approx 1F + 1B $$
    • 亚线性方案的流程 :它在反向传播过程中需要重新计算前向传播,因此:
      $$ 总计算量 \approx 1F + (1F_recompute + 1B) = 2F + 1B $$
  • 论文中提到,通常一次反向传播的计算量大约是前向传播的两倍(\(B \approx 2F\))
    • 实际上是大约 2~3 倍的样子
  • 基于上述这个假设,我们可以估算增加的计算开销:
    • 标准流程计算量 :
      $$T_{standard} = T_F + T_B \approx T_F + 2T_F = 3T_F$$
    • 亚线性方案计算量 :
      $$T_{sublinear} = 2T_F + T_B \approx 2T_F + 2T_F = 4T_F$$
  • 增加的运行时间百分比约为:
    $$\frac{T_{sublinear} - T_{standard}}{T_{standard}} = \frac{4T_F - 3T_F}{3T_F} = \frac{1T_F}{3T_F} = \frac{1}{3} \approx 33.3%$$
  • 这个理论计算出的 33.3% 与实验中测量到的 约30% 基本吻合(考虑到反向传播大致是前向传播的 2~3 倍,那就基本符合了)

KG——知识图谱的描述

参考博客: https://blog.csdn.net/u011801161/article/details/78833958


RDF

  • Resource Description Framework
  • 资源描述框架
  • 本质是一个数据模型
  • 提供了统一的描述实体和资源的标准
  • 形式上表现为主谓宾(SPO, Subject-Predication-Object)三元组, 也称为一条语句(Statement), 知识图谱中称为一条知识

RDF的序列化方法

参考博客: https://blog.csdn.net/u011801161/article/details/78833958

  • RDF/XML: 用XML格式来表示RDF数据

  • N-Triples: 用多个三元组来表示RDF数据集合,是最直观的表示方法,每一行表示一个三元组,方便机器解析和处理,DBpedia 是按照这个方式来发布数据的

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <http://www.kg.com/person/1> <http://www.kg.com/ontology/chineseName> "罗纳尔多·路易斯·纳萨里奥·德·利马"^^string.
    <http://www.kg.com/person/1> <http://www.kg.com/ontology/career> "足球运动员"^^string.
    <http://www.kg.com/person/1> <http://www.kg.com/ontology/fullName> "Ronaldo Luís Nazário de Lima"^^string.
    <http://www.kg.com/person/1> <http://www.kg.com/ontology/birthDate> "1976-09-18"^^date.
    <http://www.kg.com/person/1> <http://www.kg.com/ontology/height> "180"^^int.
    <http://www.kg.com/person/1> <http://www.kg.com/ontology/weight> "98"^^int.
    <http://www.kg.com/person/1> <http://www.kg.com/ontology/nationality> "巴西"^^string.
    <http://www.kg.com/person/1> <http://www.kg.com/ontology/hasBirthPlace> <http://www.kg.com/place/10086>.
    <http://www.kg.com/place/10086> <http://www.kg.com/ontology/address> "里约热内卢"^^string.
    <http://www.kg.com/place/10086> <http://www.kg.com/ontology/coordinate> "-22.908333, -43.196389"^^string.
  • RDFa: (The Resource Description Framework in Attributes)

  • Turtle是最常用的RDF序列化方式, 比RDF/XML更紧凑, 可读性比N-Triples更好

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    Example2 Turtle:

    @prefix person: <http://www.kg.com/person/> .
    @prefix place: <http://www.kg.com/place/> .
    @prefix : <http://www.kg.com/ontology/> .

    person:1 :chineseName "罗纳尔多·路易斯·纳萨里奥·德·利马"^^string.
    person:1 :career "足球运动员"^^string.
    person:1 :fullName "Ronaldo Luís Nazário de Lima"^^string.
    person:1 :birthDate "1976-09-18"^^date.
    person:1 :height "180"^^int.
    person:1 :weight "98"^^int.
    person:1 :nationality "巴西"^^string.
    person:1 :hasBirthPlace place:10086.
    place:10086 :address "里约热内卢"^^string.
    place:10086 :address "-22.908333, -43.196389"^^string.
    • 同一个实体拥有多个属性(数据属性)或关系(对象属性),我们可以只用一个subject来表示,使其更紧凑。我们可以将上面的Turtle改为
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      Example3 Turtle:

      @prefix person: <http://www.kg.com/person/> .
      @prefix place: <http://www.kg.com/place/> .
      @prefix : <http://www.kg.com/ontology/> .

      person:1 :chineseName "罗纳尔多·路易斯·纳萨里奥·德·利马"^^string;
      :career "足球运动员"^^string;
      :fullName "Ronaldo Luís Nazário de Lima"^^string;
      :birthDate "1976-09-18"^^date;
      :height "180"^^int;
      :weight "98"^^int;
      :nationality "巴西"^^string;
      :hasBirthPlace place:10086.
      place:10086 :address "里约热内卢"^^string;
      :address "-22.908333, -43.196389"^^string.
  • JSON-LD: 即“JSON for Linking Data”,用键值对的方式来存储RDF数据

    1
    2
    3
    4
    5
    6
    7
    {
    "@context": "https://json-ld.org/contexts/person.jsonld",
    "@id": "http://dbpedia.org/resource/John_Lennon",
    "name": "John Lennon",
    "born": "1940-10-09",
    "spouse": "http://dbpedia.org/resource/Cynthia_Lennon"
    }

RDF的缺点

  • 表达能力有限
    • 无法区分雷和对象
    • 无法定义和描述类的关系/属性

RDFS/OWL

  • 是RDF的一种扩展
  • 是用来描述RDF数据的
  • 本质上是一些预定义词汇(Vocabulary)构成的集合
  • 用于对RDF进行类似的类定义以及属性的定义

RDFS/OWL的序列化方法

  • RDFS/OWL序列化方式和RDF没什么不同,其实在表现形式上,它们就是RDF
  • 常用的方式主要是RDF/XML,Turtle

RDFS

  • Resource Description Framework Schema
  • 是RDF的一种扩展
  • RDFS几个比较重要,常用的词汇:
    • rdfs:Class. 用于定义类。
    • rdfs:domain. 用于表示该属性属于哪个类别。
    • rdfs:range. 用于描述该属性的取值类型。
    • rdfs:subClassOf. 用于描述该类的父类。比如,我们可以定义一个运动员类,声明该类是人的子类。
    • rdfs:subProperty. 用于描述该属性的父属性。比如,我们可以定义一个名称属性,声明中文名称和全名是名称的子类
    • 其实rdf:Property和rdf:type也是RDFS的词汇,因为RDFS本质上就是RDF词汇的一个扩展。我们在这里不罗列进去,是不希望读者混淆, 更多RDFS词汇的用法参考W3C官方文档
  • 举例
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
    @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
    @prefix : <http://www.kg.com/ontology/> .

    ### 这里我们用词汇rdfs:Class定义了“人”和“地点”这两个类
    :Person rdf:type rdfs:Class.
    :Place rdf:type rdfs:Class.

    ### rdfs当中不区分数据属性和对象属性,词汇rdf:Property定义了属性,即RDF的“边”
    :chineseName rdf:type rdf:Property;
    rdfs:domain :Person;
    rdfs:range xsd:string .

    :career rdf:type rdf:Property;
    rdfs:domain :Person;
    rdfs:range xsd:string .

    :fullName rdf:type rdf:Property;
    rdfs:domain :Person;
    rdfs:range xsd:string .

    :birthDate rdf:type rdf:Property;
    rdfs:domain :Person;
    rdfs:range xsd:date .

    :height rdf:type rdf:Property;
    rdfs:domain :Person;
    rdfs:range xsd:int .

    :weight rdf:type rdf:Property;
    rdfs:domain :Person;
    rdfs:range xsd:int .

    :nationality rdf:type rdf:Property;
    rdfs:domain :Person;
    rdfs:range xsd:string .

    :hasBirthPlace rdf:type rdf:Property;
    rdfs:domain :Person;
    rdfs:range :Place .

    :address rdf:type rdf:Property;
    rdfs:domain :Place;
    rdfs:range xsd:string .

    :coordinate rdf:type rdf:Property;
    rdfs:domain :Place;
    rdfs:range xsd:string .

OWL

  • Web Ontology Language

  • 是对RDFS的一个扩展,添加了额外的预定义词汇

  • 提供快速,灵活的数据建模能力

  • 高效的自动推理能力

  • 描述属性特征的词汇

    • owl:TransitiveProperty. 表示该属性具有传递性质。例如,我们定义“位于”是具有传递性的属性,若A位于B,B位于C,那么A肯定位于C。
    • owl:SymmetricProperty. 表示该属性具有对称性。例如,我们定义“认识”是具有对称性的属性,若A认识B,那么B肯定认识A。
    • owl:FunctionalProperty. 表示该属性取值的唯一性。 例如,我们定义“母亲”是具有唯一性的属性,若A的母亲是B,在其他地方我们得知A的母亲是C,那么B和C指的是同一个人。
    • owl:inverseOf. 定义某个属性的相反关系。例如,定义“父母”的相反关系是“子女”,若A是B的父母,那么B肯定是A的子女
  • 本体映射词汇(Ontology Mapping)

    • owl:equivalentClass. 表示某个类和另一个类是相同的。
    • owl:equivalentProperty. 表示某个属性和另一个属性是相同的。
    • owl:sameAs. 表示两个实体是同一个实体
  • 举例

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
    @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
    @prefix : <http://www.kg.com/ontology/> .
    @prefix owl: <http://www.w3.org/2002/07/owl#> .

    ### 这里我们用词汇owl:Class定义了“人”和“地点”这两个类
    :Person rdf:type owl:Class.
    :Place rdf:type owl:Class.

    ### owl区分数据属性和对象属性(对象属性表示实体和实体之间的关系)。词汇owl:DatatypeProperty定义了数据属性,owl:ObjectProperty定义了对象属性
    :chineseName rdf:type owl:DatatypeProperty;
    rdfs:domain :Person;
    rdfs:range xsd:string .

    :career rdf:type owl:DatatypeProperty;
    rdfs:domain :Person;
    rdfs:range xsd:string .

    :fullName rdf:type owl:DatatypeProperty;
    rdfs:domain :Person;
    rdfs:range xsd:string .

    :birthDate rdf:type owl:DatatypeProperty;
    rdfs:domain :Person;
    rdfs:range xsd:date .

    :height rdf:type owl:DatatypeProperty;
    rdfs:domain :Person;
    rdfs:range xsd:int .

    :weight rdf:type owl:DatatypeProperty;
    rdfs:domain :Person;
    rdfs:range xsd:int .

    :nationality rdf:type owl:DatatypeProperty;
    rdfs:domain :Person;
    rdfs:range xsd:string .

    :hasBirthPlace rdf:type owl:ObjectProperty;
    rdfs:domain :Person;
    rdfs:range :Place .

    :address rdf:type owl:DatatypeProperty;
    rdfs:domain :Place;
    rdfs:range xsd:string .

    :coordinate rdf:type owl:DatatypeProperty;
    rdfs:domain :Place;
    rdfs:range xsd:string .
  • 举个例子体现对两个不同知识图谱的融合

    1
    2
    3
    http://www.zhangsan.com/ontology/Person rdf:type owl:Class . 
    http://www.lisi.com/ontology/Human rdf:type owl:Class .
    http://www.zhangsan.com/ontology/Person owl:equivalentClass http://www.lisi.com/ontology/Human .

Python——跨文件类中isinstance函数困境


不同文件为入口文件时

  • 文件一(fruit.py):

    1
    2
    3
    4
    5
    6
    7
    # file: fruit.py
    class Apple:
    def __init__(self):
    name = "HongFuShi"

    apple = Apple()
    print apple.__class__
  • 文件二(run.py):

    1
    2
    # file: run.py
    import fruit
  • 考虑一个文件名为 fruit.py 的文件夹中定义了一个类Apple,同时初始化一个对象apple

    • 若执行 python fruit.py:
      • 输出 “main.Apple”
    • 若将当前文件导入到另一个文件 run.py 中,然后执行python run.py:
      • 输出 “fruit.Apple”
    • 也就是说,执行不同文件,类 Apple 的前缀不同

跨文件类中isinstance函数的困境

  • 困境说明:isinstance的困境:看起来是同一个类,但执行isinstance后返回False

  • 文件一(fruit.py):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    # file: fruit.py
    class Apple(object):
    pass

    if __name__ == "__main__":
    from getapple import get_apple # 注意,这里 import 必须放到 "__main__" 中,不能放到外面,否则会发生文件的递归依赖,出现初始化错误
    apple1 = Apple()
    print apple1.__class__ # <class '__main__.Apple'>
    apple2 = get_apple()
    print apple2.__class__ # <class 'fruit.Apple'>
    print isinstance(apple2, Apple) # False
  • 文件二(getapple.py):

    1
    2
    3
    4
    5
    6
    7
    # file: getapple.py
    from fruit import Apple

    def get_apple():
    apple = Apple()
    print apple.__class__ # <class 'fruit.Apple'>
    return apple
  • 此时执行 python getapple.py,无任何输出(符合预期,因为这里 getapple.py 只是用于定义函数)

  • 若执行 python fruit.py,则输出如下:

    1
    2
    3
    4
    <class '__main__.Apple'>
    <class 'fruit.Apple'>
    <class 'fruit.Apple'>
    False
    • 此时 fruit.py 是程序的入口文件
    • 在入口文件中执行 apple1 = Apple() 后得到的类将是 __main__.Apple
    • 在入口文件被导入到 getapple.py 文件中后,执行 apple2 = Apple() 后得到的类将是 fruit.Apple
    • 此时,由于下面的原因造成 isinstance(apple2, Apple) 返回 False
      • apple2 的类别是 fruit.Apple(在 getapple.py 中定义的)
      • Apple 是 __main__.Apple(在 fruit.py 中定义的)
  • isinstance的困境总结:看起来是同一个类,但执行isinstance后返回False

Python——数字范围边界等问题

C++中不同类型的数字有自己不同的边界和范围,Python中呢?如何判断边界问题?


最大最小整数

C++

1
2
int minInt = 0x80000000;
int maxInt = 0xffffffff

Python

1
2
minInt = -0xffffffff
maxInt = 0xffffffff
  • Python中int大小为24个字节,数字太大时不会越界,会变为long类型,long类型的字节占位可以非常大(24以下为int,之后为long,分别可以为36,44,52,60等,每次8位递加?),不会越界

    • 测试:当一个数字太大时,使用int(a)强制字符转换也不能将数字转换为int类型,将一直为long类型
    • 测试: Python中24个字节存储一个int类型对象,但是并不是所有空间都存值,只有一部分用来存储数值
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      MinInt = int(0x80000000000000000)
      print MinInt
      import sys
      print sys.getsizeof(MinInt)
      print type(int(MinInt))

      # output:
      147573952589676412928
      36
      <type 'long'>
  • Python中定义最小负数时可以使用float最小值或者是很大的整数的负数,而不是像C++一样


最大最小浮点数

Python

1
2
minFloat = float("-inf")
maxFloat = float("inf")

ML——主成分分析-PCA


与TSVD的对比

  • 关于SVD的进一步了解可参考Math——奇异值分解-SVD
  • PCA与TSVD目标不同
  • TSVD奇异值与PCA分解得到的对角矩阵元素意义不同
    • PCA得到矩阵对角元素的是该维度的方差
    • TSVD得到的是某种重要的隐形意义(注意,不是方差)
  • PCA等价于下面两个步骤:
    • 对数据X中心化
    • 对数据做TSVD分解

与ICA的对比

  • ICA得到的变量满足独立性
  • PCA得到的变量满足不相关性
  • 独立与不相关的关系
    • 变量独立 \(=>\) 变量不相关
    • 变量不相关 \(\neq>\) 变量独立
    • 当变量是正态分布时:变量独立 \(<=>\) 变量不相关

Tips——一些有用的tips总结

本文对一些程序员日常可能用到的小 tips 进行总结和记录


海量字符串的合并

问题描述

  • 将大量的(现实遇到的是 18W+ 级别的句子,句子长度平均在 100 个字符以上)字符串需要合并为一个字符串

  • 如果直接迭代并使用下面的语句合并,花费很多时间,随着字符串的增大,合并速度越来越慢

    1
    2
    all_texts += " %s" % text
    all_texts = "%s %s" % (all_text, text)
  • 现实生活中发现到了 5000 个字符串以上时速度变得极慢

解决方案

  • 分批次合并:将词语分批次分别合并为一个比较小的,最后再合并到一起
  • 实际中我按照 2000 个句子一份合并完成,再最终合并,速度提升了非常多

Emoji 搜索网址

  • Emoji 大全:www.unicode.org/emoji
1…394041…63
Joe Zhou

Joe Zhou

Stay Hungry. Stay Foolish.

630 posts
53 tags
GitHub E-Mail
© 2026 Joe Zhou
Powered by Hexo
|
Theme — NexT.Gemini v5.1.4