前言
给一个提示词, Midjourney, Stable Diffusion 和 DALL-E 可以生成很好看的图片,那么它们是怎么工作的呢?它们都用了 Diffusion models(扩散模型) 这项技术。
Diffusion models 正在成为生命科学等领域的一项尖端技术,例如, Diffusion models 可以生成分子用于药物发现。
这篇文章,我们会谈到当前扩散模型的发展状态和能力。
我们将从理解sampling process(采样过程)开始,从纯噪声开始并逐步改进它以获得最终的好看的图像。我们将
建立必要的编程技能来有效地训练扩散模型。我们将学习如何构建能够预测图像中噪声的神经网络。我们将向模型添加上下文,以便可以控制它生成的位置。最后,通过实施高级算法,你将学习如何通过10倍的因数加速采样过程。
对扩散模型直观的理解
首先我们将讨论扩散模型的目标,然后我们将讨论你拥有的不同精灵的训练数据如何对这些模型有用,然后我们将讨论如何在这些数据上训练模型本身。
扩散模型的目标是什么?你有很多训练数据,比如你看到的这些精灵图像,这些是你的训练数据集。你想要的是你想要更多的这些精灵,它们没有在你的训练数据集中表示出来。你可以使用一个神经网络,它可以为你生成更多的这些精灵,遵循扩散模型的过程。
那么,我们如何使这些图像对神经网络有用呢?好吧,你希望神经网络能够普遍地学习精灵的概念,它是什么。这可能是更细致的细节,比如精灵的头发颜色,或者它腰带上的扣子。但它也可能是一般的轮廓,像它的头和身体,以及其中的一切。做到这一点的一种方式,强调更细致的细节或一般轮廓的方式,实际上是添加不同级别的噪声。所以这只是向图像中添加噪声,它被称为“增噪过程”。
这是受到物理学启发的。你可以想象一滴墨水滴入一杯水中。最初,你确切地知道墨水滴在哪里落下。但随着时间的推移,你实际上会看到它扩散到水中,直到它消失。这里的想法是一样的,你从“鲍勃精灵”开始,当你添加噪声时,它会逐渐消失,直到你不知道它实际上是哪个精灵。那么当你逐渐向图像中添加更多噪声时,神经网络究竟应该在每一个噪声级别上想些什么呢?当它是“鲍勃精灵”时,你希望神经网络会说,“是的,那是鲍勃精灵”。保持鲍勃的样子,就是一个精灵。如果可能是鲍勃,那么你可能希望神经网络会说,“你知道,这儿有些噪声。”。提出一些建议的细节,使其看起来像“鲍勃精灵”。如果现在它只是一个精灵的轮廓,那么你只能感觉到这可能是一个精灵人物,但它可能是鲍勃或者弗雷德,甚至可能是南希,那么你想要为可能的精灵提出更一般的细节。所以或许你会根据这个为鲍勃提出一些建议的细节,或者你会为弗雷德提出一些细节。最后,如果你一无所知,如果它看起来完全像什么都没有,你仍然希望它看起来更像一个精灵。你仍然希望神经网络会说,“你知道吗,我还是要把这个完全噪声的图像变成某种稍微像精灵的东西,通过提出一个精灵可能看起来的轮廓。”
那么现在开始训练那个神经网络吧。它要学会处理不同的噪声图像并将它们转换回精灵图像。这就是你的目标。 它是如何做到这一点的呢?它学会了去除你添加的噪声。 从“毫无头绪”级别开始,那里只有纯粹的噪声, 然后开始让它看起来好像可能有一个人在那里,变得像弗雷德一样,最终成为一个看起来像弗雷德的精灵。“毫无头绪”级别的噪声非常重要,因为它是正态分布的。 我的意思是,这些像素中的每一个都是从一个正态分布中抽样得到的,也就是所谓的 “高斯分布”或“钟形曲线”。所以当你想要请求神经网络生成一个新的精灵,比如这里的弗雷德,你可以从那个正态分布中抽样噪声, 然后你可以通过神经网络逐渐去除那些噪声,得到一个全新的精灵。现在你已经达到了你的目标。你甚至可以得到更多的精灵,超出了你所训练过的所有精灵。
采样(推理)
现在我们讨论采样。我们将深入了解其细节以及它是如何在多次迭代中工作的。 在我们讨论如何训练这个神经网络之前,让我们谈谈采样,或者我们在训练完成后在推理时如何使用神经网络。 所以发生的事情是你有了那个噪声样本。 你将其通过你的训练有素的神经网络 它已经理解了精灵的样子 它所做的是预测噪声。它预测噪声 而不是精灵,然后我们从噪声样本中减去 预测出的噪声,以得到更像精灵的东西。 现实情况是,这只是噪声的预测 它并没有完全去除所有噪声,所以你需要 多个步骤来获得高质量样本。经过 500次迭代后,我们能够得到看起来 非常像精灵的东西。所以现在让我们从算法上逐步了解这个过程。
首先,你可以采样一个随机噪声 样本,现在我们从最初的 噪声开始。 然后你想要逆着时间走,实际上你是 从最后一次迭代,500次,那时是完全噪声状态,一直 回到第一次。只需想象你的墨水滴。你实际上是 在时间上倒退。它最初是完全扩散的 然后你正在回到 最初墨水滴入水中的那一刻。
你实际上将原始噪声,那个样本,再次传回你的神经网络, 然后你会得到一些预测噪声。这个预测噪声是经过训练的神经网络想要从原始噪声中减去的,以得到看起来更像 精灵的东西。 最后,有一个叫做“DDPM”的采样算法,意为 去噪扩散概率模型, 一篇由 Jonathan Ho, Ajay Jain 和 Pieter Abbeel 所写的论文(https://arxiv.org/abs/2006.11239)。 这个采样算法本质上能够 得到一些用于缩放的数字。这不是特别重要,但重要的是 这是你实际上从 原始噪声样本中减去预测噪声的地方。而且你又添加那一点额外的噪声回去。
好的,现在我们讨论那额外的噪声。现在你的神经网络在预测你原始噪声样本中的噪声。你将它减去,得到更像精灵的东西。但这个神经网络期望输入的是正态分布的噪声样本。去噪后,样本的分布就不再是这样了。因此,你需要在每一步之后和下一步之前,添加根据当前时间步骤缩放的额外噪声,作为下一次迭代的输入。实际上,这有助于稳定神经网络,防止它仅产生接近数据集平均值的结果。如果我们不把噪声加回去,神经网络只会产生这些平均的精灵团块;而当我们加回噪声时,它才能够创造出美丽的精灵图像。
神经网络架构 UNet
接下来我们将讨论神经网络、其架构以及我们如何将额外信息整合到其中。我们用于扩散模型的神经网络架构是一个UNet。你需要知道的最重要的事情是,UNet以这张图片作为输入,并输出一个与该图片大小相同的东西,但这里它预测的是噪声。UNet已经存在很长时间了,自2015年起就有了,并且它首次被用于图像分割。它最初是用来将图像准确分割成行人或汽车的,因此它在自动驾驶汽车研究中被广泛使用。但UNet特别之处在于其输入和输出是同样的大小。它所做的首先是将关于这个输入的信息进行嵌入,通过许多卷积层来下采样,将所有信息压缩到一小块空间中。然后它通过同样数量的上采样块将输出重新上采样完成它的任务。在这个案例中,任务是预测被应用到这张图片上的噪声。而这个预测的噪声与原始输入图像的尺寸相同,是16x16x3的维度。关于这个UNet的另一个优点是它可以接收额外的信息。所以它压缩了图像以理解发生了什么,但它也可以接收更多信息。那么我们想要包含哪些信息呢?嗯,对于这些模型来说一个非常重要的事情是时间嵌入。所以这是一个告诉模型时间步长的嵌入,因此知道我们需要什么样的噪声水平。而你所需要做的关于这个时间嵌入就是将它嵌入到某种向量中,并且你可以将它添加到这些上采样块中。
另一条有用的信息是上下文嵌入。上下文嵌入所做的就是帮助你控制模型生成的内容。例如,一个文本描述,就像你真的希望它是Bob,或者某种因素,比如它需要是特定的颜色。在上采样块中,你将上下文嵌入与上采样块相乘,然后添加时间嵌入。我们稍后会更多地讨论这个问题。
训练神经网络
现在,我们将讨论如何训练这个UNet神经网络并让它预测噪声。因此,神经网络的目标是预测噪声,并且它确实学习了图像上噪声的分布,但也学习了什么不是噪声,什么是精灵的相似性。我们做这个的方法是,我们从我们的训练数据中取一个精灵,并实际向其添加噪声。我们给它添加噪声,然后交给神经网络,并要求神经网络预测那个噪声。然后我们比较预测的噪声和添加到那个图像上的实际噪声,这就是我们如何计算损失的。
然后通过神经网络进行反向传播,于是神经网络就学会更好地预测那个噪声。那么你怎么确定这里的噪声是什么呢?你可以通过时间采样并给予不同的噪声水平。但实际上,在训练中,我们不希望神经网络一直看同一个精灵。如果它在一个epoch中观察不同的精灵,它会更稳定,而且更加均匀。所以实际上我们所做的是我们随机采样这个时间步骤可能是什么。然后我们获得适合那个时间步骤的噪声水平。我们将它添加到这个图像上,然后让神经网络预测它。我们取我们训练数据中的下一个精灵图像。我们再次随机采样一个时间步骤。它可能和你在这里看到的完全不同。然后我们将它添加到这个精灵图像上,并再次让神经网络预测添加的噪声。这样就产生了一个更稳定的训练方案。那么实际的训练是什么样子的呢?这里是一个巫师帽精灵,这里是噪声输入看起来的样子。
当你首次在第0个epoch将它放入神经网络时,神经网络还没有真正学会什么是精灵。所以预测的噪声并没有真正改变输入的样子,而当它被减去后,它实际上就变成了这个样子,看起来差不多。但到了第31个epoch,神经网络对这个精灵的样子有了更好的理解。然后它预测噪声,然后从这个输入中减去这个噪声,生成了类似这个巫师帽精灵的东西。
很酷,所以那是一个样本。这是针对多个不同的样本,多种不同的精灵,在许多个时期中,看起来是什么样的。正如你可以在这个第一个epoch中看到的,它与精灵相去甚远,但是到了这里的第32个epoch甚至在那之前,它看起来很像小型视频游戏角色。
控制模型的生成内容
下面,你将学习如何控制模型和它生成的内容。 对许多人来说,这是最令人兴奋的部分,因为你可以告诉模型你想要的内容,然后它可以为你想象出来。 当谈到控制这些模型时,我们实际上想要使用嵌入(embeddings)。嵌入是什么呢?我们在前面已经稍微了解了一下时间嵌入和上下文嵌入,嵌入就是向量,它们是能够捕获含义的数字。这里它捕获了这个句子或者这个笑话的含义,也许是通过扩散模型。"布朗运动体经常碰撞到彼此"。所以它将这个含义编码成嵌入,即这一组向量中的数字。 嵌入特别的地方在于它们能够捕获语义含义,因此内容相似的文本将具有相似的向量。而嵌入神奇的一点是你几乎可以用它进行向量算术。例如“巴黎 - 法国 + 英格兰 = 伦敦嵌入”。好的,那这些嵌入是如何在训练期间真正成为模型上下文的呢?这里,你有一个鳄梨的图片,你希望神经网络去学习,你也为它提供了一个标题,一个成熟的鳄梨。你实际上可以通过这个过程,得到一个嵌入,并将其输入神经网络,然后预测添加到这个鳄梨图片上的噪声,接着计算损失并做之前相同的事情。
你可以在许多不同的带有标题的图片上应用这个方法。这里有一个舒适的扶手椅。你可以将其通过一个嵌入,传入模型,并作为训练的一部分。 现在,这个部分的魔力在于,虽然你能从互联网上抓取带有这些标题的鳄梨和扶手椅的图片,但在推理时,你能生成模型之前从未见过的东西。那可能是一个“鳄梨扶手椅”。这一切之所以神奇,是因为你可以将“鳄梨扶手椅”这些词嵌入到包含了一些鳄梨和一些扶手椅的嵌入中,将其通过神经网络,让它预测噪声,然后去除这些噪声,你看,就出现了一个“鳄梨扶手椅”。 更广泛来说,上下文是一个可以控制生成的向量。正如我们现在所见,上下文可以是那个“鳄梨扶手椅”的文本嵌入,那是很长的。但是上下文不必非要那么长。上下文还可以是五个不同类别的长度,你知道的,五个不同维度,比如设定为英雄或非英雄,就像这些火球和蘑菇这样的对象。它可以是食物项目,你知道的,苹果、橙子、西瓜。它可以是像这个弓箭或者这个蜡烛这样的咒语和武器。最后,它可能是这些精灵是侧面还是正面。
加速采样方法
下面我们将了解到一种新的采样方法,它比我们迄今为止使用的DDPM高效10倍以上。这种新方法被称为DDIM。
您的目标是希望获得更多的图片,并且希望快速获得。但是到目前为止,采样过程一直很慢,因为一来,涉及许多时间步骤,您知道的,有500个,有时甚至更多,以获得一个好的样本,每一个时间步骤还依赖于前一个步骤。它遵循马尔可夫链过程。
不过值得庆幸的是,现在有许多新的采样器来解决这个问题,因为这一直是扩散模型的一个长期问题。问题在于您可以训练它们,它们能创造出既多样又逼真的美丽图像,但是从它们那里得到结果却非常缓慢。而这些采样器中一个非常受欢迎的叫做DDIM,或者叫去噪扩散隐式模型(Denoising Diffusion Implicit Models)。
这篇论文是由Jiaming Song、Chenlin Meng和Stefano Ermon撰写的。DDIM之所以更快,是因为它能跳过时间步骤。所以它不是从时间步骤500到499再到498,而是能跳过所有这些时间步骤。它能跳过相当多,因为它打破了马尔可夫假设。
马尔可夫链只用于概率过程。但DDIM实际上从这个采样过程中移除了所有的随机性,因此它是确定性的。它本质上所做的就是预测最终输出的粗略草图,然后用去噪过程进行细化。
现在有了这种更快的采样方法(DDIM),你不会总是得到跟运行DDPM一样的质量水平。但这些实际上看起来相当不错。
从经验上看,人们发现,例如,对于一个在这500步骤上训练的模型,如果你采样500步,DDPM会表现得更好。但对于任何小于500步的数字,DDIM会做得更好。
总结
到此我们学习了扩散模型的基础知识。 现在,把所有内容汇总起来,你能够训练一个扩散模型来预测噪声,并且迭代地从纯噪声中减去预测噪声,以获得一幅好的图像。 你能够从那个训练过的神经网络中快速采样图像,而且还用了一个更高效的采样器,叫做DDIM。 你了解了模型架构,一个UNet。 你向模型中添加了上下文,这样你就能决定你是想要食物、魔法还是英雄精灵,或者介于两者之间的某种古怪的东西。扩散模型也不仅限于图像,那只是它们最受欢迎的领域。还有用于音乐的扩散模型,你可以给它任何提示并得到音乐,用于提出新分子以加速药物发现。 你还可以尝试一个更大的数据集,尝试一个新的采样器。 实际上有很多采样器比DDIM更快更好。 你能够用这些模型做更多事情,比如内画法,即让扩散模型在你已有的图片周围绘制一些东西,以及文本反演,它使模型能够只用几个样本图像捕捉一个全新的文本概念。 你在这里了解了基础知识,基础原理。 在这个领域还有其他重要的发展。 例如,稳定扩散使用了一种叫做潜在扩散的方法,它直接在图像嵌入上操作,而不是直接在图像上,使得过程更加高效。其他值得一提的酷炫方法包括交叉关注、文本条件化和无分类器引导。
研究社区仍在努力研究更快的采样方法,因为在推断时间上它仍然比其他生成模型慢。总而言之,这对扩散模型来说是一个极其激动人心的时期,因为它们作为一个整体生成模型,它们的应用变得越来越广泛。
参考资料和更多学习参考网页
文中图片来自于课程 https://learn.deeplearning.ai/courses/diffusion-models ,内容也来自于对该课程的学习。
关于扩散模型,更多学习可以参考下面网页:
https://huggingface.co/docs/diffusers/v0.17.0/en/api/schedulers/ddpm
https://huggingface.co/docs/diffusers/v0.17.0/en/index
What is Stable Diffusion? - Stable Diffusion AI Explained - AWS