前言
上一章,我们介绍了Hyper Network的情况
本章,我们介绍如何使用LoRA微调大模型
LoRA微调大模型可以说是时下最流行的一个名词或者技术方式了。针对于其余的几种方式,LoRA可能是表现最好,趋势最好的一个方式了。
这个你可以在C站的大模型库中的LoRA模型的比例和其效果看到它的未来趋势。
国内也有很多所谓炼丹的说法。是不是很有趣。那么一起来仔细炼丹学习下吧
知识点
- LoRA
- 微调大模型
什么是LoRA
記住,不是這個物聯網的LORA哦。
https://www.mokosmart.com/zh-tw/lora-technology/
是這個
LoRA: Low-Rank Adaptation of Large Language Models 是微软研究员引入的一项新技术,主要用于处理大模型微调的问题。
https://github.com/microsoft/LoRA
目前超过数十亿以上参数的具有强能力的大模型 (例如 GPT-3) 通常在为了适应其下游任务的微调中会呈现出巨大开销。
比如,GPT-3有1750亿参数,为了让它能干特定领域的活儿,需要做微调,但是如果直接对GPT-3做微调,成本太高太麻烦了。
LoRA 建议冻结预训练模型的权重并在每个 Transformer 块中注入可训练层 (秩-分解矩阵)。因为不需要为大多数模型权重计算梯度,所以大大减少了需要训练参数的数量并且降低了 GPU 的内存要求。
通过聚焦大模型的 Transformer 注意力块,使用 LoRA 进行的微调质量与全模型微调相当,同时速度更快且需要更少的计算。
要做个比喻的话,就好比是大模型的一个小模型,或者说是一个插件。
LoRA本来是给大语言模型准备的,但把它用在cross-attention layers(交叉关注层)也能影响用文字生成图片的效果。
最早的Stable Diffusion模型其实不支持LoRa的,后来才加入了对LoRa的支持,据说,Simo Ryu是第一个让Stable Diffusion支持LoRa的人,感兴趣的话,去大佬的GitHub上看看这个项目。
https://github.com/cloneofsimo/lora
效果展示
以下是比较技术性的文绉绉的内容。我更倾向于用一个实际的效果来展示
我们用这个LoRA模型
https://civitai.com/models/12597/moxin
可以看到, 触发的词汇是
SHUIMOBYSIM
WUCHANGSHUO
BONIAN
ZHENBANQIAO
BADASHANREN
开启 LoRA的时候效果图如下
不开启LoRA的时候是这样的
以下是技术性的内容
用于 Diffusers 的 LoRA 🧨
尽管 LoRA 最初是为大模型提出的,并在 transformer 块上进行了演示,但该技术也可以应用于其他地方。在微调 Stable Diffusion 的情况下,LoRA 可以应用于将图像表示与描述它们的提示相关联的交叉注意层。下图的细节 (摘自 Stable Diffusion 论文) 并不重要,只需要注意黄色块是负责建立图文之间的关系表示就行。
为 Dreambooth 和全微调方法提供 Diffusions 中的 LoRA 训练支持!这些技术提供了以下好处:
- 更快的训练速度
- 计算要求较低。我们可以在具有 11 GB VRAM 的 2080 Ti 中创建一个全微调模型!
- 小了很多的训练模型。由于原始模型已冻结,我们注入了新层进行训练,因此我们可以将新层的权重保存为大小约为 3 MB 的单个文件。这比 UNet 模型的原始大小 小一千倍。
我们对最后一点特别兴奋。为了让用户分享他们出色的微调或 dreamboothed 模型,他们必须分享最终模型的完整副本。其他想要试用它们的用户必须在他们最喜欢的 UI 中下载经过微调的权重,这会增加大量存储和下载成本。截至今天,大约有 1000 个 Dreambooth 模型在 Dreambooth 概念库中注册,可能还有更多未在库中注册。
使用 LoRA,现在可以发布 单个 3.29 MB 文件 以允许其他人使用你的微调模型。
LoRA 微调
Stable Diffusion 的全模型微调过去既缓慢又困难,这也是 Dreambooth 或 Textual Inversion 等轻量级方法变得如此流行的部分原因。使用 LoRA,在自定义数据集上微调模型要容易得多。
Diffusers 现在提供了一个 LoRA 微调脚本,可以在低至 11 GB 的 GPU RAM 中运行而无需借助到诸如 8-bit 优化器之类的技巧。这里展示了您如何借助它来使用 Lambda Labs Pokémon 数据集 微调模型: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"
accelerate launch --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="cosine" --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="Totoro" \
--seed=1337
这里需要注意的一件事是学习率为“1e-4”,远大于常规微调的通常学习率 (通常为“~1e-6”的数量级)。
这是上次运行的 W&B dashboard,在 2080 Ti GPU (11 GB 内存)。
我没有尝试优化超参数,所以请自行尝试!Sayak 在 T4 (16 GB 内存) 上又跑了一次,请 在这里 查看他的最终模型,以及使用该模型的演示空间。
有关 diffusers 中 LoRA 支持的更多详细信息,请参阅 官方的文档 ——它将始终与实现保持同步。
推理
正如我们所讨论的,LoRA 的主要优势之一是您可以通过训练比原始模型大小少几个数量级的权重来获得出色的结果。我们设计了一个推理过程,允许在未修改的 Stable Diffusion 模型权重之上加载额外的权重。让我们看看它是如何工作的。
首先,我们将使用 Hub API 自动确定用于微调 LoRA 模型的基本模型是什么。从 Sayak 的模型 开始,我们可以使用这段代码:from huggingface_hub import model_info
# LoRA weights ~3 MB
model_path = "sayakpaul/sd-model-finetuned-lora-t4"
info = model_info(model_path)
model_base = info.cardData["base_model"]
print(model_base) # CompVis/stable-diffusion-v1-4
此代码段将打印他用于微调的模型,即 CompVis/stable-diffusion-v1-4。就我而言,我从 Stable Diffusion 1.5 版开始训练我的模型,因此如果您使用 LoRA 模型 运行相同的代码,您会看到输出是 runwayml/stable-diffusion-v1-5。
如果您使用 --push_to_hub 选项,我们在上一节中看到的微调脚本会自动填充有关基本模型的信息。正如您在 pokemon-lora 的介绍文档 中所见,这被记录为模型存储库的 README 文件中的元数据标签。
在我们确定了用于使用 LoRA 进行微调的基础模型之后,我们加载了一个正常的稳定扩散管道。我们将使用 DPMSolverMultistepScheduler 对其进行自定义,以实现非常快速的推理:import torch
from diffusers import StableDiffusionPipeline, DPMSolverMultistepScheduler
pipe = StableDiffusionPipeline.from_pretrained(model_base, torch_dtype=torch.float16)
pipe.scheduler = DPMSolverMultistepScheduler.from_config(pipe.scheduler.config)
神奇的地方来了。我们从 hub 加载 LoRA 权重 在常规模型权重之上,将 pipline 移动到 cuda 设备并运行推理:pipe.unet.load_attn_procs(model_path)
pipe.to("cuda")
image = pipe("Green pokemon with menacing face", num_inference_steps=25).images[0]
image.save("green_pokemon.png")
用 LoRA 进行 Dreamboothing
Dreambooth 允许您向 Stable Diffusion 模型“教授”新概念。LoRA 与 Dreambooth 兼容,过程类似于微调,有几个优点:
- 训练更快。
- 我们只需要几张我们想要训练的主题的图像 (通常 5 或 10 张就足够了)。
- 如果需要,我们可以调整文本编码器,以提高对训练主体的保真度。
要使用 LoRA 训练 Dreambooth,您需要使用 这个 diffusers 脚本。
如果您想体验一种快速、低成本又容易的方式来用 LoRA 训练您的 Dreambooth 模型,请查看 hysts 创作的 这个 Hugging Face Space。您需要克隆它,然后为它分配一个 GPU,这样才能运行地足够快。这个过程可以省下您从头开始配置训练环境的功夫,您可以在数分钟内开始训练模型!
其他方法
对轻松微调的追求并不新鲜。除了 Dreambooth 之外,textual inversion 是另一种流行的方法,它试图向训练有素的稳定扩散模型教授新概念。使用 Textual Inversion 的主要原因之一是经过训练的权重也很小且易于共享。然而,它们只适用于单个主题 (或一小部分主题),而 LoRA 可用于通用微调,这意味着它可以适应新的领域或数据集。
Pivotal Tuning 是一种尝试将 Textual Inversion 与 LoRA 相结合的方法。首先,您使用 textual inversion 技术向模型教授一个新概念,获得一个新的标记嵌入来表示它。然后,您使用 LoRA 训练该 token 嵌入以获得两全其美。