05. QLoRA 是什么?它相比 LoRA 多做了什么?

整理 QLoRA 相比 LoRA 的关键改动、量化机制与适用场景。

简单回答

QLoRA 就是在 LoRA 的基础上,把冻结的基座模型用 4-bit 量化(NF4)存储,同时引入双重量化(Double Quantization)压缩量化常数,并用分页优化器处理显存峰值。本质上是"4-bit 量化存储 + LoRA 微调",让单卡 24GB 的消费级显卡也能微调 33B 甚至 65B 的模型。

详细解释

QLoRA 的论文标题就说得很清楚:"Efficient Finetuning of Quantized LLMs"。它要解决的问题很具体:LoRA 虽然只训练少量参数,但冻结的 base model 还是要完整加载到显存里,一个 65B 模型 FP16 就要 130GB,这已经超出了单卡甚至双卡的容量。QLoRA 的做法是把这个冻结的 base model 量化到 4-bit 再加载,显存需求直接砍到四分之一左右。

QLoRA 引入了三个关键技术:

NF4(NormalFloat 4-bit)量化:这是 QLoRA 提出的一种新的 4-bit 数据类型。它的设计思路是,预训练模型的权重分布接近正态分布,所以量化的分位点应该按照正态分布来设置,而不是均匀分布。相比普通的 INT4 量化,NF4 对正态分布的权重理论上是信息最优的,量化误差更小。

Double Quantization(双重量化):常规量化需要为每个量化 block(比如 64 个权重)存一个 FP32 的缩放因子(scale),这些 scale 本身也占不少显存。双重量化就是把这些 scale 再做一次 8-bit 量化,进一步压缩开销。论文里给出的数字是每个参数平均能再省约 0.37 bit。

Paged Optimizers(分页优化器):训练过程中显存可能出现短暂的峰值(比如梯度 checkpoint、长序列),分页优化器借鉴了操作系统的虚拟内存思想,当 GPU 显存不足时自动把优化器状态转移到 CPU 内存,需要时再搬回来。这样可以避免 OOM 导致训练中断。

前向计算的流程是:4-bit 的权重在计算前先反量化回 BF16,然后正常做矩阵乘法,LoRA 部分用 BF16 算梯度和更新。所以虽然模型存储是 4-bit,但计算精度并没有损失太多。

一个很重要的结论是:QLoRA 几乎不牺牲效果。论文里做了大量实验,QLoRA 在 Vicuna benchmark 上的表现和全量 16-bit 微调几乎持平,甚至在某些 baseline 上打出了当时的 SOTA。这说明 4-bit 量化带来的精度损失被 NF4 的设计有效地控制住了。

工程上使用 QLoRA 很简单,用 bitsandbytes 库加载模型时指定 load_in_4bit=Truebnb_4bit_quant_type="nf4" 就行,然后像正常 LoRA 一样训练。HuggingFace 的 PEFT 库已经完全支持了。

QLoRA 和 LoRA 的选择很实际:如果显存够(比如你有一张 80G 的 A100 微调 7B),直接用 LoRA 就好,没必要加量化;如果显存紧张(比如消费级 GPU 微调大模型),QLoRA 是几乎唯一的选择。

面试时可以这样答

QLoRA 核心就是在 LoRA 的基础上加了一步:把冻结的 base model 用 4-bit 量化加载,这样大幅减少显存占用。比如一个 65B 模型 FP16 要 130GB,4-bit 量化后只要 30 多 GB,单卡或双卡就能跑。

它的三个关键技术:一是 NF4 数据类型,针对权重的正态分布特性设计量化分位点,比普通 INT4 精度更高;二是 Double Quantization,把量化的缩放因子再做一次量化,进一步省显存;三是分页优化器,显存不够时自动把优化器状态卸载到 CPU,防止 OOM。

计算时 4-bit 权重会反量化回 BF16 再做矩阵乘法,LoRA 部分正常用 BF16 算梯度,所以计算精度基本没损失。论文的结论也是 QLoRA 效果和全量 16-bit 微调几乎持平。

实际使用上,显存够就用 LoRA,显存紧张就上 QLoRA,工程上用 bitsandbytes 加 load_in_4bit 就行,HuggingFace PEFT 完全支持。

常见追问

  1. NF4 和普通 INT4 量化的区别到底在哪?
  2. QLoRA 训练速度和 LoRA 比怎么样?会慢多少?
  3. QLoRA 训完的模型部署时怎么处理——保持 4-bit 还是合并回 FP16?