我最早以为,微调大模型就是把预训练权重全部更新一遍。直到我读完LoRA论文,才发现自己错得离谱——原来我们只需要改一组小得多的矩阵,就能达到几乎相同的效果。这篇文章我想聊聊LoRA(Low-Rank Adaptation,低秩适配)到底做了什么,以及它为什么能这么省。

先感受一下全量微调的代价。假设你想把GPT-3(1750亿参数)微调成你公司的客服机器人。训练时,你需要为每个参数保存梯度、一阶动量、二阶动量。仅Adam优化器的状态就要占用数倍于模型本身的内存,光这个就能吃掉几百GB显存。就算你租得起8块A100,训练时间也长得让人崩溃。
更麻烦的是,每次微调都会得到一份全新的175B模型。如果同时服务十个任务,就得存十份模型,部署成本直接翻十倍。
这不是微调,这是换发动机。LoRA就是来修这个问题的。
LoRA的思路特别简单:预训练模型的权重W在微调过程中保持不变,只学习一个低秩的增量ΔW。这个ΔW被分解成两个小矩阵的乘积:ΔW = B × A。其中A的维度是r×d,B的维度是d×r,r远小于d。
直观上,就像你有一台出厂校准好的精密仪器。让它做新任务时,不需要拆开重装,只需要在外面加一个小旋钮,旋动旋钮就能调节输出。LoRA就是那个旋钮。
训练时,只有A和B会被优化,W和它的梯度都不参与。初始时,A按高斯分布初始化,B初始化为零,这样ΔW一开始是零,模型输出和预训练时完全一样,保证了训练的稳定。
用代码表示,原本的线性层 y = Wx 变成了:
ΔW = B @ A # A: r×d, B: d×r; y = Wx + ΔWx
参数数量也很直观:假设一个权重矩阵是1000×1000,r=8,LoRA要训练的参数是1000×8×2 = 16000个,而原矩阵有100万个参数。节省了98.4%。所以标题说“几百个参数”有点夸张——对于很小的层,比如64×64,r=4时确实是512个参数;但对于大模型,LoRA的参数通常是几百万,只是相比原来的几十亿,缩小了几个数量级。
你可能会问:为什么一个高维权重矩阵的更新可以用低秩矩阵近似?直觉是,预训练模型已经是一个高度紧凑的特征提取器。在微调特定任务时,它需要的方向变化其实非常有限,集中在一个低维子空间里。
这有理论基础。先前的研究发现,预训练模型在微调时,其权重更新的本质维度(intrinsic dimension)很低。LoRA论文也做了实验:即使把秩r设为4,GPT-3在多个NLP任务上的表现已经能接近甚至超过全量微调。
“We take inspiration from Li et al. (2018) which show that learned over-parametrized models in fact reside on a low intrinsic dimension. We hypothesize that the change in weights during model adaptation also has a low "intrinsic rank", leading to our proposed Low-Rank Adaptation (LoRA) approach.”(我们受到Li等人2018年工作的启发,他们发现过度参数化的模型实际上存在于一个低的内在维度上。我们假设模型适应过程中的权重变化也具有较低的“内在秩”,由此提出了LoRA方法。)——LoRA论文
那LoRA和全量微调、Adapter这些方法比,到底强在哪?看这张表:
| 方法 | 可训练参数占比 | 推理额外开销 | 任务切换 |
|---|---|---|---|
| 全量微调 | 100% | 无 | 需保存整个模型 |
| Adapter | 约3%–6% | 有(每层额外计算) | 每任务保存适配器 |
| Prefix-tuning | 约0.1% | 有(序列变长) | 每任务保存前缀 |
| LoRA | 可低至0.01% | 无(可合并) | 只需保存小矩阵 |
除了参数少,LoRA还有几个很实用的优点:
- 可插拔:同一份预训练模型可以同时挂多个LoRA模块,推理时按需切换。例如一个模型既能当客服,也能当法律助手,只需换一组A和B矩阵。
- 省显存:因为不需要计算和存储预训练权重的梯度,可以用更小的GPU微调更大的模型。配合量化(如QLoRA),一张消费级显卡就能微调65B模型。
- 推理零开销:训练完成后,可以计算W’ = W + BA,然后把W’存下来。推理时直接使用W’,不会引入任何额外计算。
如果你想在代码中使用LoRA,Hugging Face的PEFT库提供了现成实现。
我最初有个误解,以为LoRA是一种近似,一定会损失模型能力。但后来看了一些实验和讨论,才想通:低秩约束其实相当于一种正则化,可以避免在数据量很小的任务上过拟合。在某些场景下,LoRA的效果反而比全量微调更好。
这个认知转变让我意识到,大模型的微调并不是“参数越多越好”,关键在于如何高效地利用预训练模型已有的知识。
以下是我经常被问到的问题,一并解答:
LoRA的秩r怎么选?
论文中的实验显示,r在4到64之间都能取得不错的效果。对于大多数任务,r=8就够了。但如果你要注入大量新知识,可以适当增大r。实际使用时,最好在验证集上试几个值。
LoRA只能用在注意力层吗?
不,LoRA可以作用在任何线性层。但为了效率,大多数实现只对注意力中的Q、V矩阵应用LoRA。论文实验表明,同时对Q、K、V、O四个矩阵都加LoRA效果更好,但参数也会增加。所以这是一个权衡。
LoRA和Adapter有什么区别?
Adapter是在Transformer层之间插入额外的前馈网络,推理时需要串行计算,会带来额外延迟。LoRA则是并行地改变原有权重,训练后可以合并回去,推理时完全没有额外开销。另外,Adapter改变了模型结构,而LoRA不改变。
LoRA能减少多少显存?
以GPT-3 175B为例,全量微调光是模型参数和优化器状态就需要数TB显存。使用LoRA后,可训练参数只有几百万,配合梯度检查点等技术,可以降到几百GB以内。当然,具体节省幅度取决于应用范围和秩。
最后聊聊LoRA的边界。对于需要大量新知识的任务,比如让模型学习一种全新的语言,低秩更新可能不够,因为新知识可能无法被压缩到低秩子空间。另外,r的选择很关键,太小可能欠拟合,太大又会失去节省参数的优势。
但无论如何,LoRA已经改变了大规模模型微调的玩法。它把“微调大模型”从少数公司的专利,变成了个人开发者也能尝试的事情。结合量化技术,未来我们或许能在手机上实时适配个性化模型——那将是另一番景象。
原创文章,作者:guanweilu,如若转载,请注明出处:https://guanweilu.cn/article/230.html