Diffusers documentation

DreamBooth

Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

DreamBooth

DreamBooth 是一种训练技术,它通过仅使用少量关于某个主体或风格的图像进行训练,来更新整个扩散模型。其工作原理是将提示词中的一个特殊单词与示例图像相关联。

要加载训练好的检查点以进行推理,请参阅 加载 DreamBooth 模型以进行推理。

如果用于训练的 GPU 显存有限,建议在训练命令中启用 gradient_checkpointing 和 mixed_precision 参数。此外,你还可以使用 xFormers 提供的内存高效注意力机制来降低内存占用。

本指南将深入讲解 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(例如 notebook),你可以使用:

from accelerate.utils import write_basic_config

write_basic_config()

最后,如果您想在自己的数据集上训练模型,请查看创建训练数据集指南,了解如何创建可与训练脚本配合使用的数据集。

以下各部分重点介绍了训练脚本中对于理解如何修改脚本至关重要的内容,但并未详细涵盖脚本的每个方面。如果您希望了解更多,请随时阅读脚本,并告诉我们您是否有任何疑问或顾虑。

脚本参数

DreamBooth 对训练超参数非常敏感,且很容易过拟合。请阅读 使用 🧨 Diffusers 通过 Dreambooth 训练 Stable Diffusion 博客文章,其中提供了针对不同主题的建议设置,以帮助你选择合适的超参数。

训练脚本提供了许多参数,用于自定义您的训练运行。所有参数及其说明都可以在 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,从该检查点继续训练。

Min-SNR 加权

Min-SNR 加权策略可以通过重新平衡损失来加速收敛,从而辅助训练。训练脚本支持预测 epsilon(噪声)或 v_prediction,而 Min-SNR 与这两种预测类型均兼容。此加权策略仅支持 PyTorch。

添加 --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:生成用于创建类别图像的提示嵌入

如果启用了 prior preservation loss,类图像将在此处生成:

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() 函数,它负责为训练设置数据集以及训练循环本身。该脚本会加载 tokenizer、调度器和模型:

# 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
12GB
8GB

在 16GB 的 GPU 上,你可以使用 bitsandbytes 8-bit 优化器和梯度检查点来帮助你训练 DreamBooth 模型。安装 bitsandbytes:

pip install bitsandbytes

然后,在训练命令中添加以下参数:

accelerate launch train_dreambooth.py \
  --gradient_checkpointing \
  --use_8bit_adam \
export MODEL_NAME="stable-diffusion-v1-5/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(
    "stable-diffusion-v1-5/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", dtype=torch.float16, use_safetensors=True).to("cuda")  # or "mps", "xpu", "cpu"
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")

阶段 2 模型需要额外的验证图像来进行放大。您可以下载并使用训练图像的缩小版本来完成此操作。

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,用于将注意力掩码传递给文本编码器
阶段 1 LoRA DreamBooth
阶段 2 LoRA DreamBooth
阶段 1 DreamBooth
阶段 2 DreamBooth

使用 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 足以用于训练第一阶段模型,因为该模型的分辨率较低,无论如何都难以表现更精细的细节。
  • 对于常见或简单的对象,您不一定需要微调上采样器。请确保传递给上采样器的提示词已调整,以从实例提示词中移除新标记。例如,如果您的第一阶段提示词是“a sks dog”,那么您的第二阶段提示词应为“a dog”。
  • 对于面部等更精细的细节,完全训练第二阶段上采样器比使用 LoRA 训练第二阶段模型效果更好。此外,使用较低的学习率配合较大的批次大小也有助于提升效果。
  • 训练第二阶段模型时应使用较低的学习率。
  • DDPMScheduler 在训练脚本中的表现优于 DPMSolver。

后续步骤

恭喜您训练好了 DreamBooth 模型!如需了解如何使用新模型,以下指南或许对您有帮助:

Update on GitHub