跳转到内容

(5)AIGC组成原理(上)

作者:小A,aaronxic,知乎个人主页

发表时间:2023年7月8日

原文地址:https://zhuanlan.zhihu.com/p/646149258

开篇

大家好,我是aaronxic。前面几篇我们已经感受了transformer是如何应用在LLM和多模态领域的,从这一篇开始我们把目光转向AIGC,看看AIGC任务都是由哪些部件组装而成的。

AIGC (Artificial Intelligence Generative Content)即人工智能生成内容,这里强调的是GC部分,也就是decoder部分。

  • 上一篇 (4)多模态的大一统之路 侧重的是encoder部分,包括对Image和Video的编码。对decoder的生成主要聚焦在生成text生成上
  • 本篇《AIGC组成原理(上)》将介绍常见的4大类生成算法,包括了VAE、GAN、FlowModel和Diffusion Model。同时,还会介绍IS(Inception Score)和FID(Frechet Inception Distance)两种生成图片常见评价指标。
  • 下一篇《AIGC组成原理(下)》将介绍具体的Image生成、Video生成、Audio生成和3D生成算法

PS: 长文预警,本篇约12000字,关注&收藏后电脑上阅读体验更加哦~ (^_^)

提纲如下,共2个章节

  • 首先介绍了生成模型的本质目的,就是为了建模p(x) 分布。
    • 首先是最朴素的极大似然估计,虽然简单,但是要求有明确的参数化分布形式,在实际中往往不可得
    • 接着介绍4种隐变量模型,包括VAE,GAN,Flow Model和Diffusion Model。本质上用p(x)=\int p(x|z) p(z) \text{d}z 来近似
    • VAE模型。尝试提高p(z) 采样效率,尝试最小化\text{KL}(q_\theta(z|x)||p(z)) ,最终得到了正则项和重建误差项
    • GAN模型。尝试对MSE的损失函数做进一步拓展,引入判别模型D(x', x) 来隐式学习度量方法
    • Flow Model模型。强行让f 函数可逆,满足x z 的一一映射,以RevNet为例子介绍Flow Model具体使用方式
    • Diffusion Model (DDPM)。将VAE扩展到了多步,有复杂的数学推导,但是本质上跟VAE是相似的
    • DDPM的score function。换一种角度理解DDPM,发现可以用网络s\theta(x_t, t) s\theta(x_t, t) 来预测\nabla{x_t}\log p(x_t)
    • DDIM。尝试对DDPM做采样加速,将DDPM变成了确定性的过程
    • classifier-guided。使用classifier-guided技术,首次把DDPM和DDIM的IS和FID指标拉高到GAN齐平。在推理阶段,DDPM可以直接分析p(x_t|x_{t+1}, y) ;而对于DDIM,由于是个确定性过程,因此退化成分析p(x_t|y)
    • classifier-free。为了省去classifier-guided的梯度计算过程,classifier-free在训练中混合训练有condition和无condition的模型,使得在推理阶段无需求解梯度,在提高保真度的同时计算效率也很高
  • 接着介绍了图片生成常见的两种指标
    • IS(Inception Score)指标提供了两种理解角度。IS本身有很强的先验,认为符合ImageNet的分布才是真实分布
    • FID(Frechet Inception Distance) 指标,衡量两个数据集的距离,更科学一点

从生成模型谈起

假设我们有一批大小为N 的真实图片数据集合,S_x={x_1, x_2, \cdots, x_N}

  • 如果有一个完美的分布 p(x) 能生成集合S_x 中的元素,就意味着要求每次采样出来的x' \sim p(x) 都满足x' \in S_x
  • 当集合元素N 比较小的时候,p(x) 可以强行背下来即可;但是当N 变得非常大的时候,完美分布p(x) 就几乎不可能获取了。

而AIGC的任务就是逼近这个完美分布p(x) ,这里的x 可以是Image,可以是Video,可以是Audio或者3D模型

那具体如何逼近这个完美分布p(x) 呢?各类方法各显神通,下面我们就来逐个来看

极大似然估计

估计分布 p(x) 有个最直接的方法,就是极大似然估计。先假设 p(x) 的形式为 p_\theta(x) ,然后待定其中的参数 \theta 。例如我们假设$x$来自多元高斯分布 \mathcal{N}(\mu, \Sigma) ,即 x \sim \mathcal{N}(\mu, \Sigma) ,其中高斯分布的维度和图片的像素个数一致。于是这里的待定参数就是 \theta=(\mu, \Sigma) ,此时似然估计函数为

L_\theta(S_x)=p(S_x;\theta)=\prod_{i=1}^N p(x_i;\theta)

做最大似然估计,用梯度下降或者公式推导求解出最佳参数 \hat{\theta}

(\hat{\mu}, \hat{\Sigma})=\hat{\theta}=\argmax_\theta L_\theta(S_x)=\argmin_\theta(-\sum_{i=1}^N \ln p(x_i;\theta))

这样就求得了 p(x) 的分布为 \mathcal{N}(\hat{\mu}, \hat{\Sigma})

上述方法简单直观,但是弊端也很明显:

  • p(x) 形式未知。需要丰富的领域知识才能笃定 p(x) 就是某个形式,其实对于复杂问题来说只有上帝才知道分布的参数化表达式是啥
  • 参数量 \theta 的空间太大。多元高斯分布的维度跟图片像素数一样大,例如ImageNet是 \mathbb{R}^{3 \times 224 \times 224} 维度,那么意味着是150528元高斯分布,那得需要多少海量的数据才能估计得准确呀

隐变量估计

为了解决上述两个问题,更加广泛使用的方式是隐变量估计法,目前生成模型主流的4大类方法本质上都是生成模型,如下所示。原图出处

在介绍上述4种方法之前,我们先深入了解一下隐变量模型是什么。

隐变量模型顾名思义,就是引入隐变量 z ,期望从简单的分布 p(z) 出发,用积分公式来间接求出复杂的 p(x)

p(x)=\int p(x|z) p(z) \text{d}z

这里值得注意的是

  • 简单满足两个性质。
    • p(z) 分布表达式简单,例如是普通的多元高斯分布
    • z 自由度低,例如对于多元高斯分布,维度为 d ,其中 d \ll 3 \times 224 \times 224
  • p(x|z) 可以是个确定性的过程 p_\theta(x|z) ,即 x=f(z) f 用神经网络来表示
  • 有了万能拟合函数 f ,那么从简单分布 p(z) 生成任意分布 p(x) 过程为
    • Step1: 假设想得到 p(x=x') 的概率,那么就先研究 f 找到所有 z 使得 x'=f(z)
    • Step2: 假设 z 的解集合为 {z_1, z_2, \cdots, z_M} ,则把这些 z 出现的概率全部加起来就是 x' 出现的概率,即可以得到 p(x=x')=\sum_{i=1}^Mp(z=z_i)

但是要找到Step2里面 z 的解集合是很难的,所以虽然 p(z) 很简单, f 是个确定过程,但由于 f 不一定可逆, p(x) 仍然很难直接算出表达式。

我们能做的是数值模拟的方式采样出 x' \sim p(x) ,常用的为蒙特卡洛方法

  • 首先依 p(z) 的分布采样 K z ,得到数组 T_z=[z_1, z_2, \cdots, z_K] ,其中 z_i \sim p(z)
  • 根据 x=f(z) 计算得到数组 T_x=[x_1, x_2, \cdots, x_K]
  • 注意如果 p(z_i) 概率更高,那么 z_i 出现在 T_z 的次数会越多,相应的 x_i 出现在 T_x 的概率就会高
  • 只需要简单对 T_x 取均值即可得到本次采样最终的 x'=\frac{1}{K}\sum_{i=1}^Kx_i

蒙特卡洛方法虽然简单,但是也有2个可改进方向

  • 提高采样效率。这里的 K 可能需要非常大才能得到对应满意的结果,也就是生成一个 x' 需要很多次 z 的采样。因此一种思路是提高 z 的采样效率,最好采样一次就能完成任务 (VAE方向)
  • 损失误差不用均方误差MSE。在实际网络训练中,上述蒙特卡洛采样过程,每次得到的 x' 会启发式地和真实图片 x 做MSE。但没有证据表明MSE就是最优度量,因此另外一种思路是用神经网络 D(x, x') 来隐式学这个度量方式 (GAN方向)

VAE

观察隐变量的积分式

p(x)=\int p(x|z) p(z) \text{d}z

如何提高 z 的采样效率呢?一种思路是用 p(z|x) 来估计 p(z) ,原因是有了 x 的信息, z 怎么着都应该变得确定一点吧。这里研究的变量是 z ,因此 p(z) 是先验分布, p(z|x) 是后验分布。

但即便如此,无中生有出 p(z|x) 会陷入鸡生蛋和蛋生鸡的窘境,我们需要一个具体可优化模型来逼近 p(z|x) ,于是引入新的概率分布 q_\theta(z|x) 。思路逐渐清晰了

  • Step1:先想办法构造一个新的分布 q\theta(z|x) q\theta(z|x) ,使得 z' \sim q\theta(z|x) z' \sim q\theta(z|x)
  • Step2:然后不断优化 q_\theta(z|x) 靠近 p(z|x) ,使得最终近似满足 z'\sim p(z|x)

引入的 q\theta(z|x) q\theta(z|x) 是一系列的分布家族,并且需要在里面做优化,选择最合适的 q{\theta^*}(z|x) q{\theta^*}(z|x) 分布,这个过程就是变分。

下面我们用KL衡量一下这两个分布的差距

\begin{align} \text{KL}(q_\theta(z|x) ||p(z|x)) &= \int q_\theta(z|x)\ln \frac{q_\theta(z|x)}{p(z|x)} \text{d}z \\ &= \mathbb{E}_{z\sim q_\theta(z|x)}[\ln q_\theta(z|x) - \ln p(z|x)]\\ &= \mathbb{E}_{z\sim q_\theta(z|x)}[\ln q_\theta(z|x) - \ln \frac{p(x|z)p(z)}{p(x)}]\\ &= \mathbb{E}_{z\sim q_\theta(z|x)}[\ln q_\theta(z|x) - \ln p(x|z) - \ln p(z) + \ln p(x)]\\ &=\text{KL}(q_\theta(z|x)||p(z))-\mathbb{E}_{z\sim q_\theta(z|x)}\ln p(x|z) + \ln p(x) \end{align}

可以看到,通过变分我们绕过了虚无缥缈的 p(z|x) ,留下的3项都是可以分析的对象。

下面我们逐项分析:

  • 明确目标是希望左侧的KL距离越来越小,并且要重点关注 q_\theta(z|x) 要怎么变才能逼近 p(z|x)
  • 右边第一项 \text{KL}(q_\theta(z|x)||p(z)) ,希望尽可能小,也就是新引入的采样过程得到的 z' 不能离原来的标准多元高斯分布假设 p(z) 太远。我们是希望 z' 的方差变小,而不是完全变个样。这个不就是正则项要尽可能小嘛
  • 右边第二项 -\mathbb{E}{z\sim q\theta(z|x)}\ln p(x|z) -\mathbb{E}{z\sim q\theta(z|x)}\ln p(x|z) -\mathbb{E}{z\sim q\theta(z|x)}\ln p(x|z) ,希望尽可能小,也就是 \mathbb{E}{z\sim q\theta(z|x)}\ln p(x|z) \mathbb{E}{z\sim q\theta(z|x)}\ln p(x|z) \mathbb{E}{z\sim q\theta(z|x)}\ln p(x|z) 要尽可能大,含义就是每张图的似然 \ln p(x|z) 在所有 z 采样中要尽可能解释观测数据 $x$,这个不就是重建误差要尽可能小嘛
  • 右边第三项 \ln p(x) ,是个跟 q\theta(z|x) q\theta(z|x) 没啥关系的常数,不随 q\theta(z|x) q\theta(z|x) 变化而变化,忽略

上式也常常写成如下形式

\begin{align} \ln p(x) &= \text{KL}(q_\theta(z|x) ||p(z|x)) -\text{KL}(q_\theta(z|x)||p(z)) + \mathbb{E}_{z\sim q_\theta(z|x)}\ln p(x|z)\\ &\ge -\text{KL}(q_\theta(z|x)||p(z)) + \mathbb{E}_{z\sim q_\theta(z|x)}\ln p(x|z) \\ &= \text{Variational Lower Bound} \end{align}

要最大化$p(x)$,只需要不断提高VLB(Variational Lower Bound)即可,即最大化VLB

由上我们知道了第一项就是正则项,第二项就是重建误差,整个VAE的网络呼之欲出,魔改苏老师的图,如下所示

  • q_\theta(z|x) 过程是采样过程。而神经网络g是个确定性过程,本身没有随机性,因此为了让网络参数可学习,需要引入重参数化技巧。拿图中各分量独立的多元高斯变量举例
    • g过程直接预测每个维度的均值 \mu_i 和方差 \sigma_i ,然后叠加随机数发生器 \epsilon_i \sim \mathcal{N}(0, 1) ,得到采样结果 z'_i = \sigma_i \cdot \epsilon_i+ \mu_i
    • 每个维度 i 都操作完之后得到 z'=[z'1, z'2, \cdots, z'_d] z'=[z'1, z'2, \cdots, z'_d] z'=[z'1, z'2, \cdots, z'_d]
    • 所有 \mu_i 组成 \mu ,所有 \sigma_i 组成 \Sigma ,则 z' \sim \mathcal{N}(\mu, \Sigma)
  • p_\theta(x|z) 过程是个确定性过程,当 z' 被采样出来之后,直接调用decoder网络就能得到重建的 \hat{X}

对VAE网络有了认识,我们再回到VAE网络的loss上来,包含两项:

  • 最小化正则项。从 \text{KL}(q\theta(z|x)||p(z)) \text{KL}(q\theta(z|x)||p(z)) 转为 \text{KL}(\mathcal{N}(\mu,\Sigma)||\mathcal{N}(0, I)) ,有闭式解,即最小化 \sum{j=1}^d\frac{1}{2}(-\ln \sigma_j^2 + \sigma_j^2 + \mu_j^2 -1) \sum{j=1}^d\frac{1}{2}(-\ln \sigma_j^2 + \sigma_j^2 + \mu_j^2 -1)
  • 最小化重建误差项。 \mathbb{E}{z\sim q\theta(z|x)}\ln p(x|z) \mathbb{E}{z\sim q\theta(z|x)}\ln p(x|z) \mathbb{E}{z\sim q\theta(z|x)}\ln p(x|z) 可以转换为要求 x_i \hat{x}i \hat{x}i 的MSE的值尽可能小,即最小化 \sum{i=1}^N||x_i - \hat{x}^i||^2_2 \sum{i=1}^N||x_i - \hat{x}^i||^2_2

最终VAE网络的loss如下

\sum_{i=1}^N (\frac{1}{2}\sum_{j=1}^d(\sigma_{i,j}^2 +\ln \frac{1}{\sigma_{i,j}^2} + \mu_{i,j}^2 -1) + ||x_i - \hat{x}^i||^2_2)

模型收敛之后

  • 把encoder网络丢弃
  • 每次按标准多元高斯分布采样$z$,然后经过decoder网络输出 \hat{x} ,完成一次采样

GAN

让我们重新回到梦开始的地方,再看看隐变量模型

p(x)=\int p(x|z) p(z) \text{d}z

前面说到VAE的思路是提高 p(z) 采样效率,参数化后验分布 q\theta(z|x) q\theta(z|x) ,引入数据依赖直接得到均值 \mu 和方差 \Sigma ,使得 q\theta(z|x)=\mathcal{N}(\mu, \Sigma) q\theta(z|x)=\mathcal{N}(\mu, \Sigma)

而原始GAN的思路是保留 p(z) 是固定的标准多元高斯分布,额外引入新网络 D(x', x) 对生成的 x' 和真实的 x 做分类,而不是像VAE一样用固定的MSE损失函数

GAN的数学化表达如下,公式直观,但是背后蕴藏了非常多玄机,对GAN的性质和优化感兴趣的建议阅读这篇关于WGAN的文章

-\mathbb{E}_{x\sim P_r}[\log D(x)]-\mathbb{E}_{x\sim P_g}[\log(1- D(x))]

Flow Model

我们接着介绍第三种生成模型Flow Model,还是从隐变量模型说

p(x)=\int p(x|z) p(z) \text{d}z

前面介绍了如何用神经网络 f 来表示 p_\theta(x|z) 来建立 z X 的关系,方法如下

  • Step1: 假设想得到 p(x=x') 的概率,那么就先研究 f 找到所有 z 使得 x'=f(z)
  • Step2: 假设 z 的解集合为 {z_1, z_2, \cdots, z_M} ,则把这些 z 出现的概率全部加起来就是 x' 出现的概率,即可以得到 p(x=x')=\sum_{i=1}^Mp(z=z_i)

但我们知道,想得到Step2里面 z 的解集合是很难的,所以虽然 p(z) 很简单, f 是个确定过程,但由于 f 不一定可逆, p(x) 仍然很难直接算出表达式。于是退而求其次,不求 p(x) 的表达式了,只求蒙特卡洛的方式能采样出 x' \sim p(x) 就好

但如果,我们就是想硬上求出表达式呢,其实也可以,只是需要满足

  • f 函数是可逆的,即知道了 x=f(z) ,那么容易推导出来 z =f^{-1}(x)
  • 因此 f 是一一映射的,同时 x z 要求是维度一样的,如果 x \in \mathbb{R}^{D} 那么 z \in \mathbb{R}^{D}
  • 既然 f 是一一映射的,也用不着积分了,直接变量替换 z=f^{-1}(x) \sim \mathcal{N}(0, I)

变量替换后概率密度如下

p(x)=\frac{1}{(2\pi)^{D/2}}\exp(-\frac{1}{2}||f^{-1}(x)||^2)\bigg |\det[\frac{\partial {f^{-1}}}{\partial x}]\bigg|

可见除了要求 f 可逆,还要求逆函数 f^{-1}(x) 的行列式计算也要简单

贯彻了flow model理念的代表作有RevNet (Reversible Network),可逆网络,如下所示

  • 输入是 x ,输出是 y
  • x 分成两部分 x_1 x_2 ,把 y 也分成两部分 y_1 y_2
  • 输入和输出tensor shape一样的函数 \mathcal{F} \mathcal{G}

那么可以计算前馈和反传

主要这个跟省显存的技术checkpointing不一样

  • checkpoint是通过更浅层的输入重计算当前层输入
  • RevNet是通过当前层的输出直接算出当前层的输入

有了当前层的输入,接着就可以正常求梯度了。完整的梯度回传公式如下

Diffusion Model (DDPM)

最后我们看看近几年爆红的以DDPM为代表的Diffusion Model,继续回到隐变量模型

p(x)=\int p(x|z) p(z) \text{d}z

回想VAE的思路是提高$p(z)$采样效率

  • encoder。用参数化的后验分布模型 q\theta(z|x) q\theta(z|x) ,直接预测均值 \mu 和方差 \Sigma ,使得 q\theta(z|x)=\mathcal{N}(\mu, \Sigma) q\theta(z|x)=\mathcal{N}(\mu, \Sigma)
  • decoder。采样得到 z 之后,经过参数化的 p_\theta(x|z) 生成最后的 \hat{x}

如果 q_\theta(z|x) 不是一步生成的,而是经过 T 步会怎么样呢,即encoder为

q_\theta(z|x)=q_\theta(z|x_{T-1})\cdot q_\theta(x_{T-1}|x_{T-2})\cdots q_\theta(x_{t}|x_{t-1}) \cdots q_\theta(x_2|x_1) \cdot q_\theta(x_1|x)

同理decoder可以变成

p_\theta(x|z)=p_\theta(x|x_1)\cdot p_\theta(x_1|x_2)\cdots p_\theta(x_{t-1}|x_t) \cdots p_\theta(x_{T-2}|x_{T-1})\cdot p_\theta(x_{T-1}|z)

如下所示,这个就是diffusion model的思想,但跟VAE也有很大不同

PS: 符号变换一下, x 变成了 x_0 z 变成了 x_T

  • 从右往左的encoder是无参数的 q(x_t|x_{t-1}) 。不像VAE是带超参数的,这是个人为定义的过程,从原始清晰图 x_0 开始,每次转换成新的高斯噪声,逐渐变成标准多元高斯变量 x_T
  • 从左往右的decoder是带参数的 p\theta(x{t-1}|x_t) p\theta(x{t-1}|x_t) p\theta(x{t-1}|x_t) 。不是像VAE一样直接预测 \hat{x} ,而是预测高斯噪声,并且会减去这个高斯噪声得到更清晰的图片
  • 另外中间隐变量 x_T 的维度变成了跟原始图片 x_0 一样大

encoder过程

首先定义递增的常量序列 \beta_t ,满足 0<\beta_1 \lt \beta_2 \lt \cdots \lt \beta_T<1

定义观测原图为随机变量 x_0 ,然后定义从随机变量 x_{t-1} 到随机变量 x_t 的分布关系为

\begin{align}q(x_t|x_{t-1})=\mathcal{N}(x_t;\sqrt{1-\beta_t}x_{t-1}, \beta_t )\end{align}

x_t 是均值 \sqrt{1-\beta_t}x_{t-1} 且方差为 \beta_t 的高斯分布,用类似重参数分解可以得到

\begin{align}x_t = \sqrt{1-\beta_t}x_{t-1} + \sqrt{\beta_t} \epsilon_{t-1}, \ \epsilon_i \sim \mathcal{N}(0, 1)\end{align}

对于公式(2)有以下一些解释

  • x{t-1} x{t-1} \epsilon{t-1} \epsilon{t-1} 前面的两个系数平方和等于1
  • \beta_t 单调递增且 \beta_t \in (0, 1) ,则可以保证 t=0 时候方差几乎为0, t=T 时方差几乎为1

如果定义

  • \alpha_t=1-\beta_t 。为了书写方便
  • \bar{\alpha}t=\prod{i=1}^t \alpha_i \bar{\alpha}t=\prod{i=1}^t \alpha_i \bar{\alpha}t=\prod{i=1}^t \alpha_i 。为了书写方便
  • \bar{\epsilon}_k \sim \mathcal{N}(0, 1) 。代表 k 个高斯分布合并之后的新高斯分布

那么递推展开可以得到

\begin{align}x_t&=\sqrt{\alpha_t} x_{t-1} + \sqrt{1-\alpha_t} \epsilon_{t-1} \\ &=\sqrt{\alpha_t \alpha_{t-1}} x_{t-2} + \sqrt{1-\alpha_t \alpha_{t-1}} \bar{\epsilon}_2 \\&= \cdots \\&=\sqrt{\bar{\alpha_t}}x_0 +\sqrt{1-\bar{\alpha_t}}\bar{\epsilon}_t\end{align}

注意

  • 这里用了方差的性质,即两个高斯分布的和还是高斯分布,并且新方差等于这两个高斯分布的方差
  • \bar{\epsilon}_k k 个高斯分布合并之后的新高斯分布
  • x_0 \bar{\epsilon}_t 前面两个系数的平方和仍然是1

观察公式(6)里的$x_t$可以发现

  • 随着 t \rightarrow T \sqrt{\bar{\alpha_t}} \rightarrow 0 \sqrt{1-\bar{\alpha_t}} \rightarrow 1 ,因此 x_t \rightarrow \mathcal{N}(0, 1) ,逐渐变成标准高斯分布,极端情况下 x_T =\mathcal{N}(0, 1)
  • 不仅 q(x_t|x{t-1})=\mathcal{N}(\sqrt{1-\beta_t}x{t-1}, \beta_t ) q(x_t|x{t-1})=\mathcal{N}(\sqrt{1-\beta_t}x{t-1}, \beta_t ) q(x_t|x{t-1})=\mathcal{N}(\sqrt{1-\beta_t}x{t-1}, \beta_t ) 可以直接计算,并且 q(x_t|x_0)=\mathcal{N}(\sqrt{\bar{\alpha_t}}x_0 , 1-\bar{\alpha_t}) 也可以直接计算
  • 整个encoder过程的是完全透明的,可以高效的计算中间任意分布 q(x_t|x_0) 的方式

优化目标

有了encoder过程后,接下来寻找优化目标。我们有两种推导方式

  • 方法1:最小化 D{\text{KL}}(q(x{1:T}|x_0)||p\theta(x{1:T}|x_0)) D{\text{KL}}(q(x{1:T}|x_0)||p\theta(x{1:T}|x_0)) D{\text{KL}}(q(x{1:T}|x_0)||p\theta(x{1:T}|x_0)) D{\text{KL}}(q(x{1:T}|x_0)||p\theta(x{1:T}|x_0)) D{\text{KL}}(q(x{1:T}|x_0)||p\theta(x{1:T}|x_0)) (跟前面VAE一样)
  • 方法2:最小化CE损失 -\mathbb{E}{q(x_0)}\log p\theta(x_0) -\mathbb{E}{q(x_0)}\log p\theta(x_0) -\mathbb{E}{q(x_0)}\log p\theta(x_0)

殊途同归,发现都是要最小化 L_{t-1}

L_{t-1}=\text{KL}(q(x_{t-1}|x_t, x_0) || p_\theta(x_{t-1}|x_t))

  • q(x_{t-1}|x_t, x_0) 可以用贝叶斯公式求得
  • p\theta(x{t-1}|x_t) p\theta(x{t-1}|x_t) p\theta(x{t-1}|x_t) q(x_{t-1}|x_t) 的参数化建模,假设也符合高斯分布,只需关注均值和方差即可

分析 \mathbf{q(x_{t-1}|x_t, x_0)}

使用贝叶斯公式

\begin{align} q(x_{t-1}|x_t, x_0) &= q(x_t|x_{t-1},x_0) \frac{q(x_{t-1}|x_0)}{q(x_t|x_0)} \\ &= q(x_t|x_{t-1}) \frac{q(x_{t-1}|x_0)}{q(x_t|x_0)} \end{align}

惊喜地发现每个 q(\cdot) 代表的是高斯函数的密度函数,因此可以带入得到 q(x{t-1}|x_t, x_0) q(x{t-1}|x_t, x_0) 的密度函数,并且也是高斯分布。此时是可以用待定系数的方式 推导求出 q(x{t-1}|x_t, x_0) q(x{t-1}|x_t, x_0) 的均值 \mu_t(x_t, x_0) 和方差 \sigma_t^2(x_t, x_0) 的,如下所示

\begin{align}\mu_t(x_t,x_0)&=\frac{\sqrt{\alpha_t}(1-\bar{\alpha}_{t-1})}{1-\bar{\alpha}_t}x_t+\frac{\sqrt{\bar{\alpha}_{t-1}}(1-\alpha_t)}{1-\bar{\alpha}_t}x_0\\\sigma_t^2(x_t, x_0)&=\frac{1-\bar{\alpha}_{t-1}}{1-\bar{\alpha}_t} \cdot \beta_t\end{align}

把式中的 x_0 代换掉,可以得

\begin{align}\mu_t(x_t,x_0)&=\frac{1}{\sqrt{\alpha_t}} (x_t-\frac{1-\alpha_t}{\sqrt{1-\bar{\alpha}_t}} \bar{\epsilon}_t)\\\sigma_t^2(x_t, x_0)&=\frac{1-\bar{\alpha}_{t-1}}{1-\bar{\alpha}_t} \cdot \beta_t\end{align}

观察分析方差公式 \sigma_t^2(x_t, x_0) ,其实有好几种选择

  • 选择1: \bar{\alpha}{t-1} \bar{\alpha}{t-1} \bar{\alpha}t \bar{\alpha}t 是通过预先设置 \beta_t 直接计算而来,运算结果是常量
  • 选择2:DDPM里面进一步发现可以简化成 \sigma_t^2(x_t, x_0)=\beta_t
  • 选择3:Improved DDPM里面发现也可以设置成可学

这里我们使用第2种选择 \sigma_t^2(x_t, x_0)=\beta_t ,因此

\begin{align}q(x_{t-1}|x_t, x_0)=\mathcal{N}(x_{t-1};\mu_t(x_t, x_0), \beta_t)\end{align}

分析 \mathbf{p\theta(x{t-1}|x_t)} \mathbf{p\theta(x{t-1}|x_t)} \mathbf{p\theta(x{t-1}|x_t)}

由于已经假设 p\theta(x{t-1}|x_t) p\theta(x{t-1}|x_t) p\theta(x{t-1}|x_t) 是高斯分布且满足

\begin{align}p_\theta(x_{t-1}|x_t)=\mathcal{N}(x_{t-1}; \mu_\theta(x_t, t), \beta_t)\end{align}

那么当我们计算两个高斯分布的KL散度,利用现成结论公式可以得到

\begin{align}L_{t-1}&=\text{KL}(\mathcal{N}(x_{t-1};\mu_t(x_t, x_0), \beta_t)||\mathcal{N}(x_{t-1}; \mu_\theta(x_t, t), \beta_t))\\&\propto||\mu_t(x_t, x_0)-\mu_\theta(x_t, t)||^2\end{align}

DDPM的贡献点之一,就是发现与其让网络输出 $\mu\theta(x_t, t)$预测$\mu_t(x_t, x_0)$ ,不如让网络输出 \epsilon\theta(x_t,t) \epsilon\theta(x_t,t) 预测 \bar{\epsilon}t \bar{\epsilon}t \mu\theta(x_t, t) \mu\theta(x_t, t) \epsilon_\theta(x_t,t) 关系如下

\begin{align}\mu_\theta(x_t, t)= \frac{1}{\sqrt{\alpha_t}} (x_t-\frac{1-\alpha_t}{\sqrt{1-\bar{\alpha}_t}} \epsilon_\theta(x_t,t))\end{align}

于是终于得到了最终的Loss表达式

\begin{align}L_{t-1} &\propto ||\bar{\epsilon}_t-\epsilon_\theta(x_t,t)||^2 \\&= ||\bar{\epsilon}_t-\epsilon_\theta(\sqrt{\bar{\alpha_t}}x_0 +\sqrt{1-\bar{\alpha_t}}\bar{\epsilon}_t,t)||^2\end{align}

于是终于得到了最终的Loss表达式

\begin{align}L_{t-1} &\propto ||\bar{\epsilon}_t-\epsilon_\theta(x_t,t)||^2 \\&= ||\bar{\epsilon}_t-\epsilon_\theta(\sqrt{\bar{\alpha_t}}x_0 +\sqrt{1-\bar{\alpha_t}}\bar{\epsilon}_t,t)||^2\end{align}

这里 \epsilon\theta(\sqrt{\bar{\alpha_t}}x_0 +\sqrt{1-\bar{\alpha_t}}\bar{\epsilon}t,t) \epsilon\theta(\sqrt{\bar{\alpha_t}}x_0 +\sqrt{1-\bar{\alpha_t}}\bar{\epsilon}t,t) \epsilon\theta(\sqrt{\bar{\alpha_t}}x_0 +\sqrt{1-\bar{\alpha_t}}\bar{\epsilon}t,t) 是个U-Net网络,并且时间步 t 需要做embedding灌入网络

训练&推理过程

因此训练方式呼之欲出,引用DDPM的原始paper伪代码

  • 训练的时候只从 T 步里面随机抽取一步来算,这归功于 x_t 只需要 x_0 就能直接算出的良好性质
  • line2-3: 从数据集随机抽取一张图片 x_0 ,同时随机选择一个时间步 t
  • line4: 从标准高斯分布里面采样一个值,当做 x_t 表达式中由 t 个高斯分布合并的新分布 \bar{\epsilon}_t 的采样结果
  • line5: 按照上面MSE的loss的来求梯度,并且做梯度更新

相应的推理过程如下所示

  • 跟VAE一样,训练完就扔掉encoder,然后从标准高斯分布开始采样,然后经过 T 步递推产生 x_0
  • line1:从 x_T 开始,从标准高斯分布采样
  • line2-5, t T 不断递减,直到 t=1
    • 每一步decoder输入为 t x_t ,神经网络先预测出噪声 \epsilon_\theta(x_t, t)
    • x{t-1} x{t-1} 的均值按 \mu\theta(x_t, t) \mu\theta(x_t, t) 的公式计算出
    • x_{t-1} 的方差 \sigma_t 可以按前面的 \sigma_t(x_t, x_0) 公式计算出来。直接用 \sigma_t^2=\beta_t 效果也不错,总之不需要神经网络预测
    • 然后从高斯分布 \mathcal{N}(\mu\theta(x_t, t),\sigma^2_t) \mathcal{N}(\mu\theta(x_t, t),\sigma^2_t) 里面采出样本作为 x{t-1} x{t-1}
  • 这里容易造成困惑的是生成过程每一步为什么还需要采样 z ,直接高斯分布的均值不行吗?个人理解这类似于ChatGPT里面推理的top-p核采样 (忘记的同学可以参考(3)ChatBot是怎么炼成的? ,需要引入一定的随机性,最后的效果反而更好

DDPM推导非常多,我们梳理一下核心逻辑

  • 首先建模encoder过程为清晰图 x_0 到标准高斯分布 x_T 的扩散过程,相应的decoder过程为标准高斯分布 x_T 到清晰图 x_0 的采样过程。我们最后需要的是decoder过程。
  • 定义单调递增的序列 \beta_t ,并定义 q(x_t|x_{t-1}) 的递推表达式
  • 利用递推式可以求出encoder的每一步 x_t 的分布 q(x_t|x_0)
  • 利用贝叶斯公式可以求出分布 q(x{t-1}|x_t, x_0) q(x{t-1}|x_t, x_0) ,并且满足 \mathcal{N}(x{t-1};\mu_t(x_t, x_0),\sigma_t^2(x_t, x_0)) \mathcal{N}(x{t-1};\mu_t(x_t, x_0),\sigma_t^2(x_t, x_0))
  • 变分分析得出最终的优化loss目标为 L{t-1}=\text{KL}(q(x{t-1}|x_t, x_0) || p\theta(x{t-1}|x_t)) L{t-1}=\text{KL}(q(x{t-1}|x_t, x_0) || p\theta(x{t-1}|x_t)) L{t-1}=\text{KL}(q(x{t-1}|x_t, x_0) || p\theta(x{t-1}|x_t)) L{t-1}=\text{KL}(q(x{t-1}|x_t, x_0) || p\theta(x{t-1}|x_t)) L{t-1}=\text{KL}(q(x{t-1}|x_t, x_0) || p\theta(x{t-1}|x_t))
  • 设置 p\theta(x{t-1}|x_t) p\theta(x{t-1}|x_t) p\theta(x{t-1}|x_t) 为高斯分布,并且满足 \mathcal{N}(x{t-1}; \mu\theta(x_t, t), \beta_t) \mathcal{N}(x{t-1}; \mu\theta(x_t, t), \beta_t) \mathcal{N}(x{t-1}; \mu\theta(x_t, t), \beta_t)
  • 带入 L{t-1} L{t-1} 求解,化简表达式,最终发现网络预测噪声 \epsilon\theta(x_t,t) \epsilon\theta(x_t,t) 来逼近 \bar{\epsilon}_t 即可

从Score Function理解DDPM

energy function

对于任意分布 p(\textbf{x}): \mathbb{R}^{D \rightarrow 1} ,没法直接以 D 维输入和1维输出的神经网络拟合,原因是要求

\int p(\textbf{x}) dx=1

但是如果做了如下变换后,发现 f_\theta(\textbf{x}) 几乎没有任何约束了

p(\textbf{x})=\frac{1}{Z_\theta}e^{-f_\theta(\textbf{x})}

此时虽然引入了归一化分母 Z_\theta ,但是如果我们取对数并且对 \textbf{x} 求导,则

\begin{align} \nabla_\textbf{x}\log p(\textbf{x}) &= \nabla_\textbf{x}\log (\frac{1}{Z_\theta}e^{-f_\theta(\textbf{x})}) \\ &= \nabla_\textbf{x}\log \frac{1}{Z_\theta} + \nabla_\textbf{x}\log (e^{-f_\theta(\textbf{x})})\\ &= -\nabla_\textbf{x}f_\theta(\textbf{x}) \end{align}

惊奇地发现 Z\theta Z\theta 不见了,这里的 f\theta(\textbf{x}) f\theta(\textbf{x}) 就是energy function,是个自由函数

score function

进一步观察,发现 \nabla_\textbf{x}\log p(\textbf{x}) 是让 p(\textbf{x}) 概率最大化的前进方向,是个向量场,向量指向最大值的前进方向

此时如果定义 \mathbf{s}\theta(\textbf{x}) \in \mathbb{R}^{D \rightarrow D} \mathbf{s}\theta(\textbf{x}) \in \mathbb{R}^{D \rightarrow D} ,并且要求 \mathbf{s}\theta(\textbf{x}) \mathbf{s}\theta(\textbf{x}) 去直接拟合 \nabla_\textbf{x}\log p(\textbf{x}) ,即最小化

\mathbb{E}_{p(\textbf{x})}[||\textbf{s}_\theta(\mathbf{x})-\nabla_\textbf{x}\log p(\textbf{x})||^2_2]

当模型收敛的时候, \mathbf{s}\theta(\textbf{x}) \mathbf{s}\theta(\textbf{x}) 形成的向量场,沿着 \mathbf{s}\theta(\textbf{x}) \mathbf{s}\theta(\textbf{x}) 行走就能找到 p(\textbf{x}) 的最大值。这里的 \mathbf{s}_\theta(\textbf{x}) 就是 p(\textbf{x}) 的score function

DDPM的另外一种理解

DDPM跟score function会有什么关系呢?

考虑高斯分布 z \sim \mathcal{N}(\mu, \sigma^2) ,当我们有了 z 的观测之后,对于均值 \mu 的期望满足Tweedie’s Formula

\mathbb{E}(\mu|z)=z + \sigma^2 \nabla_z \log p(z)

回想DDPM里面 q(x_t|x_0)=\mathcal{N}(x_t;\sqrt{\bar{\alpha_t}}x_0 , 1-\bar{\alpha_t}) ,因此

\mathbb{E}(\mu_t|x_t)=x_t+(1-\bar{\alpha_t})\nabla_{x_t} \log p(x_t)

另外知道 \mu_t 的最优估计就是 \mathcal{N}(x_t;\sqrt{\bar{\alpha_t}}x_0 , 1-\bar{\alpha_t}) 的均值,即

\sqrt{\bar{\alpha_t}}x_0=\mathbb{E}(\mu_t|x_t)=x_t+(1-\bar{\alpha_t})\nabla_{x_t} \log p(x_t)

因此 x_0 可以用 \nabla_{x_t} \log p(x_t) 表示出来

x_0=\frac{x_t+(1-\bar{\alpha_t})\nabla_{x_t} \log p(x_t)}{\sqrt{\bar{\alpha_t}}}

x_0 带入求 \mu_t(x_t,x_0) 的公式(7),可以得到

\mu_t(x_t,x_0)=\frac{1}{\sqrt{\alpha_t}} x_t + \frac{1-\alpha_t}{\sqrt{\alpha_t}}\nabla_{x_t}\log p(x_t)

到了这里,跟前面DDPM的 $\epsilon\theta(x_t, t)$$\bar{\epsilon}t$ 类似,这里可以用 s\theta(x_t, t) s\theta(x_t, t) 来拟合 \nabla{x_t}\log p(x_t) \nabla{x_t}\log p(x_t) ,即

\begin{align} L_{t-1} &\propto ||s_\theta(x_t, t)-\nabla_{x_t}\log p(x_t)||^2_2 \end{align}

训练完成后。在推理采样的时候,先得到 s_\theta(x_t, t) 之后,然后计算

\mu_\theta(x_t,x_0)=\frac{1}{\sqrt{\alpha_t}} x_t + \frac{1-\alpha_t}{\sqrt{\alpha_t}}s_\theta(x_t, t)

然后采样得到 x_{t-1}

x_{t-1}=\mathcal{N}(x_{t-1};\mu_\theta(x_t,x_0),\beta_t)

因此我们得到了另外一个理解DDPM的角度,就是用网络 s\theta(x_t, t) s\theta(x_t, t) 来预测 \nabla{x_t}\log p(x_t) \nabla{x_t}\log p(x_t) ## DDIMDDIM的出发点是希望能缩减采样次数。观察DDPM的递推公式

x_{t-1}=q(x_{t-1}|x_0)=\sqrt{\bar{\alpha}_{t-1}}x_0 +\sqrt{1-\bar{\alpha}_{t-1}}\bar{\epsilon}_{t-1}

DDIM开了两个脑洞- 脑洞1:把高斯分布 \bar{\epsilon}{t-1} \bar{\epsilon}{t-1} 拆成两个高斯分布 \bar{\epsilon}t \bar{\epsilon}t \epsilon 的和- 脑洞2:无中生有 x_0 ,通过 x_t \bar{\epsilon}t \bar{\epsilon}t 估计 x_0 ,并用在 x{t-1} x{t-1} 求解上

\begin{align} x_{t-1} &\approx \sqrt{\bar{\alpha}_{t-1}}x_0 +\sqrt{1-\bar{\alpha}_{t-1}-\sigma_t^2}\bar{\epsilon}_{t}+\sigma_t \epsilon \\ &\approx \sqrt{\bar{\alpha}_{t-1}}(\frac{x_t-\sqrt{1-\bar{\alpha}}_t \bar{\epsilon_t}}{\sqrt{\bar{\alpha}}})+\sqrt{1-\bar{\alpha}_{t-1}-\sigma_t^2}\bar{\epsilon}_{t}+\sigma_t \epsilon \end{align}

如果让U-Net网络学习 \bar{\epsilon}t \bar{\epsilon}t ,即 \epsilon\theta^t(x_t) \epsilon\theta^t(x_t) ,则可得到最终表达式

x_{t-1}=\sqrt{\bar{\alpha}_{t-1}}(\frac{x_t-\sqrt{1-\bar{\alpha}}_t \cdot \epsilon_\theta^t(x_t)}{\sqrt{\bar{\alpha}}})+\sqrt{1-\bar{\alpha}_{t-1}-\sigma_t^2} \cdot\epsilon_\theta^t(x_t)+\sigma_t \epsilon

可见每一次递推,先根据 x_t 和本次的方差估计 \epsilon\theta^t(x_t) \epsilon\theta^t(x_t) 推出 x_0 ,然后再正向推出 x{t-1} x{t-1} 注意这里的方差为 \sigma_t ,回想原来DDPM里面的方差为

\sigma_t^2(x_t, x_0)=\frac{1-\bar{\alpha}_{t-1}}{1-\bar{\alpha}_t} \cdot \beta_t

因此要方差可比的话

\sigma_t^2=\frac{1-\bar{\alpha}_{t-1}}{1-\bar{\alpha}_t} \cdot \beta_t=\eta \cdot \beta_t

可见要求 \eta 非负。如果 \eta=0 就变成确定性过程,这个就是DDIM。即

x_{t-1}=\sqrt{\bar{\alpha}_{t-1}}(\frac{x_t-\sqrt{1-\bar{\alpha}}_t \cdot \epsilon_\theta^t(x_t)}{\sqrt{\bar{\alpha}}})+\sqrt{1-\bar{\alpha}_{t-1}} \cdot\epsilon_\theta^t(x_t)

因此DDIM主要把reverse过程变成了确定性过程,并且缩减了采样次数## Classifier-GuidedDDPM和DDIM生成的图片虽然视觉上效果还可以,但是在FID等指标上一直比不过GAN,直到出现了Classifier-Guided的方法,本质上是牺牲了一定的多样性,提高了保真度。DDPM过程我们想知道DDPM中加入了标签 y 之后会对 x_t 的生成有什么影响,注意此时模型的encoder过程不变。从 p(x_t|x_{t+1}, y) 原始定义出发,贝叶斯公式展开,最终可以得到下列公式

\begin{align} p(x_t|x_{t+1},y) &= \frac{p(x_t|x_{t+1})p(y|x_t, x_{t+1})p(x_{t+1})}{p(y|x_{t+1})p(x_{t+1})}\\ &= \frac{p(x_t|x_{t+1})p(y|x_t)}{p(y|x_{t+1})}\\ &= Z \cdot p_\theta(x_t|x_{t+1}) \cdot p_\phi(y|x_t) \end{align}

推导Hint如下- y x{t+1} x{t+1} 独立,因此 p(x{t+1}|x_t, y)=p(x{t+1}|x_t) p(x{t+1}|x_t, y)=p(x{t+1}|x_t) p(x{t+1}|x_t, y)=p(x{t+1}|x_t) - y 取值对给定的图而言是确定的,因此 p(y|x{t+1})=p(y)=\text{const} p(y|x{t+1})=p(y)=\text{const} 左右取对数,对 \log p_\phi(y|x_t) 添加尺度因子 s ,可得

\log p(x_t|x_{t+1}, y) = \log p_\theta(x_t|x_{t+1}) + s \cdot \log p_\phi(y|x_t)\\

进一步分析(完整推导见文章)- \log p\theta(x_t|x{t+1}) \log p\theta(x_t|x{t+1}) \log p\theta(x_t|x{t+1}) 项。从DDPM中知道是个高斯分布,可以通过 \epsilon\theta(x_t, t) \epsilon\theta(x_t, t) 求出均值 \mu\theta(x_t, t) \mu\theta(x_t, t) ,因此 \log p\theta(x_t|x{t+1}) \log p\theta(x_t|x{t+1}) \log p\theta(x_t|x{t+1}) 可以用概率密度写出- \log p\phi(y|x_t) \log p\phi(y|x_t) 项。在 x_t=\mu\theta(x_t, t) x_t=\mu\theta(x_t, t) 做泰勒展开最终表达式为

\begin{align} \log p(x_t|x_{t+1}, y) &= \log p(z) + C,\ \ z \sim \mathcal{N}(\mu_\theta(x_t, t)+\sigma\cdot c \cdot\nabla_{x_t}\log p_\phi(y|x_t), \sigma^2) \end{align}

最终推理方式如下所示,本质上是对均值做一下修正

DDIM过程

由于DDIM是个确定性过程, p(x_t|x{t+1}) p(x_t|x{t+1}) 是个确定性映射过程,不是分布。目标对象从 p(x_t|x{t+1}, y) p(x_t|x{t+1}, y) 退化成了 p(x_t|y) 。根据贝叶斯公式

p(x_t|y)=\frac{p(y|x_t)\cdot p(x_t)}{p(y)}

两边取对数,并且对 x_t 求导数(注意 y 不能由 x_t 表出,因此 \nabla_{x_t}\log p(y) 导数为0)

\begin{align} \nabla_{x_t}\log p(x_t|y) &= \nabla_{x_t}\log p(y|x_t)+\nabla_{x_t}\log p(x_t)-\nabla_{x_t}\log p(y)\\ &= \nabla_{x_t}\log p(y|x_t)+\nabla_{x_t}\log p(x_t) \end{align}

\nabla_{x_t}\log p(y|x_t) 加入尺度因子,方便做标签强度调整

\begin{align} \nabla_{x_t}\log p(x_t|y) =\nabla_{x_t}\log p(x_t) + \gamma \cdot \nabla_{x_t}\log p(y|x_t) \end{align}

论文结论可知,借助score function的结论

\nabla_{x_t}\log p(x_t)=-\frac{1}{\sqrt{1-\bar{\alpha}_t}}\epsilon(x_t)

于是代入整理可得,并且对概率进行参数化(这里 p_\phi(y|x_t) 就是分类器)

-\frac{1}{\sqrt{1-\bar{\alpha}_t}}\epsilon_\theta^t(x_t|y)=-\frac{1}{\sqrt{1-\bar{\alpha}_t}}\epsilon_\theta^t(x_t)+\gamma \cdot \nabla_{x_t}\log p_\phi(y|x_t)

整理可以得到

\epsilon_\theta^t(x_t|y)=\epsilon_\theta^t(x_t)-\sqrt{1-\bar{\alpha}_t} \cdot\gamma \cdot \nabla_{x_t}\log p_\phi(y|x_t)

在求出 \epsilon\theta^t(x_t) \epsilon\theta^t(x_t) 之后,用分类器的梯度对其修正,求出 \epsilon\theta^t(x_t|y) \epsilon\theta^t(x_t|y) 后替换原始的 \epsilon_\theta^t(x_t) 。然后再代入DDIM的递推公式中。完整Classifier guided DDIM算法如下

Classifier-freeguidance

训练虽然能提高保真度,但是问题很多- 但是无论是DDPM还是DDIM的推理过程,每一步都需要计算梯度,操作很贵- classifier本身是扛噪音输入的特供版,需要重新训练,例如noisy-CLIP模型能否既得到高保真度结果,又能在推理时免去梯度计算呢?guidance-free应运而生,本质是在训练阶段就想办法提高模型的能力,免去了推理时候的梯度计算。网络首先把condition吃进来,注意这个condition要跟数据相关,例如- 分类的话就是待生成图片的类别- 文生图的话就是文字的embedding训练阶段随机概率把输入condition置为空,即概率性 \epsilon\theta(x_t|y) \rightarrow \epsilon\theta(x_t|\varnothing) \epsilon\theta(x_t|y) \rightarrow \epsilon\theta(x_t|\varnothing) \epsilon\theta(x_t|y) \rightarrow \epsilon\theta(x_t|\varnothing) 推理采样阶段,用下面公式做采样

\hat{\epsilon}_\theta(x_t|y)=(1+w)\cdot \epsilon_\theta(x_t|y)-w\cdot\epsilon_\theta(x_t|\varnothing)

其中 w 为引导强度,一般认为 w>0 会使生成往有condition和无condition差异比较大的方向走,引导强度越大,越牺牲多样性提高保真度。这里的 y 也可以换成其他condition。

小结

生成模型背后有大量的数学原理,本质上想解决如何生成 p(X) 的问题,各类方法总结如下

AIGC评价指标

生成的多模态内容往往包含很强的主观色彩,因此评价相对比较困难,本节我们介绍常见额两种图片生成质量指标,IS(Inception Score) 和 FID (Frechet Inception Distance)

IS指标

Inception Score (IS) 是个非常启发式的指标,本质上利用“Inception网络对于真实图片有很好的判别能力”这个特性而设计得到的,理解这个指标有两个角度,一个是互信息角度,一个是KL散度角度。符号定义如下- x 是个随机变量,由图片生成网络 G 产生。假设 G 生成的图片集合为 X_G G 生成图片的分布为 P_G ,则 x \in X_G x \sim P_G

  • y 是个随机变量,取值离散集合为 L_Y= {1, 2, \cdots, 1000} 。假设inception网络经过softmax后1000分类的概率向量为 \mathbf{p} ,则 y \in L_Y p(y=i)=\mathbf{p}_i

我们可以从两个角度理解这个指标,互信息角度和KL散度角度。

互信息

首先从互信息角度考虑,考察互信息 I(y;x) ,衡量的是两个随机变量 y x 的依赖情况

  • 情况1:如果 x 是随机噪声图片,那么 x 的信息对决定 y 没有任何帮助, x y 完全独立不相关,则 I(y;x)=0
  • 情况2:如果 x 就是ImageNet的图片全集,那么只要 x 就完全能决定 y 的分布,两者完全相关,此时 I(y; x) 应该取到最大值

由此我们知道, I(y;x) x 的真实程度有一定的正相关性。如果我们继续分析 I(y;x) ,想知道最大的 I(y;x) 应该满足什么条件。可以通过互信息公式得到

I(y;x) = H(y) - H(y|x)

如果想最大化这个指标,那么

  • 多样性: 最大化第一项 H(y) ,如果 y 的分布越均匀,多样性越大,不出现模态坍缩, H(y) 才能越大,当 y 为均匀分布的时候
  • 清晰度: 最小化第二项 H(y|X) ,即代表给定图片 x 后的标签 y 的熵,分布越尖峰,越接近one-hot, H(y|X) 才能越小

由上我们知道 I(y;x) 的最大值为

\begin{align}I_\text{max}(y; x)&=H(y)-0\\&=-\sum_{i=1}^{1000}\frac{1}{1000}\ln(\frac{1}{1000})\\&=\ln(1000)\end{align}

KL散度

换一个角度,考察KL散度,给出IS的标准定义

\text{IS}(G)=\exp(\mathbb{E}_{x\sim {P_G}}\text{KL}(p(y|x)||p(y))

这个式子看起来很复杂,但是其实通过数学推导会发现等价于上述的 I(y;x) ,完整推导如下

\begin{align}\ln(\text{IS}(G))&=\mathbb{E}_{x\sim {P_G}}\text{KL}(p(y|x)||p(y) \\&=\sum_{x\in X_G} p(x)\sum_{y\in L_Y}p(y=i|x)\cdot \ln\frac{p(y=i|x)}{p(y=i)} \\&=\sum_{x\in X_G} \sum_{y\in L_Y} p(y=i, x)\cdot \ln p(y=i|x) - \sum_{x\in X_G} \sum_{y\in L_Y} p(y=i, x)\cdot \ln p(y=i)\\&= -H(y;x) +(- \sum_{y\in L_Y} \ln p(y=i)\sum_{x\in X_G}p(y=i, x)) \\&=-H(y;x)+(- \sum_{y\in L_Y} \ln p(y=i) \cdot p(y=i)) \\&=-H(y;x) + H(y) \\&= I(y;x)\end{align}

因此可以得到

\text{IS}(G)=e^{I(y;x)}

计算代码

条件假设

  • 假设我们选取了 N 张图片,分别为 {x_1, x_2, \cdots, x_N}
  • 将这N张图喂入inception网络,得到输出的softmax概率tensor为 Z \in \mathbb{R}^{N \times 1000}
  • Z(i, j) 相当于 p(y=j|x=x_i) ,即第 i 张图的第 j 个label的概率值
  • p(x=x_i)=1/N ,看成均匀分布
  • 边缘分布重新写成条件概率求和的方式

\begin{align}p(y=j)&=\sum_{i=1}^Np(y=j, x=x_i)\\&=\sum_{i=1}^N p(x=x_i) \cdot p(y=j|x=x_i) \\&=\frac{1}{N}\sum_{i=1}^N p(y=j|x=x_i)\end{align}

因此可以得到可计算的IS表达,如下所示

\begin{align}\text{IS}(G)&=\exp(\sum_{x\in X_G} p(x)\sum_{y\in L_Y}p(y=i|x)\cdot \ln\frac{p(y=i|x)}{p(y=i)}) \\&=\exp(\sum_{i=1}^N \frac{1}{N}\sum_{j=1}^{1000} p(y=j|x=x_i)\cdot \ln\frac{p(y=j|x=x_i)}{\frac{1}{N}\sum_{k=1}^Np(y=j|x=x_k)}) \\\end{align}

至此终于可以把所有 p(y=j|x=x_i) Z 来替换了,即

\begin{align}\text{IS}(G)&=\exp(\frac{1}{N} \sum_{i=1}^N \sum_{j=1}^{1000} Z(i,j)\cdot \ln\frac{Z(i,j)}{\frac{1}{N}\sum_{k=1}^NZ(k,j)}) \\\end{align}

最终代码如下 (一般切分多个splits来计算,计算均值和方差)

def calculate_inception_score(z_preds, splits=10):
    # z_preds: (N, 1000)
    scores = []
    for i in range(splits):
        slice_start = i * z_preds.shape[0] // splits
        slice_end = (i + 1) * z_preds.shape[0] // splits
        part = z_preds[slice_start:slice_end, :]
        kl = part * (np.log(part) - np.log(np.mean(part, 0, keepdims=True)))
        kl = np.mean(np.sum(kl, 1))
                kl = np.exp(kl)
        scores.append(kl)
    return np.mean(scores), np.std(scores)

FID指标

指标Frechet是个人名,法国数学家,提出了Frechet Distance概念。

Frechet Inception Distance(FID)指标计算过程如下

  • 给出了生成图片集合 X_G 和真实图片集合 X_R ,集合大小分别为 N M
  • X_G X_R 经过Inception v3得到对应feature集合 F_G \in \mathbb{R}^{N \times D} F_R \in \mathbb{R}^{M \times D}
  • F_G F_R 分别看成是来自于某分布 P_G P_R 的样本点, \mu_G \Sigma_G 分别是 P_G 的均值和协方差,同理 \mu_R \Sigma_R 分别是 P_R 的均值和协方差
  • P_G P_R 是多元高斯分布的假设前提下,按照FD定义可以求解得到

\text{FID}(X_G, X_R)=\text{FD}(P_G, P_R)=||\mu_G-\mu_R||^2_2+\text{Tr}(\Sigma_G+\Sigma_R-2(\Sigma_G \Sigma_R)^{\frac{1}{2}})

提供一些个人直观理解

  • FID是衡量生成图片和真实图片的距离,数值越小越好
  • FD指标数学定义比较复杂,也叫2-Wasserstein距离,跟最优传输理论相关
  • FD指标本身是个下界值,含义可以理解为,把概率分布 P_G 投射到概率分布 P_R 的解期望传输代价最小值,详细数学定义见wiki

计算FD指标的代码如下

import numpy as np
from scipy import linalg

def calculate_frechet_distance(feat_G, feat_R, eps=1e-6):
    # feat_G: (N, D)
    # feat_R: (M, D)
    mu1, sigma1 = np.mean(feat_G, axis=0), np.cov(feat_G.T)
    mu2, sigma2 = np.mean(feat_R, axis=0), np.cov(feat_R.T)
    diff = mu1 - mu2

    # product might be almost singular
    covmean, _ = linalg.sqrtm(sigma1.dot(sigma2), disp=False)
    if not np.isfinite(covmean).all():
        offset = np.eye(sigma1.shape[0]) * eps
        covmean = linalg.sqrtm((sigma1 + offset).dot(sigma2 + offset))

    # numerical error might give slight imaginary component
    if np.iscomplexobj(covmean):
        if not np.allclose(np.diagonal(covmean).imag, 0, atol=1e-3):
            m = np.max(np.abs(covmean.imag))
            raise ValueError("Imaginary component {}".format(m))
        covmean = covmean.real

    tr_covmean = np.trace(covmean)

    return diff.dot(diff) + np.trace(sigma1) + np.trace(sigma2) - 2 * tr_covmean

小结

  • IS指标计算有很强的先验,认为符合ImageNet的分布才是真实分布
  • FID指标衡量两个数据集的距离,更科学一点

写在最后

本文一共分了2个小节

  • 首先介绍了生成模型的本质目的,就是为了建模 p(x) 分布。
    • 首先是最朴素的极大似然估计,虽然简单,但是要求有明确的参数化分布形式,在实际中往往不可得
    • 接着介绍4种隐变量模型,包括VAE,GAN,Flow Model和Diffusion Model。本质上用 p(x)=\int p(x|z) p(z) \text{d}z 来近似
    • VAE模型。尝试提高 p(z) 采样效率,尝试最小化 \text{KL}(q_\theta(z|x)||p(z)) ,最终得到了正则项和重建误差项
    • GAN模型。尝试对MSE的损失函数做进一步拓展,引入判别模型 D(x', x) 来隐式学习度量方法
    • Flow Model模型。强行让 f 函数可逆,满足 x z 的一一映射,以RevNet为例子介绍Flow Model具体使用方式
    • Diffusion Model (DDPM)。将VAE扩展到了多步,有复杂的数学推导,但是本质上跟VAE是相似的
    • DDPM的score function。换一种角度理解DDPM,发现可以用网络 s\theta(x_t, t) s\theta(x_t, t) 来预测 \nabla{x_t}\log p(x_t) \nabla{x_t}\log p(x_t)
    • DDIM。尝试对DDPM做采样加速,将DDPM变成了确定性的过程
    • classifier-guided。使用classifier-guided技术,首次把DDPM和DDIM的IS和FID指标拉高到GAN齐平。在推理阶段,DDPM可以直接分析 p(x_t|x_{t+1}, y) ;而对于DDIM,由于是个确定性过程,因此退化成分析 p(x_t|y)
    • classifier-free。为了省去classifier-guided的梯度计算过程,classifier-free在训练中混合训练有condition和无condition的模型,使得在推理阶段无需求解梯度,在提高保真度的同时计算效率也很高
  • 接着介绍了图片生成常见的两种指标
    • IS(Inception Score)指标提供了两种理解角度。IS本身有很强的先验,认为符合ImageNet的分布才是真实分布
    • FID(Frechet Inception Distance) 指标,衡量两个数据集的距离,更科学一点

预告:计划下一篇为《AIGC组成原理(下)》,将介绍具体的Image生成、Video生成、Audio生成和3D生成算法,敬请期待。

PS:由于笔者小A并没有亲手撸过上述内容的所有细节,大部分是通过研究代码和精读优秀文章的方式 bottom-up 总结而来,本质上是个拾人牙慧的知识搬运工,所以终究是纸上谈兵。因此希望各方有实际经验的大佬猛锤,思维碰撞才生火花,真理越辩越明。

如果想了解transformer在NLP/多模态/AIGC的算法知识,分布式训练的知识,以及如何在TVM上做PTQ量化和部署,可以关注我aaronxic哟~

系列文章导览

参考资料