大家还记得网上流行的插画变形金刚吗?近日,知名博主JayAlammar也在其博客上写了一张流行的StableDiffusion模型的图解,让你从零开始全面了解图像生成模型的原理,并且还配有超详细的视频讲解!文章链接:https://jalammar.github.io/illustrated-stable-diffusion/视频链接:https://www.youtube.com/watch?v=MXmacOUJUawGraphicalStableDiffusionAI模型最新图像生成能力远超人期望,可以直接根据文字描述制作出具有惊人视觉效果的图像。其背后的运行机制看似非常神秘神奇,但它确实影响着人类创作艺术的方式。StableDiffusion的发布是AI图像生成发展的里程碑,相当于提供了一个面向大众的高性能模型。不仅生成的图像质量很高,运行速度也很快,而且对资源和内存的要求也很低。.相信尝试过AI图像生成的人都会想知道它是如何工作的。本文将揭开StableDiffusion如何为您工作的奥秘。StableDiffusion在功能上主要包括两个方面:1)其核心功能是仅根据文本提示作为输入生成图片(text2img);2)您也可以使用它根据文字描述修改图片(即输入为文字+图片)。下图将用于帮助解释StableDiffusion的组件、它们如何相互作用以及图像生成选项和参数的含义。StableDiffusion组件StableDiffusion是一个由多个组件和模型组成的系统,而不是单个模型。当我们从模型的整体来看模型内部时,我们可以发现它包含一个文本理解组件,用于将文本信息转换为数字表示以捕获文本中的语义信息。虽然目前还是从宏观的角度来分析模型,更多的模型细节会在后面公布,但是我们可以大致推测这个文本编码器是一个特殊的Transformer语言模型(具体来说就是CLIP模型的文本编码器)。模型的输入是一个文本字符串,输出是一个数字列表,用来表示文本中的每一个单词/token,即将每一个token转化为一个向量。然后将此信息提交给图像生成器,图像生成器也包含多个组件。图像生成器主要包括两个阶段:1.图像信息生成器该组件是StableDiffusion的专属配方。与之前的模型相比,它的许多性能提升都在这里实现。该组件运行多个步骤生成图像信息,其中steps也是StableDiffusion接口和库中的一个参数,通常默认为50或100。ImageInformationCreator完全在图像信息空间(或潜在空间)中运行,这使得它比其他在像素空间中运行的Diffusion模型运行得更快;从技术上讲,这个组件由一个UNet神经网络和一个Scheduling(调度)算法组成。扩散这个词描述了这个组件内部运行过程中发生的事情,即信息被一步步处理,最终由下一个组件(图像解码器)产生高质量的图像。2.图像解码器图像解码器根据从图像信息生成器获得的信息绘制一幅图画,整个过程只运行一次,生成最终的像素图像。可以看出,StableDiffusion一共包含三个主要组件,每个组件都有一个独立的神经网络:1)ClipText用于文本编码。输入:文本输出:77个标记嵌入向量,每个包含768个维度2)UNet+Scheduler在信息(潜在)空间中逐步处理/扩散信息。输入:文本嵌入和初始多维噪声数组(结构化数字列表,也称为张量)。输出:一个处理过的信息数组3)AutoencoderDecoder,使用处理过的信息矩阵绘制最终图像的解码器。输入:处理后的信息矩阵,维度为(4,64,64)输出:结果图像,每个维度为(3,512,512),即(red/green/blue,width,height)什么是Diffusion?扩散是下图中粉色图像信息创建器组件中发生的过程。该过程包括表示输入文本的标记嵌入和随机初始图像信息矩阵(也称为潜在)。这个过程还需要用到Imagedecoder来绘制最终图像的信息矩阵。整个操作过程是一步一步的,每一步都会添加更多相关信息。为了更直观地感受整个过程,你可以看一半的随机潜在矩阵,看看它是如何转化为视觉噪声的,这里通过图像解码器进行视觉检查。整个扩散过程包含多个步骤,每个步骤都基于输入的latentsmatrix,生成另一个latentsmatrix,以更好地拟合“输入文本”和从模型图像集中获得的“视觉信息”。可视化这些潜伏显示信息是如何在每个步骤中累加的。整个过程都是从零开始,看起来还蛮刺激的。步骤2和步骤4之间的过程转换看起来特别有趣,仿佛画面的轮廓从噪音中浮现出来。Diffusion的工作原理使用扩散模型生成图像的核心思想仍然是基于现有的强大的计算机视觉模型。只要输入数据集足够大,这些模型就可以学习任意复杂的操作。假设我们已经有了一张图像,生成一些噪声添加到图像中,然后我们就可以把图像当作训练样例。使用相同的操作,可以生成大量的训练样本来训练图像生成模型中的核心组件。上面的示例显示了一些可选的噪声幅度,从原始图像(0级,无噪声)到添加的完全噪声(4级),可以轻松控制向图像添加多少噪声。所以我们可以把这个过程分散成几十个步骤,为数据集中的每张图片生成几十个训练样本。基于以上数据集,我们可以训练出一个性能优异的噪声预测器,每个训练步骤与其他模型的训练类似。噪声预测器在特定配置下运行时会生成图像。去除噪声,绘制图像经过训练的噪声预测器可以对添加噪声的图像进行去噪,还可以预测添加的噪声量。由于采样噪声是可预测的,如果从图像中减去噪声,生成的图像将更接近模型训练的图像。生成的图像并不是精确的原始图像,而是一个分布,即世界的像素排列,比如天空通常是蓝色的,人有两只眼睛,猫有尖耳朵等,生成的特定图像风格完全取决于训练数据集。不仅StableDiffusion通过去噪进行图像生成,DALL-E2和Google的Imagen模型也一样。需要注意的是,到目前为止所描述的扩散过程还没有使用任何文本数据来生成图像。所以,如果我们部署这个模型,它可以生成漂亮的图像,但用户无法控制生成的内容。在接下来的部分中,我们将描述如何将条件文本合并到管道中以控制模型生成的图像类型。Acceleration:Diffusiononcompresseddata为了加快图像生成的过程,StableDiffusion并没有选择在像素图像本身上运行扩散过程,而是选择在图像的压缩版本上运行,也称为“DeparturetoLatentSpace"inthepaper"。整个压缩过程,包括后续对图像的解压和绘制,都是通过一个autoencoder来完成的,autoencoder将图像压缩到一个latentspace中,然后只使用decoder来重构它使用压缩后的信息。前向扩散过程是在压缩的潜层上进行的,噪声切片(slices)应用于潜层上的噪声,而不是像素图像,因此噪声预测器实际上被训练来预测压缩表示(潜在的空间中的噪声)前向传递,即使用自动编码器中的编码器来训练噪声预测器。一旦训练完成,就可以通过运行生成图像反向过程(自动编码器中的解码器)。前向和后向过程如下图所示,图中包含一个conditioning组件,用于描述模型应该生成图像的文本提示。Textencoder:Transformer语言模型模型中的语言理解组件使用Transformer语言模型,可以将输入的文本提示转换为tokenembeddingvectors。发布的StableDiffusion模型使用ClipText(基于GPT的模型)。在本文中,为了方便起见,选择了BERT模型。Imagen论文中的实验表明,与选择更大的图像生成组件相比,更大的语言模型可以带来更多的图像质量改进。早期的StableDiffusion模型使用了OpenAI发布的预训练ClipText模型,但在StableDiffusionV2中转向了新发布的更大的CLIP模型变体OpenClip。CLIP是如何训练的?CLIP需要的数据是图像及其标题,数据集包含约4亿张图像和描述。数据集是从从网络上抓取的图像和相应的“alt”标签文本收集的。CLIP是图像编码器和文本编码器的组合,其训练过程可以简化为获取图像和文本描述,并使用两个编码器分别对数据进行编码。然后使用余弦距离比较生成的嵌入。在刚开始训练的时候,即使文字描述与图片相匹配,它们之间的相似度也一定很低。随着模型的不断更新,编码器对图像和文本编码的embeddings会在后续阶段逐渐趋于相似。通过在整个数据集中重复这个过程,并使用大批量编码器,我们最终能够生成一个嵌入向量,其中狗的图像和句子“pictureofadog”之间存在相似性。就像在word2vec中一样,训练过程也需要包括不匹配图像和说明的负样本,模型需要为其分配低相似度分数。将文本信息输入图像生成过程为了将文本调节作为图像生成过程的一部分,噪声预测器的输入必须适应文本。所有操作都在潜在空间上执行,包括编码文本、输入图像和预测噪声。为了更好地理解文本标记在Unet中是如何使用的,也有必要先了解一下Unet模型。Unetnoisepredictor(notext)中的layer是一个不使用text的diffusionUnet,它的输入输出如下:模型内部,可以看到:1.Unet模型中的layer主要用来转换潜伏;2.每一层都对前面层的输出进行操作;3.一些输出(通过残差连接)将其馈送到网络稍后的处理中4.将时间步长转换为时间步长嵌入向量,可以在层中使用。Unet噪声预测器中的层(带有文本)现在需要将以前的系统改造为文本版本。修改的主要部分是添加对文本输入(术语:文本条件)的支持,即在ResNet块之间添加一个注意力层。需要注意的是,ResNetblock并没有直接看到文本内容,而是通过attentionlayer将文本在latents中的表示结合起来,然后下一个ResNet就可以在这个过程中使用文本信息。
