LoRA(Low-Rank Adaptation of Large Language Models,大语言模型的低秩自适应)是一种在大模型微调(Fine-tuning)领域极具革命性的技术。简单来说,LoRA 是一种“四两拨千斤”的微调方法。它允许我们在不更新大模型原有巨量参数的情况下,通过引入极少量的额外参数来适配特定的下游任务,从而极大地降低了训练成本和硬件门槛。
背景:为什么要发明 LoRA?
在 LoRA 出现之前,如果你想让一个通用的大模型(比如 LLaMA 或 GPT-3)学会某个特定领域的知识(比如法律、医疗或特定的写作风格),通常有两种选择,但都有明显缺陷:
- 全量微调(Full Fine-tuning):
- 做法: 重新训练模型的所有参数(比如 70 亿或 1750 亿个参数)。
- 痛点: 成本极高。需要巨大的显存(VRAM)和计算资源,且每个新任务都要保存一份完整的巨大模型文件,存储压力极大。
- 传统的轻量化微调(如 Adapter 或 Prefix-tuning):
- 做法: 在模型层之间插入小的神经网络层,或在输入端增加特殊的 Token。
- 痛点: 往往会增加模型的推理延迟(Inference Latency),或者效果不如全量微调好。
LoRA 的出现,就是为了解决“既想要全量微调的效果,又想要极低的训练成本,还不想增加推理延迟”这一“既要又要还要”的难题。
核心原理:LoRA 是如何工作的?
LoRA 的核心思想基于一个数学假设:模型在适应新任务时,其参数权重的改变量本质上是“低秩”(Low-Rank)的。
通俗的解释如下:
旁路设计(Bypass)
想象大模型的某个权重矩阵是一个巨大的正方形($W$)。在微调时,我们本来需要修改这个大正方形里的每一个数字。 LoRA 的做法是:冻结这个大正方形不动,在旁边挂两个非常“瘦”的小矩形矩阵($A$ 和 $B$)。
矩阵分解(Matrix Decomposition)
- 假设原模型的权重矩阵维度是 $1000 \times 1000$(这就由 100 万个参数)。
- LoRA 不去动这 100 万个参数,而是训练两个小矩阵:
- 矩阵 $A$:$1000 \times r$
- 矩阵 $B$:$r \times 1000$
- 这里的 $r$ 被称为秩(Rank),通常设得很小(比如 8、16 或 64)。
- 当 $r=8$ 时,这两个小矩阵的参数量只有 $1000 \times 8 \times 2 = 1.6万$。
- 对比: 100 万 vs 1.6 万,参数量减少了 98% 以上。
推理与融合
数据的流向变成了两条路:
- 数据进大模型原权重 $W$,算出结果。
- 数据进 LoRA 的旁路 $A \times B$,算出增量。
- 最终结果 = 原结果 + 增量。
最妙的是,在推理(使用)阶段,根据线性代数的原理,我们可以直接把 $A \times B$ 的结果加回到原权重 $W$ 中($W_{new} = W + BA$)。这样,模型结构完全没变,推理速度没有任何降低。
LoRA 的核心优势
- 极低的显存占用(VRAM Efficiency):
- 由于不需要计算和存储原有大模型参数的梯度,显存占用可以降低 50% 甚至更多。这使得在消费级显卡(如 RTX 3090/4090)上微调 7B 甚至更大的模型成为可能。
- 便于存储和分享(Storage):
- 全量微调产生的模型文件可能有几十 GB。
- LoRA 微调产生的权重文件通常只有 几 MB 到 几百 MB。
- 这也是为什么 Civitai(C站)和 HuggingFace 上有成千上万个 LoRA 模型的原因——大家可以像分享插件一样分享模型。
- 无推理延迟(No Inference Latency):
- 如前所述,训练完后,LoRA 权重可以合并回原模型,合并后的模型与原模型运行速度完全一致。
- 快速切换任务(Task Switching):
- 你可以保留一个基础大模型(Base Model),然后根据需要动态加载不同的 LoRA 模块。比如上一秒加载“写代码 LoRA”,下一秒切换成“写武侠小说 LoRA”,无需重新加载整个庞大的基座模型。
通俗类比
为了更好地理解,我们可以打个比方:
- 大模型(Base Model) 就像一本印刷精美的百科全书。
- 全量微调 就像是把整本书重新排版、重新印刷一遍,不仅费钱,而且每改一次都要印一本新书。
- LoRA 就像是在百科全书的某些页面上贴了透明便利贴(Post-it notes)。
- 你在便利贴上写下新的修正内容或新知识。
- 阅读时,透过便利贴看到的是修正后的内容。
- 便利贴非常轻薄(参数少)。
- 如果你想换个主题,只需要撕下旧便利贴,换上新的即可,书本身(基座模型)不用动。
- 最后,如果你确定这些修改是永久的,你可以把便利贴的内容直接印在书页上(权重合并)。
peft 库示例
Hugging Face peft (Parameter-Efficient Fine-Tuning) 库示例
from peft import LoraConfig, get_peft_model, TaskType
from transformers import AutoModelForCausalLM
# 1. 加载基础模型
model = AutoModelForCausalLM.from_pretrained(`meta-llama/Llama-2-7b-hf`)
# 2. 定义 LoRA 配置
peft_config = LoraConfig(
task_type=TaskType.CAUSAL_LM, # 任务类型:因果语言模型
inference_mode=False, # 训练模式
r=16, # 秩
lora_alpha=32, # alpha通常是r的2倍
lora_dropout=0.05,
target_modules=[`q_proj`, `v_proj`], # 仅在 Q 和 V 上加 LoRA
bias=`none`, # 不训练 bias
)
# 3. 将 LoRA 适配器注入模型
model = get_peft_model(model, peft_config)
# 4. 打印可训练参数量(验证配置是否生效)
model.print_trainable_parameters()最后
LoRA 是目前大模型微调领域事实上的标准配置(De facto standard)。
它打破了大模型训练被大公司垄断的局面,让个人开发者、研究人员和中小企业都能以低廉的成本定制属于自己的大模型。无论是在 AI 绘画(Stable Diffusion)还是大语言模型(LLM)领域,LoRA 都是推动 AI 社区繁荣的最关键技术之一。
最近更新
最新评论