跳到主要内容

5.8 QLoRA:4 位底座 + 16 位便利贴

省完行李,轮到石碑了​

上一节的实验 ② 留下一张很有说服力的图:换成 LoRA 之后,橙色的「行李」缩成了一条细线,而紫色的「冻结底座」占满了整根条形图。

这张图其实是在提问:既然行李已经省到极致,剩下的大头是那块石碑——石碑本身,非得用 16 位精度刻不可吗?

这个问题你已经有答案了。6.3 节会讲(如果你按顺序读,那就是先在这里剧透):大模型对权重上的小误差出奇地迟钝,int8 几乎无损,int4 配合分组缩放也能保住绝大部分能力。

那把这两件事拼起来会怎样?底座量化到 4 位、便利贴保持 16 位。 这就是 2023 年华盛顿大学提出的 QLoRA。

一个反直觉的组合​

初听会觉得别扭:训练不是最讲精度的环节吗?把底座压成 4 位,梯度还能算准?

能。关键在于被压的和被训的是两拨参数:

  • 底座是 4 位、且冻结——它只负责「读」。前向计算时临时解压成 16 位参与运算,算完就丢,显存里始终只存 4 位的那一份。既然它一个字都不用改,量化误差就不会在训练中被反复累积放大。
  • 便利贴是 16 位、且可训练——它负责「写」。所有梯度和优化器状态都落在这张贴纸上,精度分毫未减。

一句话:把精度花在需要更新的地方,把压缩用在只读的地方。

再算一次账​

回到上一节那台计算器,这次只动「底座精度」这一档:

🎮 动手实验
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」、r = 8、「整个注意力」,依次点 LoRA(底座 bf16) → LoRA(底座 int8) → QLoRA(底座 NF4 4 位),盯着「训练显存」那一栏:约 16 GB → 9 GB → 6 GB。每按一次,紫色的底座条正好短一半(13.4 → 6.7 → 3.35 GB)——省下来的全是底座。到 NF4 这一档,一张 8 GB 的入门显卡都装得下 7B 微调了。

实验 ⑥:把模型换成 70B。 点「70B(旗舰级)」,然后对比:

  • 全参微调:1100 GB 以上——十几张 80 GB 卡起步,这是大厂的配置;
  • LoRA(bf16 底座):约 156 GB——还是要两张卡;
  • QLoRA(NF4):约 51 GB——一张 80 GB 卡搞定。

这一格的跨越,就是 QLoRA 论文的核心成果:把「微调 65B 需要一整个机柜」变成「一张卡,一晚上」。论文自己的说法是从 780 GB 以上降到 48 GB 以下(他们的全参基线没算 fp32 主权重那一份副本,口径比本计算器的 16 字节略松——这也提醒你,看到任何显存数字都要先问清口径)。

三个让它成立的零件​

QLoRA 不只是「量化 + LoRA」两行代码拼一起,论文里有三个具体发明:

NF4(4 位 NormalFloat)。 普通的 int4 把 16 个刻度均匀摆开,但神经网络的权重是钟形分布的——中间挤满了值,两头几乎没有。均匀刻度等于把一半的刻度浪费在了空旷地带。NF4 改成按分布摆刻度:中间密、两头疏,让每个刻度平均分到差不多数量的权重。同样是 4 位,信息利用率更高。

双重量化。 分组量化要为每 64 个权重存一个缩放系数,这些系数本身也是浮点数,摊下来约 0.5 位/参数——听着不多,65B 模型上就是 3 GB。QLoRA 的做法很直接:把这些缩放系数本身也量化一遍,省下约 0.37 位/参数。

分页优化器。 训练时偶尔会有显存尖峰(比如某个特别长的样本),一次尖峰就 OOM 崩掉,几小时白跑。分页优化器借用显卡驱动的统一内存机制,在尖峰时把优化器状态临时挪到内存里,扛过去再挪回来——像操作系统的虚拟内存。它不省显存,它省的是你的时间。

这个「免费午餐」在哪里要收费?

两笔账不能忘。

第一笔是速度。 4 位底座在每次前向计算时都要临时解压回 16 位,这个解压是实打实的额外计算。QLoRA 通常比 bf16 底座的 LoRA 慢 20% ~ 40%(因模型和实现而异)。你用时间换了显存,不是白拿。

第二笔是精度。 QLoRA 论文的实验结论是「在他们测的任务上匹配 16 位微调的效果」——但这是 2023 年在特定模型、特定评测上的结论,不是普适定律。在数学、代码这类对精度敏感的任务上,4 位底座的退化可能明显得多(这一点和 6.3 节讲量化时的提醒是同一件事)。有条件就跑一次 A/B:同样的数据,bf16 底座和 NF4 底座各训一版,用你自己的评测集比一比。

小结​

本节要点
  • LoRA 省掉行李之后,显存大头变成冻结的底座——QLoRA 把它量化到 4 位,再砍四分之三。
  • 分工是关键:只读的底座压到 4 位,可训练的便利贴保持 16 位——精度花在需要更新的地方。
  • 三个零件:NF4(按正态分布摆刻度)、双重量化(把缩放系数也量化,省约 0.37 位/参数)、分页优化器(扛住显存尖峰不崩)。
  • 效果:65B 的微调从一整个机柜压进一张卡(论文口径 780 GB → 48 GB 以下,2023)。
  • 收费两笔:解压带来 20%~40% 的速度损失;精度在敏感任务上可能退化,有条件要跑 A/B。
📝 动手自测0/3
1. QLoRA 为什么可以把底座压到 4 位而不严重影响训练?
2. NF4 相比普通 int4 的改进是什么?
3. 关于 QLoRA 的代价,下面哪个说法是对的?

延伸阅读​