笔记|扩散模型(六)DALL-E 理论与实现|自回归文生图
论文链接:Zero-Shot
Text-to-Image Generation
官方实现:openai/DALL-E
非官方实现:kuprel/min-dalle、lucidrains/DALLE-pytorch
虽然 DALL-E 并不是基于扩散模型的方法,但是因为它的后续工作 DALL-E 2
和 DALL-E 3 都是基于扩散模型的,所以这个方法也放到扩散模型系列里。
DALL-E 是 OpenAI
比较早期的文生图模型,和一些早期的多模态方法的做法类似,其主要的思想是将图像的
token 和文本的 token 当作同一个序列输入
Transformer,利用自回归生成能力进行图像生成。除了使用 Transformer
进行生成之外,由于图像的像素数量相比文本 token
来说过多,因此需要将图像也预先进行 tokenization,这里使用的模型是
VQ-VAE(也就是 dVAE);为了优先输出生成质量比较高的结果,这里使用 CLIP
对结果的质量进行了排序。总结来说,DALL-E 共包括三个部分:
Transformer:用来进行自回归生成;
VQ-VAE:将图像 t ...
笔记|扩散模型(五)Classifier-Free Guidance 理论与实现
论文链接:Classifier-Free Diffusion
Guidance
上一篇文章我们学习了 Classifier
Guidance,这种方法通过引入一个额外的分类器,使用梯度引导的方式成功地实现了条件生成。虽然
Classifier Guidance 可以直接复用训练好的 diffusion
models,不过这种方法的问题是很明显的,首先需要额外训练一个分类器,而且这个分类器不仅仅分类一般的图像,还需要分类加噪后的图像,这会给方法带来比较大的额外开销;其次分类器训练完成后类别就固定下来了,如果希望生成新的类别就需要重新训练分类器。这篇文章学习的
Classifier-Free Guidance 则可以比较好地解决这些问题。
Classifier-Free Guidance
在 Classifier Guidance 中,从条件概率 \(p(\mathbf{x}_t|y)\) 出发,利用贝叶斯公式和
score function
推导出了以下公式,在下面的公式中,等号右侧的第一项已知,第二项则需要引入分类器进行计算。
\[
\nabla_{\mathbf{x}_t}\lo ...
笔记|扩散模型(四)Classifier Guidance 理论与实现
论文链接:Diffusion
Models Beat GANs on Image Synthesis
在前边的几篇文章中我们已经学习了 DDPM
以及分别对其训练和采样过程进行改进的工作,不过这些方法都只能进行无条件生成,而无法对生成过程进行控制。我们这次学习的不再是无条件生成,而是通过一定方式对生成过程进行控制,比较常见的有两种:Classifier
Guidance 与 Classifier-Free Guidance,本文首先介绍第一种。
一些工作背景
实际上 Classifier Guidance 是上边给出的论文工作中的一部分,虽然
Improved DDPM 已经比较有效地提升了 DDPM
的生成效果,但在一些大数据集上的效果仍然不如当时主流的生成模型 GAN。因此
OpenAI 在 Improved DDPM
的基础上继续进行了一些改进,主要是一些工程上的改进:
在模型的尺寸基本不变的前提下,提升模型的深度与宽度之比,相当于使用更深的模型;
增加多头注意力中 head 的数量;
使用多分辨率 attention,即 32x32、16x16 和 8x8,而不是只在 1 ...
笔记|Score-based Generative Models(二)基于 SDE 的模型
上一篇文章中我们介绍了 score-based model
的基本概念,包括其如何对分布进行建模、如何从建模的分布中进行采样以及通过对分布进行扰动提高其建模精度的方式。在这篇文章中我们将介绍的是如何使用随机微分方程(也就是
SDE)进行 score-based 建模。
随机微分方程简介
首先我们先介绍一些随机微分方程的基本知识以便理解。
我们首先举一个常微分方程(ODE)的例子,例如下面的一个常微分方程: \[
\frac{\mathrm{d}\mathbf{x}}{\mathrm{d}t}=\mathbf{f}(\mathbf{x},t)\quad\mathrm{or}\quad\mathrm{d}\mathbf{x}=\mathbf{f}(\mathbf{x},t)\mathrm{d}t
\] 其中的 \(\mathbf{f}(\mathbf{x},t)\) 是一个关于 \(\mathbf{x}\) 和 \(t\) 的函数,其描述了 \(\mathrm{x}\)
随时间的变化趋势,如下面图中的左图所示。直观地说,\(\mathbf{f}(\mathbf{x},t)\)
对应于图中的 ...
笔记|Score-based Generative Models(一)基础理论
这篇文章应该属于 Diffusion Models
系列的一个番外篇,虽然基于分数的生成模型包括了一系列比较复杂的研究,不过之所以写这篇博客是为了给
score-based diffusion models
的学习做准备,所以应该不会面面俱到,主要还是介绍基础知识。
正式开始介绍之前首先解答一下这个问题:score-based
模型是什么东西,微分方程在这个模型里到底有什么用?我们知道生成模型基本都是从某个现有的分布中进行采样得到生成的样本,为此模型需要完成对分布的建模。根据建模方式的不同可以分为隐式建模(例如
GAN、diffusion models)和显式建模(例如 VAE、normalizing
flows)。和上述的模型相同,score-based
模型也是用一定方式对分布进行了建模。具体而言,这类模型建模的对象是概率分布函数
log 的梯度,也就是 score
function,而为了对这个建模对象进行学习,需要使用一种叫做
score matching 的技术,这也是 score-based
模型名字的来源。至于第二个问题,微分方程的作用本篇文章暂时不介绍,下一篇文章再进行 ...
笔记|扩散模型(三)Improved DDPM 理论与实现
论文链接:Improved
Denoising Diffusion Probabilistic Models
在前边两篇文章中我们学习了 DDPM 和 DDIM,这篇文章介绍的是 Improved
DDPM,是一个针对 DDPM 生成效果进行改进的工作。
虽然 DDPM 在生成任务上取得了不错的效果,但如果使用一些 metric 对 DDPM
进行评价,就会发现其虽然能在 FID 和 Inception Score
上获得不错的效果,但在负对数似然(Negative
Log-likelihood,NLL)这个指标上表现不够好。根据 VQ-VAE2 文章中的观点,NLL
上的表现体现的是模型捕捉数据整体分布的能力。而且有工作表明即使在 NLL
指标上仅有微小的提升,就会在生成效果和特征表征能力上有很大的提升。
Improved DDPM 主要是针对 DDPM
的训练过程进行改进,主要从两个方面进行改进:
不使用 DDPM 原有的固定方差,而是使用可学习的方差;
改进了加噪过程,使用余弦形式的 Scheduler,而不是线性
Scheduler。
可学习的方差
我们知道 DDPM ...
笔记|扩散模型(二)DDIM 理论与实现
论文链接:Denoising
Diffusion Implicit Models
在上一篇文章中我们进行了
DDPM 的理论推导,并且自己编写代码实现了 DDPM
的训练和采样过程。虽然取得了还不错的效果,但 DDPM
有一个非常明显的问题:采样过程很慢。因为 DDPM
的反向过程利用了马尔可夫假设,所以每次都必须在相邻的时间步之间进行去噪,而不能跳过中间步骤。原始论文使用了
1000 个时间步,所以我们在采样时也需要循环 1000
次去噪过程,这个过程是非常慢的。
为了加速 DDPM 的采样过程,DDIM 在不利用马尔可夫假设的情况下推导出了
diffusion 的反向过程,最终可以实现仅采样 20~100 步的情况下达到和 DDPM
采样 1000 步相近的生成效果,也就是提速 10~50 倍。这篇文章将对 DDIM
的理论进行讲解,并实现 DDIM 采样的代码。
DDPM 的反向过程
首先我们回顾一下 DDPM 反向过程的推导,为了推导出 \(q(\mathbf{x}_{t-1}|\mathbf{x}_t)\)
这个条件概率分布,DDPM
利用贝叶斯公式将其变成了先验分布的组 ...
笔记|扩散模型(一)DDPM 理论与实现
感谢 qq、wbs、hsh 等读者对本文提出的宝贵意见(大拍手
论文链接:Denoising
Diffusion Probabilistic Models
端午假期卷一卷,开一个新坑系统性地整理一下扩散模型的相关知识。扩散模型的名字来源于物理中的扩散过程,对于一张图像来说,类比扩散过程,向这张图像逐渐加入高斯噪声,当加入的次数足够多的时候,图像中像素的分布也会逐渐变成一个高斯分布。当然这个过程也可以反过来,如果我们设计一个神经网络,每次能够从图像中去掉一个高斯噪声,那么最后就能从一个高斯噪声得到一张图像。虽然一张有意义的图像不容易获得,但高斯噪声很容易采样,如果能实现这个逆过程,就能实现图像的生成。
这个过程可以形象地用上图表示,扩散模型中有两个过程,分别是前向过程(从图像加噪得到噪音)和反向过程(从噪音去噪得到图像)。在上图中,向图像
\(\mathbf{x}_0\)
逐渐添加噪声可以得到一系列的 \(\mathbf{x}_1,\mathbf{x}_2,...,\mathbf{x}_T\),最后的
\(\mathbf{x}_T\)
即接近完全的高斯噪声,这个过程显然是比较容易 ...
笔记|Normalizing Flow 理论与实现(一)基础理论
Normalizing
flow(标准化流)是一类对概率分布进行建模的工具,它能完成简单的概率分布(例如高斯分布)和任意复杂分布之间的相互转换,经常被用于
data generation、density estimation、inpainting 等任务中,例如 Stability
AI 提出的 Stable Diffusion
3 中用到的 rectified flow 就是 normalizing flow 的变体之一。
为了便于理解,在正式开始介绍之前先简要说明一下 normalizing flow
的做法。如上图所示,为了将一个高斯分布 \(z_0\) 转换为一个复杂的分布 \(z_K\),normalizing flow 会对初始的分布
\(z_0\)
进行多次可逆的变换,将其逐渐转换为 \(z_K\)。由于每一次变换都是可逆的,从 \(z_K\) 出发也能得到高斯分布 \(z_0\)。这样,我们就实现了复杂分布与高斯分布之间的互相转换,从而能从简单的高斯分布建立任意复杂分布。
对 diffusion models 比较熟悉的读者可能已经发现了,这个过程和
diffusi ...
技术相关|使用 Pytorch 进行分布式训练
其实 Pytorch 分布式训练已经不算什么新技术了,之所以专门写一篇 blog
是因为今天训模型的时候出现了一个没见过的问题,在调试的时候发现自己平时都是用别人写好的分布式代码,没有深入研究过其中的实现细节,因此感觉有必要整理吸收一下。
最简单的数据并行
作为最简单的并行计算方式,使用 nn.DataParallel
只需要添加一行代码即可完成:
123456module = nn.DataParallel( module, # 原始模型 device_ids=None, # 使用的显卡 output_device=None, # 输出汇总的显卡 dim=0 # Batch 所在维度)
除此之外,其他的部分和单卡训练的内容基本上都相同。在使用
nn.DataParallel
进行训练时,在每次前向传播时,nn.DataParallel
会做以下几件事:
切分数据:对于输入的 Tensor,其会被沿 batch
维度切分成多份,用于输入不同的显卡;对于元组、列表、字典等类型,其会被浅拷贝 ...