写点什么

文本生成图像 DALL·E 2 背后的原理——Diffusion Model | 社区征文

作者:秃头小苏
  • 2023-07-23
    辽宁
  • 本文字数:7902 字

    阅读完需:约 26 分钟

文本生成图像DALL·E 2背后的原理——Diffusion Model | 社区征文

文本生成图像 DALL·E 2 背后的原理——Diffusion Model

写在前面

Hello,大家好,我是小苏🧒🏽🧒🏽🧒🏽


DALL·E 2 大家是不是都已经玩过了呢,它是一款人工智能图像生成器,它可以根据自然语言的文本描述创建图像和艺术形式。没体验过的快点击https://openai.com/dall-e-2链接去试试叭🥬🥬🥬

我们可以直观来看看 DALL·E 2 生成图片的效果,是不是很惊艳呢!!!

这么惊艳的 DALL·E 2 是怎么实现的呢?背后的原理和机制又是什么呢?其实啊,关键技术就是 Diffusion Model。那么今天就为大家来介绍介绍 Diffusion Model(扩散模型 )


在具体介绍之前呢,先来谈谈 Diffusion Model 主要是用来干什么的。🥂🥂🥂其实啊,它对标的是生成对抗网络(GAN),只要 GAN 能干的事它基本都能干。🍄🍄🍄在之前我已经做过很多期有关 GAN 网络的教学,还不清楚的可以点击☞☞☞进入专栏查看详情。在我一番体验 Diffusion Model 后,它给我的感觉是非常惊艳的。我之前用 GAN 网络来实现一些图片生成任务其实效果并不是很理想,而且往往训练很不稳定。但是换成 Diffusion Model 后生成的图片则非常逼真,也明显感觉到每一轮训练的结果相比之前都更加优异,也即训练更加稳定。


说了这么多,我就是想告诉大家 Diffusion Model 值得一学。🍋🍋🍋但是说实话,这部分的公式理解起来是有一定困难的,我想这也成为了想学这个技术的同学的拦路虎。那么本文将用通俗的语言和公式为大家介绍 Diffusion Model,并且结合公式为大家梳理 Diffusion Model 的代码,探究其是如何通过代码实现的。如果你想弄懂这部分,请耐心读下去,相信你会有所收获。🌾🌾🌾


如果你准备好了的话,就让我们开始吧!!!🚖🚖🚖

Diffusion Model 原理详解

整体思路

Diffusion Model 的整体思路如下图所示:



其主要分为正向过程和逆向过程,正向过程类似于编码,逆向过程类似于解码。


  • 正向过程

  • 首先,对于一张原始图片,我们给加一个高斯噪声,图片由变成【注意:这里必须要加高斯噪声喔,因为高斯噪声服从高斯分布,后面的一些运算需要用到高斯分布的一些特性】接着我们会在的基础上再添加高斯噪声得到。重复上述添加高斯噪声步骤,直到图片变成,由于添加了足够多的高斯噪声,现在的近似服从高斯分布(又称正态分布)。

  • 现在有一个问题需要大家思考一下,我们每一步添加高斯噪声的量一直是不变的吗?🎅🏽🎅🏽🎅🏽滴,开始解答。答案是每步添加高斯噪声的量是变化的,且后一步比前一步添加的高斯噪声更多。我想这一点你通过上图也非常容易理解,一开始原图比较干净,我们添加少量高斯噪声就能对原图产生干扰;但越往后高斯噪声量越多,如果还添加一开始少量的高斯噪声,那么这时对上一步结果基本不会产生任何影响。【注:后文所述的每个时刻图像和这里的每一步图像都是一个意思,如时刻图像表示的就是这个图像】

  • 逆向过程

  • 首先,我们会随机生成一个服从高斯分布的噪声图片,然后一步一步的减少噪声直到生成预期图片。逆向过程大家先有这样的一个认识就好,具体细节稍后介绍。🌱🌱🌱


怎么样,大家现在的感觉如何?是不是知道了 Diffusion Model 大概是怎么样的过程了呢,但是又对里面的细节感到很迷惑,搞不懂这样是怎么还原出图片的。不用担心,后面我会慢慢为大家细细介绍。🥡🥡🥡

实施细节

这一部分为大家介绍一下 Diffusion Model 正向过程和逆向过程的细节,主要通过推导一些公式来表示加噪前后图像间的关系,谈到公式,大家可能头都大了,相信我,你可以看懂!!!🥂🥂🥂

正向过程

在整体思路部分我们已经知道了正向过程其实就是一个不断加噪的过程,于是我们考虑能不能用一些公式表示出加噪前后图像的关系呢。我想让大家先思考一下后一时刻的图像受哪些因素影响呢,更具体的说,比如由哪些量所决定呢?我想这个问题很简单,即是由和所加的噪声共同决定的,也就是说后一时刻的图像主要由两个量决定,其一是上一时刻图像,其二是所加噪声量。【这个很好理解,大家应该都能明白吧】明白了这点,我们就可以用一个公式来表示时刻和时刻两个图像的关系,如下:




——公式 1


其中,表示时刻的图像,表示时刻图像,表示添加的高斯噪声,其服从 N(0,1)分布。【注:N(0,1)表示标准高斯分布,其方差为 1,均值为 0】目前你可以看出都有关系,这和我们前文所述后一时刻的图像由前一时刻图像和噪声决定相符合,这时你可能要问了,那么这个公式前面的是什么呢,其实这个表示这两个量的权重大小,它们的平方和为 1。


enmmm,我想你已经明白了公式 1,但是你可能对的理解还存在一些疑惑,如为什么要设置这样的权重?这个权重的设置是我们预先设定的吗?🌶🌶🌶其实呢,还和另外一个量有关,关系式如下:




——公式 2


其中,是预先给定的值,它是一个随时刻不断增大的值,论文中它的范围为[0.0001,0.02]。既然越来越大,则越来越小,越来越小,越来越大。现在我们在来考虑公式 1,的权重随着时刻增加越来越大,表明我们所加的高斯噪声越来越多,这和我们整体思路部分所述是一致的,即越往后所加的噪声越多。🍄🍄🍄




现在,我们已经得到了时刻和时刻两个图像的关系,但是时刻的图像是未知的。【注:只有阶段图像是已知的,即原图】我们需要再由时刻推导出时刻图像,然后再由时刻推导出时刻图像,依此类推,直到由时刻推导出时刻图像即可。既然这样我们不妨先试试时刻图像和时刻图像的关系,如下:


这个公式很简单吧,就是公式 1 的一个类推公式,此时我们将公式 3 代入公式 1 中得:


——公式 4


这个公式 4 大家能理解吗?🌼🌼🌼我觉得大家应该对最后一个等式存在疑惑,也即怎么等于 ?其实呢,这个用到了高斯分布的一些知识,这部分见附录部分,我做相关介绍。看了附录中高斯分布的相关性质,我想这里你应该能够理解了,我在帮大家整理一下,如下图所示:



这下对于公式 4 的内容都明白了叭。注意这里的也是服从高斯分布的,服从。我们来看看公式 4 得到了什么——其得到了时刻图像和时刻图像的关系。按照我们先前的理解,我们再列出时刻图像和时刻图像的关系,如下:

同理,我们将公式 5 代入到公式 4 中,得到时刻图像和时刻图像的关系,公式如下:


——公式 6


公式 5 我没有带大家一步步的计算了,只写出了最终结果,大家可以自己算一算,非常简单,也只用到了高斯分布的相关性质。注意上述的同样服从的高斯分布。那么公式 6 就得到了时刻图像和时刻图像的关系,我们如果这么一直计算下去,就会得到时刻图像和时刻图像的关系。但是这样的推导貌似很漫长,随着向后推导你会发现这种推导是有规律的。我们可以来比较一下公式 4 和公式 6 的结果,你会发现很明显的规律,这里我就根据这个规律直接写出时刻图像和时刻图像的关系,你看看和你想的是否一致喔,公式如下:


——公式 7


其中表示累乘操作,即,N(0,1)Z 服从标准高斯分布即可,用什么表示都行】这个公式 7 就是整个正向过程的核心公式喔,其表示时刻的图像可以由时刻的图像和一个标准高斯噪声表示,大家需要牢记这个公式哦,在后文以及代码中会用到。🍈🍈🍈



逆向过程

逆向过程是将高斯噪声还原为预期图片的过程。先来看看我们已知条件有什么,其实就一个时刻的高斯噪声。我们希望将时刻的高斯噪声变成时刻的图像,是很难一步到位的,因此我们思考能不能和正向过程一样,先考虑时刻图像和时刻的关系,然后一步步向前推导得出结论呢。好的,思路有了,那就先来想想如何由已知的时刻图像得到时刻图像叭。🥂🥂🥂


有没有大佬想出怎么办呢?我就不卖关子了,要想由时刻图像得到时刻图像,我们需要利用正向过程中的结论,我们在正向过程中可以由时刻图像得到时刻图像,然后利用贝叶斯公式即可求解。


!!!???什么,贝叶斯公式,不知道大家是否了解。如果不知道的建议去学习一下概率的知识,如果实在也不想学,大家就记住贝叶斯公式的表达式即可,如下:



那么我们将利用贝叶斯公式来求时刻图像,公式如下:




——公式 8


公式 8 中我们可以求得,就是刚刚正向过程求的嘛。🍟🍟🍟但是未知的。又由公式 7 可知,可由得到每一时刻的图像,那当然可以得到时刻的图像,故将公式 8 加一个作为已知条件,将公式 8 变成公式 9,如下:




——公式 9


现在可以发现公式 9 右边 3 项都是可以算的啦,我们列出它们的公式和对应的分布,如下图所示:



知道了公式 9 等式右边 3 项服从的分布,我们就可以计算出等式左边的。大家知道怎么计算嘛,这个很简单啦,没有什么技巧,就是纯算。在附录->高斯分布性质部分我们知道了高斯分布的表达式为:。那么我们只需要求出公式 9 等式右边 3 个高斯分布表达式,然后进行乘除运算即可求得



上图为等式右边三个高斯分布表达式,这个结果怎么得的大家应该都知道叭,就是把各自的均值和方差代入高斯分布表达式即可。现我们只需对上述三个式子进行对应乘除运算即可,如下图所示:





现在我们有了均值和方差就可以求出了,也就是求得了时刻的图像。推导到这里不知道大家听懂了多少呢?其实你动动小手来算一算你会发现它还是很简单的。但是不知道大家有没有发现一个问题,我们刚刚求得的最终结果中含义一个,这个是什么啊,他是我们最后想要的结果,现在怎么当成已知量了呢?这一块确实有点奇怪,我们先来看看我们从哪里引入了。往上翻翻你会发现使用贝叶斯公式时我们利用了正向过程中推导的公式 7 来表示,但是现在看来那个地方会引入一个新的未知量,该怎么办呢?这时我们考虑用公式 7 来反向估计,即反解公式 7 得出的表达式,如下:


——公式 10


得到的估计值,此时将公式 10 代入到上图的中,计算后得到最后估计的 ,表达式如下:


——公式 11


好了,现在在整理一下时刻图像的均值和方差,如下图所示:



有了公式 12 我们就可以估计出时刻的图像了,接着就可以一步步求出的图像啦。🍄🍄🍄🍄



原理小结

这一小节原理详解部分就为大家介绍到这里了,大家听懂了多少呢。相信你阅读了此部分后,对 Diffusion Model 的原理其实已经有了哥大概的解了,但是肯定还有一些疑惑的地方,不用担心,代码部分会进一步帮助大家。🌸🌸🌸

Diffusion Model 源码解析

代码下载及使用

本次代码下载地址:Diffusion Model代码🚀🚀🚀


先来说说代码的使用吧,代码其实包含两个项目,一个的ddpm.py,另一个是ddpm_condition.py。大家可以理解为ddpm.py是最简单的扩散模型,ddpm_condition.pyddpm.py的优化。本节会以ddpm.py为大家讲解。代码使用起来非常简单,首先在ddpm.py文件中指定数据集路径,即设置dataset_path的值,然后我们就可以运行代码了。需要注意的是,如果你使用的是 CPU 的话,那么你可能还需要修改一下代码中的device参数,这个就很简单啦,大家自己摸索摸索就能研究明白。




这里来简单说说ddpm的意思,英文全称为Denoising Diffusion Probabilistic Model,中文译为去噪扩散概率模型。🍄🍄🍄



代码流程图

这里我们直接来看论文中给的流程图好了,如下:



看到这个图你大概率是懵逼的,我来稍稍为大家解释一下。首先这个图表示整个算法的流程分为了训练阶段(Training)和采样阶段(Sampling)。


  • Training

  • 我们先来看看训练阶段我们做了什么?众所周知,训练我们需要有真实值和预测值,那么对于本例的真实值和预测值是什么呢?真实值是我们输入的图片,预测值是我们输出的图片吗?其实不是,这里我就不和大家卖关子了。对于本例来说,真实值和预测值都是噪声,我们同样拿下图为大家做个示范。


  • 我们在正向过程中加入的噪声其实都是已知的,是可以作为真实值的。而逆向过程相当于一个去噪过程,我们用一个模型来预测噪声,让正向过程每一步加入的噪声和逆向过程对应步骤预测的噪声尽可能一致,而逆向过程预测噪声的方式就是丢入模型训练,其实就是 Training 中的第五步。

  • Sampling

  • 知道了训练过程,采样过程就很简单了,其实采样过程就对应我们理论部分介绍的逆向过程,由一个高斯噪声一步步向前迭代,最终得到时刻图像。

代码解析

首先,按照我们理论部分应该有一个正向过程,其最重要的就是最后得出的公式 7,如下:




那么我们在代码中看一看是如何利用这个公式 7 的,代码如下:


def noise_images(self, x, t):    sqrt_alpha_hat = torch.sqrt(self.alpha_hat[t])[:, None, None, None]    sqrt_one_minus_alpha_hat = torch.sqrt(1 - self.alpha_hat[t])[:, None, None, None]    Ɛ = torch.randn_like(x)    return sqrt_alpha_hat * x + sqrt_one_minus_alpha_hat * Ɛ, Ɛ
复制代码


Ɛ为随机的标准高斯分布,其实也就是真实值。大家可以看出,上式的返回值sqrt_alpha_hat * x + sqrt_one_minus_alpha_hat其实就表示公式 7。【注:这个代码我省略了很多细节,我只把关键的代码展示给大家看,要想完全明白,还需要大家记住调试调试了】


接着我们就通过一个模型预测噪声,如下:


predicted_noise = model(x_t, t)
复制代码


model的结构很简单,就是一个 Unet 结构,然后里面嵌套了几个 Transformer 机制,我就不带大家跳进去慢慢看了。现在有了预测值,也有了真实值Ɛ【返回后Ɛ用 noise 表示】,就可以计算他们的损失并不断迭代了。


loss = mse(noise, predicted_noise)optimizer.zero_grad()loss.backward()optimizer.step()
复制代码




上述其实就是训练过程的大体结构,我省略了很多,要是大家有任何问题的话可以评论区留言讨论。现在就来看看采样过程的代码吧!!!


def sample(self, model, n):    logging.info(f"Sampling {n} new images....")    model.eval()    with torch.no_grad():        x = torch.randn((n, 3, self.img_size, self.img_size)).to(self.device)        # for i in tqdm(reversed(range(1, self.noise_steps)), position=0):        for i in tqdm(reversed(range(1, 5)), position=0):            t = (torch.ones(n) * i).long().to(self.device)            predicted_noise = model(x, t)            alpha = self.alpha[t][:, None, None, None]            alpha_hat = self.alpha_hat[t][:, None, None, None]            beta = self.beta[t][:, None, None, None]            if i > 1:                noise = torch.randn_like(x)            else:                noise = torch.zeros_like(x)            x = 1 / torch.sqrt(alpha) * (x - ((1 - alpha) / (torch.sqrt(1 - alpha_hat))) * predicted_noise) + torch.sqrt(beta) * noise       model.train()    x = (x.clamp(-1, 1) + 1) / 2    x = (x * 255).type(torch.uint8)    return x
复制代码


上述代码关键的就是 x = 1 / torch.sqrt(alpha) * (x - ((1 - alpha) / (torch.sqrt(1 - alpha_hat))) * predicted_noise) + torch.sqrt(beta) * noise这个公式,其对应着代码流程图中 Sampling 阶段中的第 4 步。需要注意一下这里的跟方差这个公式给的是,但其实在我们理论计算时为 $\sqrt {\frac{{{\beta t}(1 - {{\bar a}{t - 1}})}}{{1 - {{\bar a}t}}}}{\bar a}{t - 1}\bar a_t{\frac{{(1 - {{\bar a}_{t - 1}})}}{{1 - {{\bar a}_t}}}}$当成 1 计算,这里注意一下就好。🍵🍵🍵

代码小结

可以看出,这一部分我所用的篇幅很少,只列出了关键的部分,很多细节需要大家自己感悟。比如代码中时刻 T 的用法,其实是较难理解的,代码中将其作为正余弦位置编码处理。如果你对位置编码不熟悉,可以看一下我的这篇文章的附录部分,有详细的介绍位置编码,相信你读后会有所收获。🌿🌿🌿

参考链接

由浅入深了解Diffusion🍁🍁🍁

附录

高斯分布性质

高斯分布又称正态分布,其表达式为:




其中为均值,为方差。若随机变量服 X 从正态均值为,方差为的高斯分布,一般记为。此外,有一点大家需要知道,如果我们知道一个随机变量服从高斯分布,且知道他们的均值和方差,那么我们就能写出该随机变量的表达式。




高斯分布还有一些非常好的性质,现举一些例子帮助大家理解。


  • ,则

  • ,则


发布于: 2023-07-23阅读数: 41
用户头像

秃头小苏

关注

但凡凭努力就可以做到的事,就算不上困难吧 2022-07-01 加入

掘金签约作者+优秀创作者 3D视觉开发者社区优秀内容博主 C站人工智能领域优质创作者

评论 (3 条评论)

发布
用户头像
您的文章不符合本次征文的主题,请修改或重新投稿,感谢您对本次活动的大力支持
2023-07-24 10:39 · 北京
回复
用户头像
秃头写的真好,一整个明白Diffusion啦

2023-07-23 16:30 · 辽宁
回复
还得是月佬
2023-07-23 16:40 · 辽宁
回复
没有更多了
文本生成图像DALL·E 2背后的原理——Diffusion Model | 社区征文_年中技术盘点_秃头小苏_InfoQ写作社区