使用 Stable Diffusion 进行时间场景生成
1. 引言
本博客报告详细介绍了我们如何执行和实现了深度学习期末项目 **“使用 Stable Diffusion 进行零样本时间场景生成”**。本报告详细解释了我们在此过程中采取的每一个步骤,这些步骤是经过数天数小时的反复试验才获得的。在该项目中,我们实现了两个管道:Stable Diffusion 1.5 管道和 Stable Diffusion XL 管道,它们都输出一组图像,可用于:电影/卡通场景生成、社交故事生成等。基于这些场景,可以使用 Stable Video Diffusion 生成视频,然后进行合并。
本项目使用的资源:
- Google Colab Pro+ 帐户(50 美元)
- ChatGPT 4 订阅,含 20 个 API 积分(20 美元)
- Google Drive 100 GB 存储空间(3 美元)
以下几点概述了我们在此项目中完成的主要工作:在此项目中,我们使用了 2 个管道
- 在第一个管道中,我们使用了基础 Stable Diffusion 1.5 模型(**runwayml/stable-diffusion-v1-5**),我们对特定角色执行了 **DreamBooth**,并将其与**文本反演**相结合以训练特定风格,并集成了**交叉注意力控制**以创建时间上一致的图像。
- 在此管道中,我们使用了新发布的(23 年 7 月 18 日)Stable Diffusion XL 模型,并使用 **LoRA** 技术对其进行了特定字符训练,并将其与 **CivitAI** 的预训练检查点融合。
本项目背后的动机/目标是创建一个管道,该管道将生成一组一致的图像,这些图像随后可用于生成故事板、动画电影卡通场景、儿童故事等。
在上述两个管道中,我们都集成了 **ChatGPT API** 来为所需图像生成提示和标题。标题会自动输入到模型中,模型会输出图像以及图像下方的标题。
除了 Stable Diffusion XL,我们还使用了 Stable Diffusion 1.5,因为它更轻巧,并且在 DreamBooth、文本反演、控制网络等多个论文中都有官方实现,并且可以在其之上找到许多预训练的检查点。
以下是两个管道的图片
Stable Diffusion 1.5 管道
SDXL 管道
在第 2 章中,我们将介绍本项目中使用的每种技术的工作原理,从第 3 章开始,我们将展示实现细节
以下是我们模型生成的一些图像。我们所有的模型都可以在 **HuggingFace** 上找到,**所有代码(微调/图像生成)都在此 Github 仓库中**,生成的图像可以在 **CivitAI** 配置文件以及笔记本中找到。
我们模型生成的图像
2. 工作原理
a. 扩散模型
深度学习中的扩散模型代表了一类生成模型,它利用扩散过程的概念来模拟复杂的数据分布。这些模型因其生成高质量样本和执行图像合成和去噪等任务的能力而获得了突出地位。一个值得注意的扩散模型是变分扩散自编码器(VDAE),它结合了变分自编码器(VAE)原理和扩散过程,以改进生成建模。
扩散模型将狗图像转换为噪声并返回的阶段。
从数学上讲,扩散模型的生成过程可以表示如下。
设 $x_t$ 表示时间 $t$ 的数据, $z$ 表示潜在变量。扩散过程可以建模为一系列转换
其中 $\epsilon_t$ 是单位高斯噪声,$\sigma(t)$ 是一个比例函数,$\beta$ 控制扩散速率。初始数据点假定从标准高斯分布等简单分布中采样。
以下潜在变量模型用于将扩散过程与变分自编码器集成
其中 g(z) 是将潜在变量映射到初始数据点的解码器网络。
扩散过程的每一步观察到数据 xt 的可能性由下式给出
目标是最大化观测数据的边际似然
该目标可以通过变分下界进一步增强,结合编码器网络 q(z∣x0)。训练 VDAE 的最终目标变为
总而言之,深度学习中的扩散模型将变分自编码器的能力与扩散过程的优雅结合起来,以捕捉复杂的数据分布。潜在变量的集成使模型能够生成多样化和真实的样本,同时通过优化变分下界促进高效训练。
b. 稳定扩散
扩散模型在从复杂数据分布中合成高质量样本方面发挥着关键作用。然而,传统的扩散模型在生成过程中可能会遇到与稳定性相关的问题。稳定扩散模型(SDM)被提议作为一种解决方案,它结合了稳定性机制以增强收敛性和鲁棒性。
稳定扩散模型的核心在于对扩散过程进行修改以确保稳定性。每个时间步 $t$ 的生成过程定义如下
其中 $\epsilon_t$ 是单位高斯噪声,$\sigma(t)$ 是一个比例函数,$\beta$ 控制扩散速率。初始数据点假定从标准高斯分布等简单分布中采样,并且“稳定性项”确保扩散过程中的稳定性。稳定性项的具体公式取决于所选的稳定性准则。
稳定扩散模型的架构由编码器、解码器和稳定性模块组成。编码器网络将观察到的数据 x0 映射到潜在变量 z,而解码器从潜在变量重建数据。
稳定性模块包含额外参数,在扩散过程中动态调整稳定性项以保持稳定性。稳定性模块引入了额外的潜在变量,这些变量有助于生成过程中的稳定性。这些额外的潜在变量与主要潜在变量一起进行优化,从而增强模型捕获数据分布中复杂依赖关系的能力。
稳定扩散模型的训练目标是最大化观测数据的边际似然,同时考虑稳定性项和额外的潜在变量。目标函数通过变分下界进行增强,从而可以通过优化实现高效训练。
c. Stable Diffusion XL
Stable Diffusion XL (SDXL) 是图像生成领域的一项重大进展,它建立在 Stable Diffusion 成功的基础上。它采用了更大的 U-Net 模型,拥有 26 亿个参数,可实现更精细的细节和更复杂的图像。SDXL 采用了 Transformer 块的异构分布,优化了学习过程并提高了图像保真度。
SDXL 通过利用更大的文本条件编码器 `OpenCLIP ViT-bigG` 和额外的文本编码器 `CLIP ViT-L` 在文本到图像生成方面表现出色,可以准确地将文本描述转换为视觉元素。它还引入了新颖的条件技术,如大小条件、裁剪条件和多方面条件,这些技术可以优化图像生成过程。
SDXL 还集成了一个专门的细化模型,用于处理高分辨率图像生成。该模型擅长捕捉微小的局部细节并提高整体图像质量,确保即使是最高分辨率的输出也能保持清晰和视觉吸引力。这些进步促成了 SDXL 在图像生成方面的卓越性能。
现在,让我们深入了解 SDXL 的数学公式。该模型可以表示如下
其中 $\nabla H_l$ 表示损失相对于第 l 层输出的梯度,* 表示元素级乘法。超参数 $\alpha$ 控制自扩散的强度。
交叉层扩散通过允许信息在相邻层之间流动来建模
其中 $\beta$ 是控制交叉层扩散强度的超参数。
SDXL 模型的整体目标函数可以公式化为原始损失函数与自扩散和交叉层扩散项的组合
其中 $\gamma$ 是正则化参数,$\nabla H_l |_2$ 惩罚梯度的幅值,鼓励更平滑的信息流。
这个数学公式展示了 SDXL 如何融合自扩散和交叉层扩散机制,以增强梯度流并改善深度神经网络的训练动态。研究人员发现,集成此类扩散模型可以带来更稳定和高效的训练过程,有助于在各种任务中实现更好的泛化性能。
d. DreamBooth
DreamBooth 通过改变模型本身的结构来工作。我们需要关注两个输入,第一个是我们想要训练的图像,第二个是包含唯一标识符的句子。
DreamBooth 训练模型将唯一标识符与要训练的图像概念关联起来。句子被转换为文本嵌入,其中每个词都由一个包含该词语义信息的向量表示。
一个向量包含每个词的信息,并且概念(图像)与没有意义的词的新向量关联起来。
我们传入文本嵌入,然后对样本图像应用噪声,直到其具有足够的噪声,然后减少一点噪声以创建另一个图像。之后,我们尝试让模型接收噪声较多的图像并输出噪声较少的图像。输出与噪声较少的图像使用损失函数进行比较,然后执行梯度更新(如果损失高,则惩罚模型;如果损失低,则奖励模型)。
创建一个全新的模型,因为我们会更改模型的内部结构,直到它学习到这个概念。
这是最常见和最有效的方法,然而,它的存储效率很低,因为每次我们使用 DreamBooth 都会有一个新模型,并且在单个模型上训练多个概念可能会使其混淆。
DreamBooth 训练过程图,用于个性化图像生成,具有超分辨率和特定类别损失组件。
DreamBooth 模型基于条件生成对抗网络(cGAN)架构,该架构由生成器网络 G 和判别器网络 D 组成。生成器将文本描述 t 和一组输入图像 I 作为输入,并生成输出图像 O。判别器网络 D 将图像和文本描述对作为输入,并学习区分真实图像和文本条件生成的图像。
生成器网络 G 经过训练,以最大化生成图像 O 被判别器 D 正确分类为真实的概率,而判别器 D 经过训练,以最大化正确分类真实图像的概率,并最小化错误分类生成图像的概率。
cGAN 的目标函数可以表示为
其中 I 表示输入图像,t 表示文本描述,G(t,I) 表示生成的图像,E 表示期望值。
- 函数 $\mathbb{E}_{I,t} [\log D(I, t)]$ 在给定条件输入 t 的情况下,最大化判别器正确识别真实图像的能力。
- 函数 $\mathbb{E}_{t} [\log(1 - D(G(t, I)]$ 在给定条件输入 I 的情况下,最大化生成器创建能够欺骗判别器的图像的能力。
cGAN 架构使得 DreamBooth 模型能够生成以特定文本描述和输入图像为条件的图像,从而实现高度可定制和个性化的图像生成。
e. 文本反演
它类似于 DreamBooth,但区别在于梯度更新并非发生在模型中,而是发生在向量中,向量会逐渐接近所需的视觉现象,最终我们将拥有可以完美描述所需图像的向量。文本反演的优点是输出不是像 DreamBooth 那样的新模型,而是一个微小的额外嵌入。因此,它比 DreamBooth 更节省存储空间,任何人都可以轻松下载该嵌入并将其插入到他们的模型中,从而获得所需的图像输出。
因此,只需使用一个完美的向量,我们就可以生成任何任意的视觉现象。然而,DreamBooth 比文本反演更有效,如果您有至少 12GB 的显存可用,DreamBooth 是一个可行的选择。
模型架构
所提出的文本反演模型架构由几个关键组件组成。
令 $x$ 表示输入文本序列,$Y$ 表示相应的图像输出。该架构的核心组件包括
分词器: 分词器将输入文本序列处理成标记,以便进一步处理。
$T(x) = {t_1, t_2, ... t_n }$ 其中 $x$ 是输入文本,$T$ 是分词器,$t_1$ 是标记。
嵌入查找: 嵌入查找操作将分词后的输入映射到连续的向量表示。
$v_i=E(t_i)$ 其中 E 是嵌入矩阵,vi 是标记 **ti 的嵌入。
文本转换器: 文本转换器模块将向量序列转换为中间表示。
$h = T_x(v_1, v_2, .., v_n)$ 其中 Tx 是文本转换器,h 是最终文本表示。
概念标记: 概念标记 C 嵌入到模型中,以便根据用户定义的概念进行个性化图像生成。
潜在空间:潜在空间 Z 捕捉输入文本和概念标记的底层特征。$z^* = argmin_zL(G(z), x)$ 其中 G 是图像生成器,z 是潜在代码,L 是损失函数。
图像生成:$I = G(z^*)$ 其中 $I$ 是生成的图像。
文本反演架构
f. LoRA
LoRA 代表低秩适应。在 DreamBooth 中,我们试图向模型教授一个新概念(我们训练和更新模型,直到它学习到新概念),直到我们得到一个新模型。通过 LoRA,我们可以在不创建模型新副本的情况下向模型教授一个新概念。LoRA 最初用于 LLM(大型语言模型),这些模型以拥有数十亿参数而闻名。当我们想要向模型教授一个新子任务时,为 LLM 创建一个新模型实际上是不可行的。因此 LoRA 在模型中插入了新层。下图显示了具有 LoRA 层的神经网络图(上图,橙色层为 LoRA 层),以及没有 LoRA 层的下图。
默认情况下,LoRA 层设置为完全不影响模型。然后随着训练在损失中进行,我们更新中间 LoRA 层,以便它们在信息通过时输出不同的值。一旦中间层得到足够的更新,它们最终将能够理解新概念。因此,LoRA 类似于 DreamBooth,但我们不是像 DreamBooth 那样更新权重,而是添加新权重并更新这些新权重以实现完全相同的效果。
LoRA 训练比 DreamBooth 快得多,并且占用内存少得多。此外,由于 LoRA 层非常小,我们可以更轻松地将它们传递和添加到不同的模型中并共享它们,而不是整个模型。
模型架构
LoRA (低秩适应) 模型是一种用于使预训练语言模型适应特定任务或领域的技术。它通过在模型的注意力机制中引入一个低秩矩阵来实现这一目标,这使得模型能够在不显著改变整体架构的情况下学习任务特定的表示。
给定一个具有注意力机制的预训练语言模型,我们引入一个低秩矩阵 $L \space \epsilon \space R^{d*r}$ 和一组任务特定向量 $v_1,v_2...v_n$,其中 d 是注意力键和值向量的维度,r 是低秩矩阵的秩,n 是任务特定向量的数量。
我们修改注意力机制如下
其中 Q、K 和 V 分别是查询向量、键向量和值向量,$v_1,v_2...v_n$ 是任务特定向量。
低秩矩阵 L 和任务特定向量 $v_1,v_2...v_n$ 在特定任务或领域上进行微调时学习。
DreamBooth、LoRA、文本反演和超网络的比较
由于我们没有在项目中尝试超网络,所以在此博客中跳过它。
3. SD 1.5 管道
尝试 DreamBooth
这或许是我们项目中最具挑战性的部分。为了训练我们管道中的角色,我们选择了 DreamBooth,因为它被认为是微调稳定扩散性能最佳的方法。为了实现 DreamBooth,我们多次在不同的笔记本和技术之间切换。我们尝试了几种 DreamBooth 的实现,其中包括 Hugging Face 的实现 github.com/huggingface/diffusers、TheLastBen、ShivamShrirao、Kohya ss 和 fastDreamBooth 等笔记本。对我们而言,TheLastBen 的笔记本被证明是最直接的实现。然而,Hugging Face 的实现提供了更多的自定义选项,同时也很简单(无需生成图像标题/实例组织等)。我们从学习率 1e-5 开始,这导致模型严重过拟合,并且只输出了输入的图像。事实证明,这对于 DreamBooth 来说太高了。在浏览 Stable Diffusion 的 Reddit 子版块 r/StableDiffusion 后,我们了解到 Stable Diffusion 极易过拟合,并且 e-7 级别的学习率对于 DreamBooth 来说很常见。此外,大量的类别图像会导致模型严重欠拟合。我们首先训练了 14 张《功夫熊猫》中阿宝角色的图像,使用令牌 phtmejhn
用于其识别。并且尝试了许多参数。我们从互联网上下载了图像,并从电影中转换了一些图像,将它们全部转换为单一格式(jpg/png),并使用 birme.net 调整了大小。尽管 Hugging Face 的实现提供了分桶选项,但我们还是选择了调整图像大小。
以下是我们在此项目中学习到的几点经验:
- 学习率 <= 1e-6 给了我们不错的模型。我们得到的最好的功夫熊猫模型学习率为 2e-6。
- 每个实例类别有 10 张类别图像。此外,我们选择了使用 dreambooth 自动生成类别图像(因为很难找到 10*14 = 140 张熊猫图像)。这也使我们能够尝试不同的数字,因为 Hugging Face 的实现提供了为我们生成类别图像的选项。我们还了解到,这种方法可能适用于真实人脸,但对于动画角色来说并不是最好的方法,因为在 dreambooth 训练期间生成的类别图像是真实熊猫的图像,导致了非常高的正则化。
- 最大步数 = 100 对我们来说效果很好。我们曾尝试高达 3000+ 的步数,但这导致了高度过拟合的模型。
- 我们从结果(以及 r/StableDiffusion)中了解到,先验保留在避免过拟合方面非常有用(我们将其保留为默认值 1),并且训练文本编码器也带来了更好的结果(我们也使用了默认值 350)。
- 我们还了解到,对于动画图像(至少对于 Stable Diffusion 1.5 而言),需要 >=75 个推理步骤才能完全生成。我们通常观察到面部会形成多边形网格。
- 此外,对于动画角色,较低的引导比例(4-6)在推理时效果更好,而对于真实人脸,7-9 效果很好。
- 我们确实使用了 8 位 Adam,因为它导致训练更快,并且我们没有观察到结果有显著下降(我们也很注意我们的 GPU 单元)。
- 负面提示词在获得所需结果方面起着关键作用并产生显著影响。对于提示词,我们发现这份指南非常有帮助 https://www.reddit.com/r/StableDiffusion/comments/17qe7v1/sdxl_prompt_best_practices_to_guide_chatgpt/
对于这个项目,我们制作了 20 多个模型,其中大部分都上传到了 Hugging Face(好的和坏的都有)。
欠拟合模型结果
然而,经过几次迭代后,我们得到了以下结果。训练这个模型在 V100 GPU 上耗时 2 小时(包括类别图像生成)。该模型已上传到 Bilal326/PO_KungfuPanda_DB
结果
这些是我们首次成功的 DreamBooth 结果
训练脚本(Hugging Face 实现)
在解决了很多 bug 和文档冲突后,我们发现以下代码有效
!git clone https://github.com/huggingface/diffusers
%cd diffusers
!pip install -e .
%cd /content/diffusers/examples
!pip install -r /content/diffusers/examples/dreambooth/requirements.txt
!accelerate config default
!pip install bitsandbytes
MODEL_NAME="frankjoshua/toonyou_beta6"
INSTANCE_DIR="/content/drive/MyDrive/DL_Project/Flynn_19"
CLASS_DIR="/content/drive/MyDrive/DL_Project/Flynn_DB/T3/class_images"
OUTPUT_DIR="/content/drive/MyDrive/DL_Project/Flynn_DB/T3"
!accelerate launch /content/diffusers/examples/dreambooth/train_dreambooth.py \
--pretrained_model_name_or_path=$MODEL_NAME \
--train_text_encoder \
--instance_data_dir=$INSTANCE_DIR \
--class_data_dir=$CLASS_DIR \
--output_dir=$OUTPUT_DIR \
--with_prior_preservation --prior_loss_weight=1.0 \
--instance_prompt="a photo of fljsdhn man" \
--class_prompt="a photo of man" \
--resolution=512 \
--train_batch_size=1 \
--use_8bit_adam \
--gradient_checkpointing \
--learning_rate=5e-6 \
--lr_scheduler="constant" \
--lr_warmup_steps=0 \
--num_class_images=3600 \
--checkpointing_steps=600 \
--max_train_steps=2400
Dreambooth 输出的模型大小在 3-12 GB 之间,因此我们认为有必要购买 100 GB 的 Google Drive 存储空间。我们在训练过程中使用了检查点步骤来保存可能产生最佳结果的训练步骤。对于推理,我们发现安装 autotrain-advanced 会为我们安装大多数库(如 xformers、diffusers、accelerate 等),之后我们可以直接进行推理。对于 dreambooth 模型的推理,我们使用了以下代码:
from diffusers import DiffusionPipeline, UNet2DConditionModel
from transformers import CLIPTextModel
import torch
unet = UNet2DConditionModel.from_pretrained("/content/drive/MyDrive/DL_Project/flyn_model_hf_5/checkpoint-5000/unet")
text_encoder = CLIPTextModel.from_pretrained("/content/drive/MyDrive/DL_Project/flyn_model_hf_5/checkpoint-5000/text_encoder")
pipeline5000 = DiffusionPipeline.from_pretrained(
"runwayml/stable-diffusion-v1-5", unet=unet, text_encoder=text_encoder, dtype=torch.float16,
).to("cuda")
但当我们没有检查点时,我们可以直接从驱动器加载文件夹,像这样:
pipelinef = DiffusionPipeline.from_pretrained(
"/content/drive/MyDrive/DL_Project/flyn_model_hf_3", torch_dtype=torch.float16
).to("cuda")
而为了生成图像,我们使用了以下代码:
prompt = "a phtmejhn panda "
generator = torch.Generator("cuda").manual_seed(1)
image = pipeline(prompt=prompt,
negative_prompt = negative_prompt,
guidance_scale = 5, generator=generator, num_inference_steps=100)
image = image.images[0]
image
一开始,我们针对各种种子值,每个提示词生成了 10 张图像,以便更好地评估模型的性能和提示词的质量。我们还发现,一些笔记本(如 fastDreambooth)以 ckpt 格式输出模型,这需要在推理之前转换为 diffusers 格式。为此,我们使用了 huggingface/diffusers 页面中的 convert_original_stable_diffusion_to_diffusers 脚本。代码如下:
!pip install autotrain-advanced
!wget https://raw.githubusercontent.com/huggingface/diffusers/main/scripts/convert_original_stable_diffusion_to_diffusers.py
!pip install omegaconf
!accelerate config default
!python convert_original_stable_diffusion_to_diffusers.py \
--checkpoint_path "/content/gdrive/MyDrive/Fast-Dreambooth/Sessions/phtmejhn/phtmejhn.ckpt" \
--dump_path "/content/gdrive/MyDrive/Fast-Dreambooth/Sessions/phtmejhn_conv2"
由于我们的硬盘存储空间有限,我们使用以下代码将模型推送到 Hugging Face。(这比手动上传快得多)
!huggingface-cli login
from huggingface_hub import HfApi
api = HfApi()
api.upload_folder(
folder_path="/content/drive/MyDrive/DL_Project/Abishek_Flynn",
repo_id="Bilal326/Flynn_LoRA",
repo_type="model",
)
ShivamShrirao 的一些笔记本输出为较新的 safe-tensors 格式,但对于这些文件,我们发现 `.from_single_file()` 方法适用于推理,但要进行微调,这些文件也需要转换为 diffusers 格式。
DreamBooth 在 Flynn - Rapunzel 上
我们了解到,对于动画角色,我们要么需要找到正则化类别图像(该动画风格的),要么跳过它。我们通过选择一个来自 *CivitAI* 的预训练 DreamBooth 检查点,并使用 DreamBooth 进一步训练它,找到了解决此问题的方法。这次我们训练了 18 张来自《魔发奇缘》电影中 Flynn 角色的图像,使用令牌 fljsdhn 进行识别。
Flynn 的训练图像如下:
我们从 CivitAI 选择了两个检查点:1. Toonyou 检查点和 2. Disney Pixar 合并检查点。
我们使用其 API 在 Google Colab 中下载了 CivitAI 的模型。
!wget https://civitai.com/api/download/models/{model_id} --content-disposition
下载的模型被转换为 diffuser 格式,并在其上应用了 DreamBooth。
对于 toonyou 模型,我们未能微调出好模型,但已将其上传 - Bilal326/Flynn_fast_1。然而,通过在 Disney Pixar 检查点上进行训练,我们得到了一个非常好的模型。
以下超参数对我们而言效果最佳:
- 最大训练步数 = 1530
- 学习率 = 2e-6
- 类图像 = 200
- 文本编码器训练步数 = 350
从结果中显而易见,在预训练/合并检查点之上训练动画角色会带来更好的结果。
文本反演
对于风格化,我们选择了文本反演,因为它是所有 Stable Diffusion 微调方法中最快、最轻量级的。在这里,如第 2 节所述,使用特定令牌将生成的图像在潜在空间中向特定方向移动。我们使用了论文 GitHub 页面上提供的官方文本反演实现。为了训练,我们从《蜘蛛侠:平行宇宙 (2023)》电影中截取了 30 张截图。我们从各种场景中截取了截图,裁剪掉了任何角色。我们在原始 Stable Diffusion 1.5 模型之上进行了训练(但如本文前面所述,在预训练检查点之上进行训练)。该模型已被推送到 huggingface 嵌入概念库,可以在 sd-concepts-library/style-spdmn 找到。我们目前只训练了一个令牌 <style-spdmn>,没有使用任何触发词。以下是训练详情:
- 令牌 = <style-spdmn>
- 学习率 5e-4
- 最大训练步数 = 2000
- 训练批次大小 = 4
我们每 250 步保存一个嵌入检查点,但发现 2000 步的检查点是所有检查点中最好的。下面是根据此嵌入生成的提示词图像。我们为每个提示词生成了 25 张图像。
提示:火星上的一场演唱会,风格为 <style-spdmn>
整合文本反演和 DreamBooth 我们尝试了各种技术和方法来制作我们喜欢的模型。我们发现将 DreamBooth 模型与文本反演结合使用可以使模型更加个性化。我们还可以将 LoRA 层与模型融合(用于特定主题/风格),但由于时间限制,我们未能尝试。我们使用以下代码将文本嵌入加载到在 Disney Pixar Checkpoint 上训练的 DreamBooth 模型中。
pipeline.load_textual_inversion("sd-concepts-library/style-spdmn")
以下是将文本反演上传到 DreamBooth 模型后的一些结果
交叉注意力控制
从上一节可以明显看出,结果并不一致。角色、主题和场景似乎都随着提示中 1 或 2 个词的变化而变化。为了解决这个问题,我们使用了交叉注意力控制(论文发布于 2022 年 8 月 2 日,GitHub 仓库:https://github.com/bloc97/CrossAttentionControl)。它适用于大型语言模型,在稳定扩散中,它在推理阶段改变模型中的注意力图。这不需要用户提供遮罩,避免了创建适当遮罩形状的挑战。这更好的一点是它不需要额外的模型训练。它通过缩放提示中特定令牌的重要性来实现,从而实现有针对性的编辑。这可用于提示到提示的编辑,其中图像被映射回其潜在空间并根据新提示进行修改。
我们使用了论文官方 GitHub 仓库中的官方实现,并进行了少量修改。
- py:这负责修改模型中的注意力机制。
- py:定义了用于序列比对的函数。
接下来,编写了 **AttentionReplace**、**AttentionRefine** 和 **AttentionReweight** 等函数,它们使用上述脚本来控制网络中的注意力层。此代码的笔记本位于 DB+TI+CAE2.ipynb 笔记本中。
OpenAI API
在获得了微调模型(微调扩散 + 文本反演 + 交叉注意力控制)后,我们获得了一个能够创建具有多个一致图像的故事板的模型,每个图像都描绘故事的不同部分。然而,我们希望从单行文本生成这些图像,例如“给我一个 Flynn 在阳光明媚的一天放松的故事”,因为好的提示词可能超过 50 个单词,而且我们的角色和风格是基于独特的单词/令牌(phtmejhn, fljsdhn, <style-spdmn>)进行训练的,这些单词/令牌需要放置在提示词中。此外,为了在图像中获得所需的特征,需要给予单词更多的权重,例如(微笑:1.3)、(牙齿、张开的嘴:1.4),并且如果训练中使用了触发词,触发词也需要仔细放置在提示词中。因此,我们将 DreamBooth+文本反演+交叉注意力控制模型与 ChatGPT 3.5 API 集成,仅使用一句话“给我一个 Flynn 在阳光明媚的一天放松的故事”来生成 5 张图像的提示词 + 标题。在参数中,Flynn 被要求替换为 fljsdhn。以下是 ChatGPT API 生成的场景的提示词和标题。API 集成的代码可以在 chatgpt_api.ipynb 笔记本中找到。结果如下所示。这些图像可以通过提示词进一步编辑,尽管结果比原始模型或 DreamBooth 模型产生的结果更加一致,但可以通过进一步调整模型和提示词来进一步改进。
提示
- Fljsdhn 清晨坐在公园长凳上,手拿三明治,脸上带着柔和的微笑,背景是阳光透过树林洒下的光芒。
- Fljsdhn 坐在草地上,略显困惑和担忧地查看地图和指南针,旁边放着一个野餐篮,草地上躺着一台老式相机。
- Fljsdhn 躲在森林里一棵大树后面,调皮地探出头来,表情顽皮,暗示他即将制造一个惊喜。
- Fljsdhn 坐在林间空地上,抱着吉他,全神贯注于音乐,脸上洋溢着热情,夕阳在他身后落下,将暖色调洒满整个场景。
- 在充满活力的暮色天空下,Fljsdhn 抬头仰望,脸上洋溢着灵感和喜悦的表情,夕阳的色彩映在他的眼中,捕捉了一个奇迹般的瞬间。
标题
- 弗林在公园里享受片刻的孤独,在阳光明媚的日子里津津有味地吃着三明治。
- 弗林陷入沉思,仔细研究着地图,带着一丝担忧计划着他的下一次冒险。
- 弗林悄悄地从树后探出头来,他调皮的笑容暗示着一个即将到来的惊喜。
- 随着轻柔的拨弦,弗林沉浸在音乐中,他的吉他声在寂静的树林中回荡。
- 当天空被暮色染红时,弗林的脸上洋溢着喜悦,一天的冒险变成了美好的回忆。
这些生成的提示词非常简单,但当被要求时,它们会变得更加高级。此外,如果与 ControlNet 结合使用,强化学习与提示到提示的交叉注意力控制相结合可能会产生更好的结果。
SDXL 流程
对于这个项目,我们还尝试对我们的角色进行 Stable Diffusion XL 模型的微调。但截至撰写本报告时,Huggingface 尚未发布 DreamBooth for SDXL 的实现。然而,Linqruf 和 bmaltis Kohya ss 笔记本提供了非官方的实现。我们确实尝试了使用 baltic/Kohya_ss 在 SDXK 上使用 DreamBooth,并在此过程中消耗了 200 个 colab 单元,但未能获得良好的结果。然后我们选择了 LoRA(大型语言模型的低秩适应),这是 DreamBooth 之后的下一个最佳选择。为此,我们使用了 Huggingface 的 Auto-train Library 中最简单的实现。我们训练了两个角色,第一个是动画角色《魔发奇缘》中的 Flynn,第二个是真实角色《权力的游戏》中的 Natalie Dormer。最初,我们选择了在检查点之上进行训练,但在对转换后的模型进行训练后(safetensors 被转换为 diffusers 进行转换),我们遇到了脚本问题。此外,我们无法在 huggingface 上找到没有该错误的相同检查点。因此,由于时间和这些限制,我们被迫在原始 SDXL 模型上进行训练。
LoRA - 弗林
我们使用与训练 SD 1.5 模型相同的 18 张图像训练了 Flynn 角色。训练 SDXL 的计算成本非常高,因此我们在 r/StableDiffusion 和 CivitAI 上进行了 extensive 搜索,以了解哪些参数已被证明能给出良好的结果。我们使用了以下参数:
- 学习率 = 1e-4
- 步数 = 1800(每张图像 100 步)
- 梯度累积 = 4
- 分辨率 512(使用 1080p 分辨率会使训练时间增加 3 倍)
- 我们没有使用 8 位 Adam,因为我们有足够的算力,并且希望获得最佳结果。
6. !autotrain dreambooth \
7. --model stabilityai/stable-diffusion-xl-base-1.0 \
8. --image-path /content/drive/MyDrive/DL_Project/Flynn_19/ \
9. --prompt "photo of fljsdhn man" \
10. --project-name "Abishek_ND_3" \
11. --resolution 512 \
12. --batch-size 1 \
13. --num-steps 1800 \
14. --fp16 \
15. --gradient-accumulation 4 \
16. --lr 1e-4
即使是 18 张 512x512 图像,在 A100 GPU 上也需要 2 小时,消耗了 Colab 上约 70 个 GPU 积分。结果如下所示,它们远优于 Stable Diffusion 1.5 的 DreamBooth 结果。由于 LoRA 层可以与其他检查点融合,我们选择了一个流行的检查点 Unstable Diffusion v11,根据其 CivitAI 页面,它以生成动画和真实世界角色的良好图像而闻名。我们从 CivitAI 下载了 safetensor,转换为 diffusers 并推送到 HuggingFace。使用以下代码将从基础 SDXL 1.0 模型训练的 LoRA 层与 UnstableDiffusers v11 检查点融合。我们尝试了各种融合比例,但对于 Flynn,LoRA 比例 0.7 效果非常好。代码如下。
from diffusers import DiffusionPipeline
import torch
pipeline_unst = DiffusionPipeline.from_pretrained(
"Bilal326/SDXLUnstableDiff_v11", torch_dtype=torch.float16
).to("cuda")
pipeline_unst.load_lora_weights("/content/drive/MyDrive/DL_Project/Abishek_Flynn", weight_name="pytorch_lora_weights.safetensors")
pipeline_unst.fuse_lora(lora_scale=0.8)
结果如下所示:
娜塔莉 - LoRA 训练
同样,为了训练一个真实世界的角色,我们使用了 30 张《权力的游戏》女演员娜塔莉·多默的图像,并使用了上一节中提到的相同参数。训练 30 张图像耗时 3.5 小时,在 Colab 上消耗了 150 个 GPU 单元(100 张 512x512 图像耗时 8 小时,100 张 1920x1080 图像耗时 24 小时)。
各种提示词的结果如下所示。最初,我们使用 0.7 的比例进行融合,但将其增加到 0.9 后,与角色的相似度更高。我们尝试将层与基础 SDXL 模型以及以下模型融合:
- Juggernaut XL v7(SDXL base 1.0 的训练检查点)
- Photon v1(SDXL base 1.0 的合并检查点)
- DreamShaper XL (SDXL Turbo 的训练检查点)
- ICBINP (SD 1.5 的 LCM)
DreamShaper 的结果对比度略高,但 Juggernaut、Photon 和 ICBINP 的结果比基础 SDXL 1.0 模型的结果要好得多。
我们大部分生成的图像都已上传到 CivitAI 的个人资料中。结果如下:
未来工作
尽管我们实现了项目的目标,即使用所有主流方法对 Stable Diffusion 模型进行微调,将它们组合起来,并将其与交叉注意力控制和 ChatGPT API 集成。我们还成功地微调了 SDXL 模型,将其与 API 集成,并从中生成了结果。然而,未来还有一些事情可以尝试:
- 我们相信我们与交叉注意力控制集成的微调模型可以进一步微调以获得更好的结果。
- 由于时间限制,我们无法将我们的结果与 MidJourney 进行比较,但由于它不是微调模型,因此生成 Natalie Dormer 图像的提示结果肯定不会比我们的好。然而,我们确实将我们的结果与 Dall-E 进行了比较,使用相同的提示词,其中用 Flynn 代替了 token 词,从视觉上看,结果比我们基于 SD 1.5 的模型要好(但 SD 1.5 已经有一年多历史了,而 Dall-E 3 是在 23 年 10 月发布的)。此外,由于时间限制,我们无法进行更多实验。然而,我们微调的 SDXL 模型给出了更好的结果。我们相信进一步微调 SD 1.5 可以给出更好的结果。
- 截至本报告撰写时,SDXL 上尚未有官方的文本反演实现。然而,GitHub 上有一个非官方实现 (https://github.com/oss-roettger/XL-Textual-Inversion),可以尝试并加载到 SDXL 中(因为现在嵌入可以加载到 SDXL 中)。
- 我们尚未评估我们模型生成的图像,使用 CLIP 分数和 RMSE 等评估指标。
- 我们将 ChatGPT 3.5 API 与我们的模型进行了集成。ChatGPT 4 API 也可以用于提供更好的提示,并能够上传图像以更好地指导模型生成我们想要的图像类型。
- 我们尚未尝试合并模型。从 r/StableDiffusion 子版块我们了解到,合并训练过的 Dreambooth 模型是一种非常常见的做法,并且被证明可以产生良好的结果,例如我们使用的 DisneyPixar 检查点就是经过训练的。
- 由于时间限制,我们未能尝试新发布的 Stable Video Diffusion 模型(2023 年 11 月 23 日发布)。我们生成的图像和场景可以转换为视频,然后进行编辑以描绘一个场景,甚至是一个音乐视频。
- 目前,SDXL 还没有与交叉注意力控制集成,这也可以在未来尝试。
- 我们的管道可以转化为一个产品(类似于 ChatGPT),用户可以通过它与模型交互,获得逼真的动画故事板场景。用户可以选择一个想要故事的角色,选择一个故事的主题/风格,然后输入一个简短的提示,例如“给我一个弗林在阳光明媚的一天放松的故事”,集成的 ChatGPT API 可以生成提示,然后将其输入模型以获得所需数量的时间一致图像。他可以使用提示编辑图像,或者上传图像来改变角色的姿势/情绪/服装。这可以通过将 ControlNet 与交叉注意力控制集成来实现,这也是未来可以尝试的另一件事。
结论
总而言之,我们的项目全面探索了如何利用 Stable Diffusion 模型和文本反演来为各种创意应用生成一致的图像,包括故事板、动画电影场景和儿童故事。该项目利用了 DreamBooth 和特定角色训练等先进技术,提供了训练脚本、推理代码和最终结果的详细见解。该项目展示了集成复杂的 AI 模型和方法来为不同讲故事目的创建具有视觉吸引力且连贯的图像的潜力,强调了 AI 进步在视觉内容生成方面的重要性。