LoRA: 大型语言模型的低秩适应
此仓库包含 Python 包 loralib
的源代码,以及如何将其与 PyTorch 模型(如 Hugging Face 中的模型)集成的几个示例。我们目前仅支持 PyTorch。请参阅我们的论文以了解 LoRA 的详细描述。
LoRA: 大型语言模型的低秩适应
Edward J. Hu*, Yelong Shen*, Phillip Wallis, Zeyuan Allen-Zhu, Yuanzhi Li, Shean Wang, Lu Wang, Weizhu Chen
论文: https://arxiv.org/abs/2106.09685
视频讲解: https://www.youtube.com/watch?v=DhRoTONcyZE
更新 2023 年 2 月: LoRA 现已被 Hugging Face 的 最先进的参数高效微调 (PEFT) 库支持。
LoRA 通过在冻结原始权重的同时学习成对的秩分解矩阵来减少可训练参数的数量。这大大减少了适应特定任务的大型语言模型的存储需求,并实现了在部署期间的高效任务切换,而不引入推理延迟。LoRA 还优于包括适配器、前缀微调和微调在内的几种其他适应方法。
在 GLUE 基准测试中,我们使用 RoBERTa (Liu et al., 2019) base 和 large 以及 DeBERTa (He et al., 2020) XXL 1.5B 获得了与完全微调相当或更优的结果,同时仅训练和存储了部分参数。点击下方的数字下载 RoBERTa 和 DeBERTa 的 LoRA 检查点。
RoBERTa base 微调 | RoBERTa base LoRA | DeBERTa XXL 微调 | DeBERTa XXL LoRA | ||
---|---|---|---|---|---|
可训练参数数量 | 125M | 0.8M | 1.5B | 4.7M | |
MNLI (m-Acc/mm-Acc) | 87.6 | 87.5±.3/86.9±.3 | 91.7/91.9 | 91.9±.1/91.9±.2 | |
SST2 (Acc) | 94.8 | 95.1±.2 | 97.2 | 96.9±.2 | |
MRPC (Acc) | 90.2 | 89.7±.7 | 92.0 | 92.6±.6 | |
CoLA (Matthew's Corr) | 63.6 | 63.4±1.2 | 72.0 | 72.4±1.1 | |
QNLI (Acc) | 92.8 | 93.3±.3 | 96.0 | 96.0±.1 | |
QQP (Acc) | 91.9 | 90.8±.1 | 92.7 | 92.9±.1 | |
RTE (Acc) | 78.7 | 86.6±.7 | 93.9 | 94.9±.4 | |
STSB (Pearson/Spearman Corr) | 91.2 | 91.5±.2/91.3±.2 | 92.9/92.6 | 93.0±.2/92.9±.3 | |
平均 | 86.40 | 87.24 | 91.06 | 91.32 |
注意: 要使用 LoRA 检查点,您仍然需要 Hugging Face 的原始预训练检查点。
微调结果取自 Liu et al. (2019) 和 He et al. (2020)。我们在实验结果中包含了置信区间。请按照 examples/NLU/
中的说明来复现我们的结果。
在 GPT-2 上,LoRA 的表现优于完全微调和其他高效微调方法,例如 适配器 (Houlsby et al., 2019) 和 前缀微调 (Li and Liang, 2021)。我们在 E2E NLG Challenge、DART 和 WebNLG 上进行了评估:
方法 | 可训练参数数量 | E2E (BLEU) | DART (BLEU) | WebNLG (BLEU-U/S/A) | |
---|---|---|---|---|---|
GPT-2 M (微调) | 354.92M | 68.2 | 46.0 | 30.4/63.2/47.6 | |
GPT-2 M (适配器) | 0.37M | 66.3 | 42.4 | 45.1/54.5/50.2 | |
GPT-2 M (前缀) | 0.35M | 69.7 | 45.7 | 44.1/63.1/54.4 | |
GPT-2 M (LoRA) | 0.35M | 70.4±.1 | 47.1±.2 | 46.7±.4/62.1±.2/55. | |
此仓库中包含多个目录: |
- loralib/ 包含
loralib
包的源代码,需安装此包才能运行我们提供的示例; - examples/NLG/ 包含在 GPT-2 中使用我们包实现的 LoRA 示例,可用于复现我们论文中的结果;
- examples/NLU/ 包含在 RoBERTa 和 DeBERTa 中使用我们包实现的 LoRA 示例,能在 GLUE 基准测试中产生有竞争力的结果;
- 参见我们在 GPT-2、RoBERTa 和 DeBERTa v2 中如何使用
loralib
。
快速开始
- 安装
loralib
非常简单:
pip install loralib
# 或者
# pip install git+https://github.com/microsoft/LoRA
- 你可以选择通过使用
loralib
实现的对应模块来替换某些层进行适应性调整。目前我们仅支持nn.Linear
、nn.Embedding
和nn.Conv2d
。我们还支持MergedLinear
,用于单个nn.Linear
表示多个层的情况,如在一些注意力qkv
投影的实现中(详见附加说明)。
# ===== 之前 =====
# layer = nn.Linear(in_features, out_features)
# ===== 之后 =====
import loralib as lora
# 添加一对低秩适应矩阵,秩 r=16
layer = lora.Linear(in_features, out_features, r=16)
- 在训练循环开始之前,只标记 LoRA 参数为可训练的。
import loralib as lora
model = BigModel()
# 这会将所有参数中不包含字符串 "lora_" 的 requires_grad 设置为 False
lora.mark_only_lora_as_trainable(model)
# 训练循环
for batch in dataloader:
...
- 保存检查点时,生成一个仅包含 LoRA 参数的
state_dict
。
# ===== 之前 =====
# torch.save(model.state_dict(), checkpoint_path)
# ===== 之后 =====
torch.save(lora.lora_state_dict(model), checkpoint_path)
- 使用
load_state_dict
加载检查点时,确保设置strict=False
。
# 首先加载预训练的检查点
model.load_state_dict(torch.load('ckpt_pretrained.pt'), strict=False)
# 然后加载 LoRA 检查点
model.load_state_dict(torch.load('ckpt_lora.pt'), strict=False)
现在训练可以像往常一样进行。
附加说明
-
虽然我们专注于一个简单但有效的设置,即仅适应 Transformer 中的
q
和v
投影,但在我们的示例中,LoRA 可以应用于任何预训练权重的子集。我们鼓励你探索不同的配置,例如通过将nn.Embedding
替换为lora.Embedding
来适应嵌入层和/或适应 MLP 层。不同的模型架构和任务可能需要不同的最佳配置。 -
某些 Transformer 实现使用单个
nn.Linear
来处理查询、键和值的投影矩阵。如果希望对单个矩阵的更新限制秩,则必须将其拆分为三个独立的矩阵,或使用lora.MergedLinear
。如果选择拆分层,请务必相应地修改检查点。
# ===== 之前 =====
# qkv_proj = nn.Linear(d_model, 3*d_model)
# ===== 之后 =====
# 拆分(记得相应地修改预训练检查点)
q_proj = lora.Linear(d_model, d_model, r=8)
k_proj = nn.Linear(d_model, d_model)
v_proj = lora.Linear(d_model, d_model, r=8)
# 或者,使用 lora.MergedLinear(推荐)
qkv_proj = lora.MergedLinear(d_model, 3*d_model, r=8, enable_lora=[True, False, True])
- 与 LoRA 一起训练偏置向量可能是一种成本效益高的方法,可以在任务性能上挤出更多性能(如果你仔细调整学习率)。虽然我们在论文中没有彻底研究其效果,但我们在
lora
中使其易于尝试。你可以在调用mark_only_lora_as_trainable
时传递 "all" 或 "lora_only" 来标记某些偏置为可训练的。保存检查点时,记得传递相应的bias=
参数给lora_state_dict
。
# ===== 之前 =====
# lora.mark_only_lora_as_trainable(model) # 不训练任何偏置向量
# ===== 之后 =====
# 训练所有与 LoRA 应用的模块相关联的偏置向量
lora.mark_only_lora_as_trainable(model, bias='lora_only')
# 或者,我们可以训练模型中的*所有*偏置向量,包括 LayerNorm 的偏置
lora.mark_only_lora_as_trainable(model, bias='all')
# 保存检查点时,使用相同的 bias= ('all' 或 'lora_only')
torch.save(lora.lora_state_dict(model, bias='all'), checkpoint_path)
- 调用
model.eval()
将触发将 LoRA 参数与对应的预训练参数合并,从而消除后续前向传播的额外延迟。再次调用model.train()
将撤销合并。可以通过向 LoRA 层传递merge_weights=False
来禁用此功能。
联系方式
如果有任何问题,请联系我们或发布问题。
有关 loralib
包的问题:
- Edward Hu (edward@edwardjhu.com)
- Phillip Wallis (phwallis@microsoft.com)
- Weizhu Chen (wzchen@microsoft.com)
GPT-2 示例:
- Phillip Wallis (phwallis@microsoft.com)
- Yelong Shen (yeshe@microsoft.com)
RoBERTa/DeBERTa 示例:
- Lu Wang (luw@microsoft.com)
致谢
感谢 Jianfeng Gao, Jade Huang, Jiayuan Huang, Lisa Xiang Li, Xiaodong Liu, Yabin Liu, Benjamin Van Durme, Luis Vargas, Haoran Wei, Peter Welinder, 和 Greg Yang 按字母顺序提供的宝贵反馈。
引用
@inproceedings{
hu2022lora,
title={Lo{RA}: Low-Rank Adaptation of Large Language Models},
author={Edward J Hu and Yelong Shen and Phillip Wallis and Zeyuan Allen-Zhu and Yuanzhi Li and Shean Wang and Lu Wang and Weizhu Chen},
booktitle={International Conference on Learning Representations},
year={2022},
url={https://openreview.net/forum?id=nZeVKeeFYf9}
}
贡献
本项目欢迎贡献和建议。大多数贡献要求你同意一个贡献者许可协议(CLA),声明你有权利并实际授予我们使用你贡献的权利。详情请访问 https://cla.opensource.microsoft.com。
当你提交拉取请求时,CLA 机器人将自动确定你是否需要提供 CLA,并适当装饰 PR(例如状态检查、评论)。只需按照机器人提供的指示操作。你只需在所有使用我们的 CLA 的仓库中执行一次此操作。
本项目采用了 Microsoft 开源行为准则。 更多信息请参见 行为准则常见问题 或联系 opencode@microsoft.com 获取其他问题或评论。