DreamBooth
DreamBooth 是一种训练技术,它通过仅对主题或风格的少数图像进行训练来更新整个扩散模型。它的工作原理是将提示中的特殊词与示例图像关联起来。
如果你的 GPU 的 vRAM 有限,你应该尝试在训练命令中启用 gradient_checkpointing
和 mixed_precision
参数。你还可以使用带有 xFormers 的内存高效注意力来减少内存占用。JAX/Flax 训练也支持在 TPU 和 GPU 上进行高效训练,但它不支持梯度检查点或 xFormers。如果你想使用 Flax 更快地进行训练,你的 GPU 应具有超过 30GB 的内存。
本指南将探索 train_dreambooth.py 脚本,以帮助你更熟悉它以及如何将其调整以适应你自己的用例。
在运行脚本之前,请确保你从源代码安装了库
git clone https://github.com/huggingface/diffusers
cd diffusers
pip install .
导航到包含训练脚本的示例文件夹,并安装你正在使用的脚本所需的依赖项
cd examples/dreambooth
pip install -r requirements.txt
🤗 Accelerate 是一个库,可以帮助你在多个 GPU/TPU 上或使用混合精度进行训练。它会根据你的硬件和环境自动配置你的训练设置。查看 🤗 Accelerate 的 快速入门 以了解更多信息。
初始化 🤗 Accelerate 环境
accelerate config
要设置默认的 🤗 Accelerate 环境,无需选择任何配置
accelerate config default
或者,如果你的环境不支持交互式 shell(例如笔记本),你可以使用
from accelerate.utils import write_basic_config
write_basic_config()
最后,如果你想在自己的数据集上训练模型,请查看 创建用于训练的数据集 指南,了解如何创建与训练脚本兼容的数据集。
以下部分重点介绍训练脚本中一些重要的部分,这些部分对于了解如何修改它至关重要,但它不会详细介绍脚本的每个方面。如果你有兴趣了解更多信息,请随时通读 脚本 ,如果你有任何问题或疑虑,请告知我们。
脚本参数
DreamBooth 对训练超参数非常敏感,很容易过拟合。阅读 使用 🧨 Diffusers 训练 Stable Diffusion with Dreambooth 博客文章,了解针对不同主题的推荐设置,以帮助你选择合适的超参数。
训练脚本提供了许多参数来自定义你的训练运行。所有参数及其描述都可以在 parse_args()
函数中找到。参数设置了默认值,这些值应该可以开箱即用,但你也可以在训练命令中设置自己的值,如果你需要。
例如,要在 bf16 格式中进行训练
accelerate launch train_dreambooth.py \
--mixed_precision="bf16"
一些基本且重要的参数需要了解和指定,包括:
--pretrained_model_name_or_path
:Hub 上的模型名称或预训练模型的本地路径--instance_data_dir
:包含训练数据集(示例图像)的文件夹的路径--instance_prompt
:包含示例图像的特殊词的文本提示--train_text_encoder
:是否也训练文本编码器--output_dir
:保存训练模型的位置--push_to_hub
:是否将训练模型推送到 Hub--checkpointing_steps
:模型训练时保存检查点的频率;如果由于某种原因训练中断,可以通过在训练命令中添加--resume_from_checkpoint
来从该检查点继续训练
最小 SNR 加权
最小 SNR 加权策略可以通过重新平衡损失来帮助训练,从而实现更快的收敛。训练脚本支持预测 epsilon
(噪声)或 v_prediction
,但最小 SNR 与两种预测类型都兼容。这种加权策略仅由 PyTorch 支持,在 Flax 训练脚本中不可用。
添加 --snr_gamma
参数并将其设置为推荐值 5.0
accelerate launch train_dreambooth.py \ --snr_gamma=5.0
先验保留损失
先验保留损失是一种使用模型自己生成的样本帮助它学习如何生成更多样化图像的方法。由于这些生成的样本图像属于与你提供的图像相同的类别,它们帮助模型保留它对该类别已经学到的知识以及它如何使用它已经对该类别知道的知识来进行新的组合。
--with_prior_preservation
:是否使用先验保留损失--prior_loss_weight
:控制先验保留损失对模型的影响--class_data_dir
: 包含生成类别样本图像的文件夹路径--class_prompt
: 描述生成样本图像类别的文本提示
accelerate launch train_dreambooth.py \
--with_prior_preservation \
--prior_loss_weight=1.0 \
--class_data_dir="path/to/class/images" \
--class_prompt="text prompt describing class"
训练文本编码器
为了提高生成输出的质量,除了UNet之外,您还可以训练文本编码器。这需要额外的内存,并且您需要至少拥有24GB vRAM的GPU。如果您拥有必要的硬件,那么训练文本编码器会产生更好的结果,尤其是在生成人脸图像时。通过以下步骤启用此选项:
accelerate launch train_dreambooth.py \ --train_text_encoder
训练脚本
DreamBooth 拥有自己的数据集类
DreamBoothDataset
: 预处理图像和类别图像,并对提示进行标记以进行训练PromptDataset
: 生成提示嵌入以生成类别图像
如果您启用了 先验保留损失,类别图像将在此处生成
sample_dataset = PromptDataset(args.class_prompt, num_new_images)
sample_dataloader = torch.utils.data.DataLoader(sample_dataset, batch_size=args.sample_batch_size)
sample_dataloader = accelerator.prepare(sample_dataloader)
pipeline.to(accelerator.device)
for example in tqdm(
sample_dataloader, desc="Generating class images", disable=not accelerator.is_local_main_process
):
images = pipeline(example["prompt"]).images
接下来是 main()
函数,它负责设置用于训练的数据集和训练循环本身。该脚本加载 标记器、调度器和模型
# Load the tokenizer
if args.tokenizer_name:
tokenizer = AutoTokenizer.from_pretrained(args.tokenizer_name, revision=args.revision, use_fast=False)
elif args.pretrained_model_name_or_path:
tokenizer = AutoTokenizer.from_pretrained(
args.pretrained_model_name_or_path,
subfolder="tokenizer",
revision=args.revision,
use_fast=False,
)
# Load scheduler and models
noise_scheduler = DDPMScheduler.from_pretrained(args.pretrained_model_name_or_path, subfolder="scheduler")
text_encoder = text_encoder_cls.from_pretrained(
args.pretrained_model_name_or_path, subfolder="text_encoder", revision=args.revision
)
if model_has_vae(args):
vae = AutoencoderKL.from_pretrained(
args.pretrained_model_name_or_path, subfolder="vae", revision=args.revision
)
else:
vae = None
unet = UNet2DConditionModel.from_pretrained(
args.pretrained_model_name_or_path, subfolder="unet", revision=args.revision
)
然后,是时候 创建训练数据集 和来自 DreamBoothDataset
的 DataLoader
train_dataset = DreamBoothDataset(
instance_data_root=args.instance_data_dir,
instance_prompt=args.instance_prompt,
class_data_root=args.class_data_dir if args.with_prior_preservation else None,
class_prompt=args.class_prompt,
class_num=args.num_class_images,
tokenizer=tokenizer,
size=args.resolution,
center_crop=args.center_crop,
encoder_hidden_states=pre_computed_encoder_hidden_states,
class_prompt_encoder_hidden_states=pre_computed_class_prompt_encoder_hidden_states,
tokenizer_max_length=args.tokenizer_max_length,
)
train_dataloader = torch.utils.data.DataLoader(
train_dataset,
batch_size=args.train_batch_size,
shuffle=True,
collate_fn=lambda examples: collate_fn(examples, args.with_prior_preservation),
num_workers=args.dataloader_num_workers,
)
最后,训练循环 处理剩余的步骤,例如将图像转换为潜在空间、向输入添加噪声、预测噪声残差以及计算损失。
如果您想了解更多关于训练循环的工作原理,请查看 了解管道、模型和调度器 教程,该教程分解了去噪过程的基本模式。
启动脚本
您现在可以启动训练脚本!🚀
对于本指南,您将下载一些 狗 的图像,并将它们存储在一个目录中。但请记住,如果您愿意,可以创建并使用自己的数据集(请参阅 创建用于训练的数据集 指南)。
from huggingface_hub import snapshot_download
local_dir = "./dog"
snapshot_download(
"diffusers/dog-example",
local_dir=local_dir,
repo_type="dataset",
ignore_patterns=".gitattributes",
)
将环境变量 MODEL_NAME
设置为 Hub 上的模型 ID 或本地模型的路径,将 INSTANCE_DIR
设置为您刚刚下载狗图像的路径,将 OUTPUT_DIR
设置为要保存模型的位置。您将使用 sks
作为特殊词语来绑定训练。
如果您有兴趣跟踪训练过程,可以定期保存生成的图像,以跟踪训练进度。将以下参数添加到训练命令中
--validation_prompt="a photo of a sks dog"
--num_validation_images=4
--validation_steps=100
在启动脚本之前还有一件事!根据您拥有的 GPU,您可能需要启用某些优化来训练 DreamBooth。
在 16GB GPU 上,您可以使用 bitsandbytes 8 位优化器和梯度检查点来帮助您训练 DreamBooth 模型。安装 bitsandbytes
pip install bitsandbytes
然后,将以下参数添加到您的训练命令中
accelerate launch train_dreambooth.py \ --gradient_checkpointing \ --use_8bit_adam \
export MODEL_NAME="runwayml/stable-diffusion-v1-5"
export INSTANCE_DIR="./dog"
export OUTPUT_DIR="path_to_saved_model"
accelerate launch train_dreambooth.py \
--pretrained_model_name_or_path=$MODEL_NAME \
--instance_data_dir=$INSTANCE_DIR \
--output_dir=$OUTPUT_DIR \
--instance_prompt="a photo of sks dog" \
--resolution=512 \
--train_batch_size=1 \
--gradient_accumulation_steps=1 \
--learning_rate=5e-6 \
--lr_scheduler="constant" \
--lr_warmup_steps=0 \
--max_train_steps=400 \
--push_to_hub
训练完成后,您可以使用新训练的模型进行推理!
迫不及待想在训练完成之前尝试您的模型进行推理?🤭 确保您安装了最新版本的 🤗 Accelerate。
from diffusers import DiffusionPipeline, UNet2DConditionModel
from transformers import CLIPTextModel
import torch
unet = UNet2DConditionModel.from_pretrained("path/to/model/checkpoint-100/unet")
# if you have trained with `--args.train_text_encoder` make sure to also load the text encoder
text_encoder = CLIPTextModel.from_pretrained("path/to/model/checkpoint-100/checkpoint-100/text_encoder")
pipeline = DiffusionPipeline.from_pretrained(
"runwayml/stable-diffusion-v1-5", unet=unet, text_encoder=text_encoder, dtype=torch.float16,
).to("cuda")
image = pipeline("A photo of sks dog in a bucket", num_inference_steps=50, guidance_scale=7.5).images[0]
image.save("dog-bucket.png")
from diffusers import DiffusionPipeline
import torch
pipeline = DiffusionPipeline.from_pretrained("path_to_saved_model", torch_dtype=torch.float16, use_safetensors=True).to("cuda")
image = pipeline("A photo of sks dog in a bucket", num_inference_steps=50, guidance_scale=7.5).images[0]
image.save("dog-bucket.png")
LoRA
LoRA 是一种训练技术,可显着减少可训练参数的数量。因此,训练速度更快,并且更容易存储结果权重,因为它们的大小要小得多(约 100MB)。使用 train_dreambooth_lora.py 脚本使用 LoRA 进行训练。
LoRA 训练脚本在 LoRA 训练 指南中进行了更详细的讨论。
Stable Diffusion XL
Stable Diffusion XL (SDXL) 是一种强大的文本到图像模型,可以生成高分辨率图像,并且在它的架构中添加了第二个文本编码器。使用 train_dreambooth_lora_sdxl.py 脚本使用 LoRA 训练 SDXL 模型。
SDXL 训练脚本在 SDXL 训练 指南中进行了更详细的讨论。
DeepFloyd IF
DeepFloyd IF 是一种包含三个阶段的级联像素扩散模型。第一阶段生成基础图像,第二阶段和第三阶段逐步将基础图像放大到 1024x1024 的高分辨率图像。使用 train_dreambooth_lora.py 或 train_dreambooth.py 脚本使用 LoRA 或完整模型训练 DeepFloyd IF 模型。
DeepFloyd IF 使用预测方差,但 Diffusers 训练脚本使用预测误差,因此训练的 DeepFloyd IF 模型切换到固定方差计划。训练脚本将为您更新完全训练的模型的调度器配置。但是,当您加载保存的 LoRA 权重时,您也必须更新管道的调度器配置。
from diffusers import DiffusionPipeline
pipe = DiffusionPipeline.from_pretrained("DeepFloyd/IF-I-XL-v1.0", use_safetensors=True)
pipe.load_lora_weights("<lora weights path>")
# Update scheduler config to fixed variance schedule
pipe.scheduler = pipe.scheduler.__class__.from_config(pipe.scheduler.config, variance_type="fixed_small")
第二阶段模型需要额外的验证图像来放大。您可以下载并使用训练图像的缩小版本来执行此操作。
from huggingface_hub import snapshot_download
local_dir = "./dog_downsized"
snapshot_download(
"diffusers/dog-example-downsized",
local_dir=local_dir,
repo_type="dataset",
ignore_patterns=".gitattributes",
)
以下代码示例简要概述了如何使用 DreamBooth 和 LoRA 的组合训练 DeepFloyd IF 模型。一些重要的参数需要注意的是
--resolution=64
,因为 DeepFloyd IF 是一个像素扩散模型,并且要在未压缩像素上运行,输入图像必须更小--pre_compute_text_embeddings
,提前计算文本嵌入以节省内存,因为 T5Model 会占用大量内存--tokenizer_max_length=77
,您可以使用更长的默认文本长度与 T5 作为文本编码器,但默认的模型编码过程使用更短的文本长度--text_encoder_use_attention_mask
,将注意力掩码传递给文本编码器
使用 LoRA 和 DreamBooth 训练 DeepFloyd IF 的第一阶段需要约 28GB 的内存。
export MODEL_NAME="DeepFloyd/IF-I-XL-v1.0"
export INSTANCE_DIR="dog"
export OUTPUT_DIR="dreambooth_dog_lora"
accelerate launch train_dreambooth_lora.py \
--report_to wandb \
--pretrained_model_name_or_path=$MODEL_NAME \
--instance_data_dir=$INSTANCE_DIR \
--output_dir=$OUTPUT_DIR \
--instance_prompt="a sks dog" \
--resolution=64 \
--train_batch_size=4 \
--gradient_accumulation_steps=1 \
--learning_rate=5e-6 \
--scale_lr \
--max_train_steps=1200 \
--validation_prompt="a sks dog" \
--validation_epochs=25 \
--checkpointing_steps=100 \
--pre_compute_text_embeddings \
--tokenizer_max_length=77 \
--text_encoder_use_attention_mask
训练技巧
训练 DeepFloyd IF 模型可能具有挑战性,但以下是一些我们发现有用的技巧。
- LoRA 足以用于训练阶段 1 模型,因为模型的低分辨率使得无论如何都难以表示更精细的细节。
- 对于常见的或简单的物体,您不一定需要微调上采样器。确保传递给上采样器的提示已调整,以从实例提示中删除新标记。例如,如果您的阶段 1 提示是“一只 SKS 狗”,那么您的阶段 2 提示应该是“一只狗”。
- 对于更精细的细节,例如人脸,完全训练阶段 2 上采样器比使用 LoRA 训练阶段 2 模型更好。使用较低的学习率和较大的批次大小也有帮助。
- 应使用较低的学习率来训练阶段 2 模型。
- 与训练脚本中使用的 DPMSolver 相比,DDPMScheduler 效果更好。
下一步
恭喜您训练您的 DreamBooth 模型!要了解有关如何使用您的新模型的更多信息,以下指南可能会有所帮助。
- 了解如何 加载 DreamBooth 模型以进行推理,如果您使用 LoRA 训练了模型。