LoRA: Low-Rank Adaptation of Large Language Models
原论文链接:arXiv:2106.09685
项目主页:GitHub - microsoft/LoRA
研究背景
随着大型语言模型(LLMs)如 GPT-3 的广泛应用,如何高效地将其适配到特定任务成为了一个关键问题。传统的微调方法需要更新模型中所有的参数,这在计算资源和存储方面都带来了巨大的挑战。为了解决这一问题,微软研究院提出了 LoRA(Low-Rank Adaptation)方法,旨在以更低的计算成本实现对大型模型的高效微调。
核心思想
LoRA 的核心理念是:在微调过程中,模型参数的更新可以被近似为一个低秩矩阵的形式。具体而言,LoRA 冻结预训练模型的原始权重,仅在每一层中引入可训练的低秩矩阵,从而大幅减少需要更新的参数数量。
通过这种方式,LoRA 实现了以下目标:
- 参数高效:相比全量微调,LoRA 将可训练参数数量减少了约 10,000 倍。
- 内存节省:GPU 内存需求降低了约 3 倍。
- 性能保持:在多个任务上,LoRA 的性能与全量微调相当,甚至更优。
方法流程详解
LoRA 的实现过程如下:
- 冻结原始权重:预训练模型的原始权重保持不变。
- 引入低秩矩阵:在每一层中,添加两个可训练的低秩矩阵 A 和 B,使得权重更新可以表示为 $\Delta W = A \times B$,其中 A 的维度为 $d \times r$,B 的维度为 $r \times d$,r 是远小于 d 的秩。
- 训练低秩矩阵:仅训练 A 和 B 两个矩阵,其他参数保持不变。
- 推理阶段:在推理时,将 $\Delta W$ 加到原始权重上,得到更新后的权重。
这种方法的优势在于,只需训练少量参数即可实现模型的适配,极大地降低了计算成本。
实验设置与结果
研究团队在多个模型和任务上对 LoRA 进行了评估,包括 RoBERTa、DeBERTa、GPT-2 和 GPT-3。实验结果表明,LoRA 在以下方面表现出色:
- 参数效率:在 GPT-3 175B 上,LoRA 将可训练参数数量减少了约 10,000 倍。
- 内存使用:GPU 内存需求降低了约 3 倍。
- 性能表现:在多个任务上,LoRA 的性能与全量微调相当,甚至更优。
此外,LoRA 的训练吞吐量更高,且在推理阶段不会引入额外的延迟。
总结
LoRA 提供了一种高效的微调大型语言模型的方法,显著降低了计算资源的需求,同时保持了模型的性能。其核心思想是利用低秩矩阵近似参数更新,从而实现参数高效的微调。
如何使用
在实践中,使用 LoRA(Low-Rank Adaptation)对大型语言模型进行高效微调,可以显著减少训练所需的参数和计算资源。以下是一个典型的 LoRA 微调流程,适用于如 LLaMA、GPT-2、BERT 等模型,结合了 Hugging Face Transformers 和 PEFT(Parameter-Efficient Fine-Tuning)库的使用。
1. 安装必要的库
确保安装了以下 Python 库:
1 | pip install torch transformers datasets peft |
2. 加载预训练模型和分词器
以 LLaMA 模型为例,加载预训练模型和对应的分词器:
1 | from transformers import AutoTokenizer, AutoModelForCausalLM |
3. 应用 LoRA 配置
使用 PEFT 库配置 LoRA 参数,并将其应用到模型中:
1 | from peft import get_peft_model, LoraConfig, TaskType |
在此配置中:
r
:低秩矩阵的秩,控制参数的压缩程度。lora_alpha
:缩放因子,影响学习速率。target_modules
:指定应用 LoRA 的模块,通常选择自注意力机制中的查询(q_proj)和键(v_proj)投影层。
4. 冻结原始模型参数
为了实现参数高效微调,冻结预训练模型的原始参数,仅训练 LoRA 模块的参数:
1 | for param in model.base_model.parameters(): |
5. 准备训练数据
使用 Hugging Face 的 datasets
库加载和预处理训练数据:
1 | from datasets import load_dataset |
根据任务需求,进行必要的数据清洗和格式转换。
6. 定义训练参数和训练器
设置训练参数,并使用 Trainer
进行模型训练:
1 | from transformers import Trainer, TrainingArguments |
7. 开始训练
启动训练过程:
1 | trainer.train() |
8. 保存和加载 LoRA 模型
训练完成后,保存 LoRA 模型的权重:
1 | model.save_pretrained("lora-llama") |
在需要时,加载保存的模型进行推理或进一步训练:
1 | from peft import PeftModel |