目前,LoRA 仅支持UNet2DConditionalModel
. 我们还支持对 DreamBooth 文本编码器的 LoRA 微调,能力有限。有关我们如何支持文本编码器的 LoRA 微调的更多详细信息,请参阅此 PR上的讨论。
Low-Rank Adaptation of Large Language Models (LoRA)是一种训练方法,可以加速大型模型的训练,同时消耗更少的内存。它将成对的秩分解权重矩阵(称为更新矩阵)添加到现有权重中,并且只训练那些新添加的权重。这有两个优点:
- 以前预训练的权重保持冻结状态,因此模型不会出现灾难性遗忘。
- 秩分解矩阵的参数明显少于原始模型,这意味着经过训练的 LoRA 权重很容易移植。
- LoRA 矩阵一般被添加到原始模型的注意力层中。🧨 Diffusers 提供了load_attn_procs()方法来将 LoRA 权重加载到模型的注意力层中。您可以通过参数控制模型适应新训练图像的程度
scale
。 - 更高的内存效率让您可以在 Tesla T4、RTX 3080 甚至 RTX 2080 Ti 等消费类 GPU 上运行微调!像 T4 这样的 GPU 是免费的,并且可以在 Kaggle 或 Google Colab 笔记本中轻松访问。
💡 LoRA 不仅限于注意力层。作者发现修改语言模型的注意力层足以高效地获得良好的下游性能。这就是为什么通常只将 LoRA 权重添加到模型的注意力层。查看使用 LoRA 实现高效稳定扩散微调博客,了解有关 LoRA 工作原理的更多信息!
cloneofsimo是第一个在流行的lora GitHub 存储库中尝试 LoRA 稳定扩散训练的人。🧨 Diffusers 现在支持使用 LoRA 进行文本到图像生成和DreamBooth微调。本指南将向您展示如何做到这两点。
如果您想存储您的模型或与社区分享您的模型,请登录您的 Hugging Face 帐户(如果您还没有,请创建一个):
huggingface-cli 登录
文本到图像
微调像 Stable Diffusion 这样具有数十亿个参数的模型可能既缓慢又困难。使用 LoRA,微调扩散模型变得更加容易和快速。它可以在具有低至 11GB GPU RAM 的硬件上运行,而无需诉诸 8 位优化器等技巧。
训练
让我们stable-diffusion-v1-5对Pokémon BLIP 字幕数据集进行微调以生成您自己的 Pokémon。
指定MODEL_NAME
环境变量(Hub 模型存储库 ID 或包含模型权重的目录路径)并将其传递给参数~diffusers.DiffusionPipeline.from_pretrained.pretrained_model_name_or_path
。您还需要将DATASET_NAME
环境变量设置为您要训练的数据集的名称。
和变量是可选的,用于指定将模型保存到集线器上的位置OUTPUT_DIR
:HUB_MODEL_ID
export MODEL_NAME = "runwayml/stable-diffusion-v1-5"
export OUTPUT_DIR = "/sddata/finetune/lora/pokemon"
export HUB_MODEL_ID = "pokemon-lora"
export DATASET_NAME = "lambdalabs/pokemon-blip-captions"
在开始训练之前,需要注意一些标志:
--push_to_hub
将经过训练的 LoRA 嵌入存储在 Hub 上。--report_to=wandb
报告训练结果并将其记录到您的权重和偏差仪表板(例如,查看此报告)。--learning_rate=1e-04
,您可以负担得起使用比通常使用 LoRA 更高的学习率。
现在您已准备好启动培训(您可以在此处找到完整的培训脚本):
加速启动 --mixed_precision= "fp16" train_text_to_image_lora.py \
--pretrained_model_name_or_path= $MODEL_NAME \
--dataset_name= $DATASET_NAME \
--dataloader_num_workers=8 \
--resolution=512 --center_crop --random_flip \
--train_batch_size=1 \
--gradient_accumulation_steps=4 \
--max_train_steps=15000 \
--learning_rate=1e-04 \
--max_grad_norm=1 \
--lr_scheduler= “余弦” --lr_warmup_steps=0 \
--output_dir= ${OUTPUT_DIR} \
--push_to_hub \
--hub_model_id= ${HUB_MODEL_ID} \
--report_to=wandb \
--checkpointing_steps=500 \
--validation_prompt= "一只蓝眼睛的口袋妖怪。" \
--seed=1337
推理
现在,您可以通过在StableDiffusionPipeline中加载基本模型然后在DPMSolverMultistepScheduler中使用模型进行推理:
>>>导入火炬
>>>从扩散器导入StableDiffusionPipeline,DPMSolverMultistepScheduler
>>> model_base = "runwayml/stable-diffusion-v1-5"
>>>管道 = StableDiffusionPipeline.from_pretrained(model_base, torch_dtype=torch.float16)
>>> pipe.scheduler = DPMSolverMultistepScheduler.from_config(pipe.scheduler.config)
从您的微调模型加载 LoRA 权重到基础模型权重之上,然后将管道移动到 GPU 以加快推理速度。当您将 LoRA 权重与冻结的预训练模型权重合并时,您可以选择调整多少权重与参数合并scale
:
💡scale
的值0
与不使用您的 LoRA 权重相同,您仅使用基本模型权重,而值scale
意味着1
您仅使用完全微调的 LoRA 权重。两个权重之间的值0
和插值。1
>>> pipe.unet.load_attn_procs(model_path)
>>> pipe.to( "cuda" )
# 使用 LoRA 微调模型的一半权重和基础模型的一半权重
>>> image = pipe(
... "A pokemon with blue eyes." , num_inference_steps= 25 , guidance_scale= 7.5 , cross_attention_kwargs={ "scale" : 0.5 }
... ).images[ 0 ]
# 使用权重完全微调的 LoRA 模型
>>> image = pipe( "一只蓝眼睛的口袋妖怪。" , num_inference_steps= 25 , guidance_scale= 7.5 ).images[ 0 ]
>>> image.save( "blue_pokemon.png" )
DreamBooth
DreamBooth是一种微调技术,用于个性化文本到图像模型(如 Stable Diffusion),以在给定几张主题图像的情况下生成不同背景下主题的逼真图像。但是,DreamBooth 对超参数非常敏感,容易过拟合。需要考虑的一些重要超参数包括影响训练时间(学习率、训练步数)和推理时间(步数、调度程序类型)的参数。
💡 使用 🧨 Diffusers 博客查看Training Stable Diffusion with DreamBooth,以深入分析 DreamBooth 实验和推荐设置。
训练
让我们stable-diffusion-v1-5用 DreamBooth 和 LoRA 使用一些🐶狗图像进行微调。下载这些图像并将其保存到目录中。
首先,指定MODEL_NAME
环境变量(Hub 模型存储库 ID 或包含模型权重的目录路径)并将其传递给参数~diffusers.DiffusionPipeline.from_pretrained.pretrained_model_name_or_path
。您还需要设置INSTANCE_DIR
为包含图像的目录路径。
变量OUTPUT_DIR
是可选的,并指定将模型保存到集线器上的位置:
export MODEL_NAME = "runwayml/stable-diffusion-v1-5"
export INSTANCE_DIR = "path-to-instance-images"
export OUTPUT_DIR = "path-to-save-model"
在开始训练之前,需要注意一些标志:
--push_to_hub
将经过训练的 LoRA 嵌入存储在 Hub 上。--report_to=wandb
报告训练结果并将其记录到您的权重和偏差仪表板(例如,查看此报告)。--learning_rate=1e-04
,您可以负担得起使用比通常使用 LoRA 更高的学习率。
现在您已准备好启动培训(您可以在此处找到完整的培训脚本):
加速发射 train_dreambooth_lora.py \
--pretrained_model_name_or_path= $MODEL_NAME \
--instance_data_dir= $INSTANCE_DIR \
--output_dir= $OUTPUT_DIR \
--instance_prompt= "一张 sks 狗的照片" \
--分辨率=512 \
--train_batch_size=1 \
--gradient_accumulation_steps=1 \
--checkpointing_steps=100 \
--learning_rate=1e-4 \
--report_to= “wandb” \
--lr_scheduler= “常量” \
--lr_warmup_steps=0 \
--max_train_steps=500 \
--validation_prompt= "桶中 sks 狗的照片" \
--validation_epochs=50 \
--种子= “0” \
--push_to_hub
还可以使用 LoRA 额外微调文本编码器。在大多数情况下,这会导致更好的结果,同时略微增加计算量。要允许使用 LoRA 微调文本编码器,请--train_text_encoder
在启动train_dreambooth_lora.py
脚本时指定。
推理
现在,您可以通过在StableDiffusionPipeline中加载基础模型来使用该模型进行推理:
>>>导入火炬
>>>从扩散器导入StableDiffusionPipeline
>>> model_base = "runwayml/stable-diffusion-v1-5"
>>>管道 = StableDiffusionPipeline.from_pretrained(model_base, torch_dtype=torch.float16)
从您微调的 DreamBooth 模型加载 LoRA 权重到基础模型权重之上,然后将管道移动到 GPU 以加快推理速度。当您将 LoRA 权重与冻结的预训练模型权重合并时,您可以选择调整多少权重与参数合并scale
:
💡scale
的值0
与不使用您的 LoRA 权重相同,您仅使用基本模型权重,而值scale
意味着1
您仅使用完全微调的 LoRA 权重。两个权重之间的值0
和插值。1
>>> pipe.unet.load_attn_procs(model_path)
>>> pipe.to( "cuda" )
# 使用 LoRA 微调模型的一半权重和基础模型的一半权重
>>> image = pipe(
... "A picture of a sks dog in a bucket." ,
... num_inference_steps= 25 ,
... guidance_scale= 7.5 ,
... cross_attention_kwargs={ "scale" : 0.5 },
... ).images[ 0 ]
# 使用完全微调的 LoRA 模型的权重
>>> image = pipe( "A picture of a sks dog in a bucket." , num_inference_steps= 25 , guidance_scale= 7.5 ).images[ 0 ]
>>> image.save( "bucket-dog.png" )