跳到主要内容

5.7 LoRA:给大模型贴便利贴

前六节讲的都是「大厂怎么做」​

到这里,后训练这条流水线你已经全看过了:SFT 上示范课、RLHF 训裁判、PPO 拔河、DPO 抄近道、RLVR 逼出推理能力。

但有一件事一直没说破:这条流水线,你自己跑不动。

问题不在算法——SFT 的代码几十行就能写完。问题在显存。第 4 章算过预训练的账,微调的账其实同样吓人:一个 70 亿参数的模型,光是把它「摆开」准备训练,就要一百多 GB 显存。而 2026 年一张顶配消费级显卡只有二三十 GB。

差了整整一个数量级。

这一节和接下来两节,讲的就是怎么把这个数量级抹平——让一张卡、几个小时、几十块钱,也能把一个大模型调成你想要的样子。

为什么微调这么吃显存​

先搞清楚显存到底被谁吃掉了。很多人以为「模型 14 GB,那微调就要 14 GB 多一点」——差得远。

训练时,每个参数身上挂着的不止它自己:

挂件干什么用占多少
参数本身就是模型2 字节
梯度这一步该往哪调2 字节
优化器状态Adam 记的「惯性」和「步长历史」,外加一份高精度参数副本12 字节

合计 16 字节/参数——参数本身只占了八分之一,剩下七份全是「为了训练它」而临时背上的行李。7B 模型于是从 14 GB 膨胀到 112 GB。

看清这笔账,省钱的思路就自己浮出来了:参数本身省不掉(模型总得装进显存),但那七份行李是按「要训练的参数个数」收费的。

如果只训练其中很小一部分呢?

便利贴的主意​

2021 年,微软的研究者给出的答案叫 LoRA(Low-Rank Adaptation,低秩适配):

原来的参数一个都不动,全部冻结。另外贴一张薄薄的「修正贴纸」,只训练这张贴纸。

用石碑打比方:微调一个模型,就像修改一块刻好的石碑。全参微调是把整块石碑磨平重刻——费工费料。LoRA 的做法是在石碑旁边贴一张便利贴,写上「此处应改为……」。读的时候把石碑和便利贴一起读,效果等价;但你只需要写那张便利贴。

关键在于这张便利贴可以做得极薄。原本一个 4096 × 4096 的参数矩阵有 1600 万个数字,LoRA 用两个瘦长条替代它的修正量:一个 4096 × 8,一个 8 × 4096——加起来只有 6.5 万个数字,不到原来的 0.4%。

这个「8」就是 LoRA 的秩(rank,记作 rr),是你唯一要调的核心旋钮:rr 越大,便利贴越厚、表达力越强、也越费显存。

亲手算这笔账​

🎮 动手实验
LoRA 账本:便利贴到底省了什么
左边选模型和训练方式,右边看三笔账:要训多少参数、要占多少显存、存下来的文件有多大。先用默认配置对比「全参微调」和「LoRA」,再把底座精度一路压到 NF4。
可训练参数
8.4 M
占全部参数
0.13%
训练显存
15.9 GB
适配器文件
16.0 MB
全参微调(基准)权重 + 梯度 + 优化器状态:107 GB激活与临时开销:2.34 GB110 GB当前方案:LoRA(底座 bf16)冻结的底座权重:13.4 GB便利贴的权重/梯度/优化器:0.13 GB激活与临时开销:2.34 GB15.9 GB
冻结底座可训练状态(权重/梯度/优化器)激活与临时
LoRA(底座 bf16):Q、K、V、O 四个投影都贴。比只改 Q、V 表达力强一些,仍然很省。 秩 r = 8 时只训 8.4 M 个参数(0.13%), 显存 15.9 GB——比全参微调省 6.9 倍,一张16 GB 显卡就够了。 训完只需保存 16.0 MB 的适配器,底座原封不动。
💡 要点:LoRA 省的不是底座权重(冻结的底座照样要整个装进显存),而是梯度和优化器状态——它们按可训练参数收费,而可训练参数被砍掉了三个数量级。所以 LoRA 把显存从「16 字节/参数」压到「2 字节/参数 + 一点点」,QLoRA 再把那个 2 压到 0.5。
数字为量级估算(口径:AdamW 混合精度,全参 = 16 字节/参数,即 bf16 权重 2 + bf16 梯度 2 + fp32 主权重与 m、v 共 12;激活按「开梯度检查点、batch=1、序列 2K」粗估)。为教学简化,K/V 投影按 d×d 计——真实模型用 GQA 会更小。

请按顺序做四个实验:

实验 ①:先看全参微调有多贵。 保持「7B」,点「全参微调(基准)」。看那个数字——110 GB 左右,一张 80 GB 的数据中心卡都装不下,得上两张。再看条形图:橙色那一大条就是「权重 + 梯度 + 优化器状态」,16 字节/参数的账全在这里。

实验 ②:换成 LoRA,看数字塌下来。 点「LoRA(底座 bf16)」。显存从 110 GB 掉到 约 16 GB——一张消费级卡就够了。注意条形图变了形状:紫色的「冻结底座」占了绝大部分,橙色的「可训练状态」缩成一条几乎看不见的线。这就是 LoRA 的全部秘密:底座省不掉,但行李没了。

实验 ③:拖动秩 r,感受它的分量。 把 r 从 1 拉到 256,盯着「可训练参数」和「显存」。你会发现一件重要的事:r 翻 32 倍,显存几乎没动——因为显存的大头是那个冻结的底座,便利贴再厚也只是零头。所以调 r 主要是在权衡「表达力 vs 过拟合」,而不是在省显存。

实验 ④:看适配器文件有多小。 保持 r = 8、「整个注意力」,看「适配器文件」那一栏——十几 MB。而完整模型是 14 GB。这意味着你可以为一百个不同任务各训一张便利贴,全部加起来还不到底座的十分之一。

便利贴为什么够用​

一个自然的疑问:把一个 1600 万参数的修正量,硬压成 6.5 万个数字,信息不会丢吗?

会丢,但丢的大多是你本来就不需要的。LoRA 论文的观察是:微调对模型做的改动,本身就集中在少数几个「方向」上——你教它说客服口吻,改的是一种整体倾向,不是一千六百万个互不相关的细节。既然改动本身就是「低秩」的,用低秩的贴纸去装它,自然装得下。

这也解释了 LoRA 的适用边界:改倾向很在行,灌知识很吃力(下一节和 5.9 节还会展开)。

还有两个白赚的好处:

  • 推理时零额外开销:训完可以把便利贴的内容加回石碑(W+BAW + BA 合成一个新矩阵),得到一个和原模型结构完全相同的模型,推理速度一模一样。
  • 热插拔:也可以不合并,让一个底座同时挂多张便利贴——客服贴纸、翻译贴纸、写代码贴纸,按请求切换。服务一百个定制模型,显存里只有一份底座。
这个类比在哪里不准确?

「贴便利贴」容易让人以为 LoRA 是在原有输出之外补一句话——不是。便利贴不是附加在结果后面,而是参与到每一层的运算里:石碑和便利贴的结果是逐层相加的,改的是模型的内部计算过程,不是最终答案的措辞。

另一个偏差:便利贴听起来「随便贴哪都行」,实际上贴在哪些矩阵上(只贴注意力?连 FFN 一起贴?)对效果影响不小,是要调的。最后,LoRA 也不是永远和全参微调等价——任务离底座原本的能力越远(比如教一门它几乎没见过的语言),低秩这个假设就越勉强,差距会显出来。

小结​

本节要点
  • 微调吃显存的大头不是权重,是梯度 + 优化器状态——AdamW 混合精度下合计约 16 字节/参数,7B 模型要 112 GB。
  • LoRA:冻结原参数,只训一张低秩「便利贴」BABA,可训练参数降到 0.1% 量级,显存从 16 字节/参数压到 2 字节/参数 + 一点点。
  • 秩 rr 是核心旋钮,但它几乎不影响显存(大头是冻结的底座)——调它是在权衡表达力与过拟合。
  • 白赚两样:训完可合并回去做到推理零开销,不合并则可热插拔多张便利贴共用一个底座。
  • 边界:改行为倾向在行,灌新知识吃力;省的是显存不是算力,训练速度不会同比变快。
📝 动手自测0/3
1. LoRA 主要省下了哪部分显存?
2. 把 LoRA 的秩 r 从 8 调到 128,最主要的影响是什么?
3. 为什么 LoRA 要把矩阵 B 初始化为全零?

延伸阅读​