7、QLoRA 量化微调
本节先认识用途: QLoRA 进一步节省基础权重的存储,但仍有其他训练开销。本课程首轮不启用量化,编码细节属于进阶选读。
本课程先保持“微调方法”为 lora、“量化等级”为 none,使用 Qwen3-0.6B 练习普通 FP16 LoRA。更换较大的模型后,如果基础权重占用过多显存,再考虑下面的 QLoRA;不要仅因页面提供量化选项就全部开启。
QLoRA 可以先理解为“量化版的 LoRA”。它仍然训练 LoRA Adapter;不同之处在于,训练时加载的基础模型会以更低位数保存,从而减少基础模型权重的显存占用。
这里的量化(quantization),是用更少的比特近似保存模型参数。例如原来一个权重用 16 bit 保存,量化后用 4 bit 编码表示;省下了空间,但数值可能出现近似误差,任务效果仍需验证。
<details> <summary>选读图解:全参数微调、LoRA 与 QLoRA 的完整对照</summary>7.1 量化与近似误差
量化可以理解为:准备一组有限的代表值,把每个原数替换为接近的代表值,并保存对应编号。4 bit 能表示 16 个编号,因此不能精确保留任意小数。计算时根据编号还原近似值,这一步叫作反量化。
先只跟踪一个数:在下面的等间距量化教学例子中,原来的 0.27 经过“选一个接近的代表值 → 保存编号和缩放因子 → 还原”,得到的是 0.304,相差 0.034。
为什么还原后不再是 0.27?因为保存的是有限选项中的编号,没有保留这个数的全部信息。量化用近似换空间,反量化取回的是近似值。 具体编号怎样算、QLoRA 使用的代表值有什么不同,见下方选读。
将上面的教学例子展开,假设一组参数是:
0.27,0.58,-0.75,1.52这一组绝对值最大的数是 1.52。我们把它保留下来作为缩放因子,再把各数除以它,将数值缩到 -1~1 的范围。这里只跟踪第一个数 0.27:
| 步骤 | 计算或保存的内容 | 这一步做了什么 |
|---|---|---|
| 缩放到统一范围 | 0.27 ÷ 1.52 ≈ 0.1776 | 先变成便于查表的小数 |
| 找最近的代表值 | 0.1776 → 0.2 | 在 -1~1 的 16 个等间距代表值中选最近的一个 |
| 保存编号 | 0.2 对应编号 9,二进制为 1001 | 编号只需 4 bit;同时保留这组的缩放因子 |
| 反量化 | 0.2 × 1.52 = 0.304 | 用编号查回代表值,再恢复到原来的量级 |
16 个代表值按从小到大编号为 0~15,编号 9 对应 -1 + 9 × 2/15 = 0.2。编号保存的是“选了哪个代表值”,并没有另外记住原数 0.1776。
所以,还原后是 0.304,不是原来的 0.27,绝对误差为 0.034。反量化是恢复近似值,不是无损解压。 模型是否还能完成任务,要继续评估,不能仅凭文件变小就判断效果。
这里使用的是等间距量化示例。QLoRA 中常用的 NF4 不是这张等间距表,而是针对权重分布设计的一组非等间距代表值;这里只借简单数字理解“存编号、存缩放因子、存在近似误差”。QLoRA 论文
<details> <summary>拓展计算:为什么 4-bit 的实际存储还包含额外开销</summary>除了参数的编号,还要保存把这一组数恢复到原量级的缩放因子等辅助信息。假设四个数为一组,原来都用 FP16 保存,一共是 4×16=64 bit。现在四个 4-bit 编号占 16 bit;若这一组的缩放因子用 FP32 保存,还要加 32 bit,合计 48 bit。即使暂时不计其他开销,这个小例子的总量也不是原来的四分之一。
四个数分一组只是为了方便计算。若改成每 64 个数共用一个 FP32 缩放因子,编号与缩放因子共占 64×4+32=288 bit,相当于每个数平均 4.5 bit。这样就能看出:缩放因子也占空间,只是被一组数分摊了。这里仍未计入码表等其他开销,也没有加入下一节的双重量化。
7.2 QLoRA 的显存开销
回到第 5 节的显存组成:LoRA 已经减少了需要更新的参数及相关状态,QLoRA 进一步压缩的是仍需加载的基础模型权重。Adapter 的梯度、优化器状态和中间计算结果仍然需要空间。
训练时,量化基础权重保持冻结,需要计算时按实现恢复到相应计算精度参与运算;可训练的 LoRA 参数并不是简单地全变成 4-bit。因此不能只看“模型已经量化”就认定一定能训。序列长度、单卡 batch、训练工具的实现和实际 GPU,仍会决定能否稳定运行。
还要区分报错发生在哪一步:基础权重尚未加载完就显存不足,先检查模型大小、加载精度和 GPU 上其他进程;权重已加载、开始处理批次后才不足,再优先检查长度和单卡 batch。减小 batch 不会缩小基础权重本体,详细排查放在第 33 章。
<details> <summary>拓展术语:双重量化与分页优化器</summary>QLoRA 还采用了两项优化:双重量化(double quantization) 进一步量化缩放因子等辅助常数,减少这些额外信息的存储;分页优化器(paged optimizer) 通过在 CPU 与 GPU 之间按需迁移优化器状态,缓解训练中的显存峰值,但可能增加传输等待。它们都不改变“冻结量化基础权重、训练 LoRA 参数”的更新范围,也不保证任何配置都能放进显存。QLoRA 论文
</details>7.3 LoRA 与 QLoRA 的选择
| 当前情况 | 优先考虑什么 |
|---|---|
| 本课程 Qwen3-0.6B 能在现有显卡上完成 LoRA | 保持 LoRA,先检查训练与任务效果 |
| 换大模型后,仅加载基础权重就占去过多显存 | 检查加载精度,再评估 QLoRA |
| 能加载模型,但处理长样本或大批次时显存不足 | 先检查长度与 batch,不能只靠量化解决 |
| 需要验证两种方法的资源差异 | 固定模型、数据和其余配置,分别记录实际资源与效果 |
把当前配置中的量化等级从 none 改为适当配置的 4-bit 加载,主要变化是基础权重的保存与计算方式;学习的仍然是 LoRA 分支。额外的量化、反量化计算和具体实现会影响速度,因此 QLoRA 也可能更慢。它带来的近似误差是否影响关键词选择,还要检查回答。
对本课程已能完成普通 LoRA 的 0.6B 模型,先用现有配置完成训练与效果检查。将来换大模型,若权重占用成为主要限制,再比较 QLoRA:核对量化是否实际生效,记录能否完整运行、显存与耗时,最后比较同一份验证数据的损失和回答。能容纳模型、运行成本合适、任务效果可接受,是三个需要分别检查的结果。
</details>量化依赖、配置和资源对比留到第 33 章第 2.5、2.6 节选做,结果整理方法见该章第 5.5 节。