🤗 PEFT:在低资源硬件上对十亿规模模型进行参数高效微调

发布于 2023 年 2 月 10 日
在 GitHub 上更新

动机

基于 Transformer 架构的大型语言模型 (LLMs),如 GPT、T5 和 BERT,在各种自然语言处理 (NLP) 任务中取得了最先进的成果。它们也开始涉足其他领域,例如计算机视觉 (CV) (VIT、Stable Diffusion、LayoutLM) 和音频 (Whisper、XLS-R)。传统的范式是在通用网络规模数据上进行大规模预训练,然后针对下游任务进行微调。与开箱即用的预训练 LLM(例如零样本推理)相比,在下游数据集上微调这些预训练 LLM 可带来巨大的性能提升。

然而,随着模型变得越来越大,在消费级硬件上进行完全微调变得不可行。此外,为每个下游任务独立存储和部署微调模型变得非常昂贵,因为微调模型与原始预训练模型大小相同。参数高效微调 (PEFT) 方法旨在解决这两个问题!

PEFT 方法仅微调少量(额外)模型参数,同时冻结预训练 LLM 的大部分参数,从而大大降低了计算和存储成本。这还克服了灾难性遗忘问题,这是一种在 LLM 全量微调过程中观察到的行为。PEFT 方法还被证明在低数据状态下优于微调,并且对域外场景具有更好的泛化能力。它可以应用于各种模态,例如图像分类Stable Diffusion Dreambooth

它还有助于可移植性,用户可以使用 PEFT 方法调整模型,以获得仅几 MB 的微小检查点,而完全微调会产生大型检查点,例如,`bigscience/mt0-xxl` 占用 40GB 存储空间,完全微调将导致每个下游数据集生成 40GB 检查点,而使用 PEFT 方法,每个下游数据集仅需几 MB,同时达到与完全微调相当的性能。PEFT 方法训练得到的小权重会添加到预训练 LLM 的顶部。因此,同一个 LLM 可以通过添加小权重用于多个任务,而无需替换整个模型。

简而言之,PEFT 方法使您能够以少量可训练参数获得与完全微调相当的性能。

今天,我们很高兴推出 🤗 PEFT 库,该库提供最新参数高效微调技术,并与 🤗 Transformers 和 🤗 Accelerate 无缝集成。这使得使用 Transformers 中最流行、性能最佳的模型,同时结合 Accelerate 的简单性和可扩展性成为可能。以下是目前支持的 PEFT 方法,更多方法即将推出:

  1. LoRA:LORA:大型语言模型的低秩适应
  2. 前缀调整:P-Tuning v2:Prompt Tuning 可以与在各种规模和任务上的微调普遍媲美
  3. Prompt Tuning:规模对于参数高效 Prompt Tuning 的力量
  4. P-Tuning:GPT 也理解

用例

我们在此探索了许多有趣的用例。以下是一些最有趣的:

  1. 使用 🤗 PEFT LoRA,在具有 11GB 内存的消费级硬件(例如 Nvidia GeForce RTX 2080 Ti、Nvidia GeForce RTX 3080 等)上,使用 🤗 Accelerate 的 DeepSpeed 集成微调 `bigscience/T0_3B` 模型(30 亿参数):peft_lora_seq2seq_accelerate_ds_zero3_offload.py。这意味着您可以在 Google Colab 中微调如此大型的 LLM。

  2. 通过使用 🤗 PEFT LoRA 和 bitsandbytes 在 Google Colab 中启用 `OPT-6.7b` 模型(67 亿参数)的 INT8 微调,将前面的示例提升一个档次:在 Colab 中打开

  3. 使用 🤗 PEFT 在具有 11GB 内存的消费级硬件(例如 Nvidia GeForce RTX 2080 Ti、Nvidia GeForce RTX 3080 等)上进行 Stable Diffusion Dreambooth 训练。尝试 Space 演示,它应该可以在 T4 实例(16GB GPU)上无缝运行:smangrul/peft-lora-sd-dreambooth

peft lora dreambooth gradio space
PEFT LoRA Dreambooth Gradio Space

使用 🤗 PEFT 训练你的模型

让我们考虑使用 LoRA 对 `bigscience/mt0-large` 进行微调的案例。

  1. 获取必要的导入
  from transformers import AutoModelForSeq2SeqLM
+ from peft import get_peft_model, LoraConfig, TaskType
  model_name_or_path = "bigscience/mt0-large"
  tokenizer_name_or_path = "bigscience/mt0-large"
  1. 创建与 PEFT 方法对应的配置
peft_config = LoraConfig(
    task_type=TaskType.SEQ_2_SEQ_LM, inference_mode=False, r=8, lora_alpha=32, lora_dropout=0.1
)
  1. 通过调用 `get_peft_model` 封装基础 🤗 Transformers 模型
  model = AutoModelForSeq2SeqLM.from_pretrained(model_name_or_path)
+ model = get_peft_model(model, peft_config)
+ model.print_trainable_parameters()
# output: trainable params: 2359296 || all params: 1231940608 || trainable%: 0.19151053100118282

就是这样!其余的训练循环保持不变。请参阅示例 peft_lora_seq2seq.ipynb 以获取端到端示例。

  1. 当您准备好保存模型以进行推理时,只需执行以下操作。
model.save_pretrained("output_dir") 
# model.push_to_hub("my_awesome_peft_model") also works

这将只保存训练过的增量 PEFT 权重。例如,您可以在此处找到使用 LoRA 在 `twitter_complaints` raft 数据集上微调的 `bigscience/T0_3B`:smangrul/twitter_complaints_bigscience_T0_3B_LORA_SEQ_2_SEQ_LM。请注意,它只包含 2 个文件:adapter_config.json 和 adapter_model.bin,其中后者仅为 19MB。

  1. 要加载它进行推理,请遵循以下代码片段
  from transformers import AutoModelForSeq2SeqLM
+ from peft import PeftModel, PeftConfig

  peft_model_id = "smangrul/twitter_complaints_bigscience_T0_3B_LORA_SEQ_2_SEQ_LM"
  config = PeftConfig.from_pretrained(peft_model_id)
  model = AutoModelForSeq2SeqLM.from_pretrained(config.base_model_name_or_path)
+ model = PeftModel.from_pretrained(model, peft_model_id)
  tokenizer = AutoTokenizer.from_pretrained(config.base_model_name_or_path)

  model = model.to(device)
  model.eval()
  inputs = tokenizer("Tweet text : @HondaCustSvc Your customer service has been horrible during the recall process. I will never purchase a Honda again. Label :", return_tensors="pt")

  with torch.no_grad():
      outputs = model.generate(input_ids=inputs["input_ids"].to("cuda"), max_new_tokens=10)
      print(tokenizer.batch_decode(outputs.detach().cpu().numpy(), skip_special_tokens=True)[0])
# 'complaint'

后续步骤

我们发布了 PEFT,作为一种在下游任务和领域上微调大型 LLM 的高效方式,它节省了大量计算和存储,同时实现了与完全微调相当的性能。在未来几个月,我们将探索更多 PEFT 方法,例如 (IA)3 和瓶颈适配器。此外,我们将重点关注新的用例,例如在 Google Colab 中对 `whisper-large` 模型进行 INT8 训练,以及使用 PEFT 方法对 RLHF 组件(如策略和排序器)进行微调。

与此同时,我们很高兴看到行业从业者如何将 PEFT 应用于他们的用例——如果您有任何问题或反馈,请在我们的 GitHub 仓库上提出问题 🤗。

祝您参数高效微调愉快!

社区

干得好👍

image.png
这篇文章有一个错误:题为“P-Tuning v2: Prompt Tuning Can Be Comparable to Fine-tuning Universally Across Scales and Tasks”的论文是关于 P-Tuning v2 的,而不是前缀调整(Prefix Tuning)。因此,前缀“Prefix Tuning”是不正确的——它们是不同的方法。

注册登录 以评论