QLoRA实战:没有A100,我用消费级显卡微调了70B模型
两个月前,老板扔给我一个任务:“把这个 70B 的模型按照我们的业务数据微调一下。”
我当时心里就三个字:得加钱。
70B 模型,全量微调起码要 8 张 A100,一张 A100 租一天就几百块。我们小团队哪烧得起这个钱。
后来一个朋友跟我说:试试 QLoRA 吧,一张 3090 就能跑 70B 的微调。
说实话我当时是不信的。一张卡跑 70B 的微调?这不是扯吗?结果试完之后我发现——不仅真的能跑,效果还不赖。
QLoRA 到底是个什么东西
QLoRA = Quantized LoRA,就是给 LoRA 又加了一层量化。
拆开说:
- LoRA(Low-Rank Adaptation):把大模型的权重冻结不动,在旁边加两个小的低秩矩阵做训练。原来要更新 1000 万个参数,现在只更新 10 万。显存需求大幅降低。
- QLoRA:在此基础上,把冻结的权重量化到 4bit(NormalFloat4),进一步砍显存。一张 24G 的 3090,跑 70B 模型的微调不是梦。
QLoRA 的核心创新是 NF4 量化格式。它不是简单的 INT4,而是针对神经网络的权重分布设计的 4bit 量化格式,比普通的 INT4 精度更高,对模型输出影响更小。
另外,QLoRA 还有一个骚操作叫 Paged Optimizer——利用 CPU 内存和 GPU 显存之间的页交换,解决显存不够时的"爆显存"问题。
我的实战环境
先交代硬件配置,方便你对照:
GPU: RTX 3090 (24GB) × 1
CPU: AMD Ryzen 5950X (16核)
内存: 64GB DDR4
系统: Ubuntu 22.04
CUDA: 12.1
就这配置,说实话在 AI 训练圈算寒碜的。但够用。
实操步骤
第一步:环境安装
装 bitsandbytes 和 peft,两个最核心的库。
pip install bitsandbytes
pip install peft transformers accelerate datasets
bitsandbytes 负责 NF4 量化,peft 负责 LoRA 操作。两个是 QLoRA 的黄金搭档。
第二步:加载量化模型
关键代码就这几行:
from transformers import AutoModelForCausalLM, BitsAndBytesConfig
import torch
bnb_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_use_double_quant=True,
bnb_4bit_quant_type="nf4",
bnb_4bit_compute_dtype=torch.bfloat16
)
model = AutoModelForCausalLM.from_pretrained(
"模型名称",
quantization_config=bnb_config,
device_map="auto", # 自动分配到各个设备
torch_dtype=torch.bfloat16
)
这里 bnb_4bit_use_double_quant=True 开启双重量化——对量化常数再量化一次,进一步省显存。device_map="auto" 让 Transformers 自动分配层到不同的 GPU/CPU,防止某一块显存爆掉。
第三步:配置 LoRA 参数
from peft import LoraConfig, get_peft_model
lora_config = LoraConfig(
r=16,
lora_alpha=32,
target_modules=["q_proj", "v_proj", "k_proj", "o_proj"],
lora_dropout=0.05,
bias="none",
task_type="CAUSAL_LM"
)
model = get_peft_model(model, lora_config)
r=16 是 LoRA 的秩,秩越大可学习参数越多但显存也更大。70B 模型我试过 r=16 性价比最高。target_modules 指定在哪些模块上加 LoRA——QKV 投影层是全连上。
第四步:开始训练
训练参数上,我用的是:
per_device_train_batch_size: 1
gradient_accumulation_steps: 8
learning_rate: 2e-4
num_train_epochs: 3
max_seq_length: 2048
batch_size=1 是因为显存真的就那么多。配合 gradient_accumulation_steps=8,等效 batch size 是 8,训练效果其实不差。
关键显存数据:
- 加载模型:约 18GB(NF4 量化+双重量化)
- 训练峰值:约 22GB(含梯度、优化器状态)
- 剩余:约 2GB(系统占用)
卡的刚刚好。3090 的 24GB 基本用满。
踩过的三个坑
坑一:CPM 评分上不去
第一次训完,跑评测 CPM 只涨了 2 个点。找了半天原因——学习率太高了。
QLoRA 因为权重是量化的,对学习率特别敏感。我一开始用了 1e-4 觉得挺保守,结果还是太高。降到 2e-5 之后,CPM 直接涨了 8 个点。
坑二:中途 OOM
训到一半报 OOM。排查后发现是 max_seq_length 设了 4096。70B 模型 + 4K 上下文 = 显存直接爆掉。降到 2048 之后稳如老狗。
坑三:NF4 反量化成为瓶颈
QLoRA 的原理是 forward 时把 4bit 权重反量化到 16bit 做计算,这导致训练速度比 LoRA 慢 30%-40%。没办法,这是 trade-off。想快就多花钱买更多卡。
效果到底怎么样?
拿我们的场景来说——用 5000 条客服对话数据微调一个 70B 模型。
- 全量微调:8 张 A100,训练 6 小时,成本约 3000 元
- QLoRA(我的方案):1 张 3090,训练 12 小时,成本 0 元(自己的卡)
模型输出质量呢?做了 100 条测试集的盲测,QLoRA 的回复质量达到全量微调的 92%。
92% 的效果,0 元的硬件成本。 这笔账不用我算了吧。
写在最后
QLoRA 这个方案,说实话不是银弹。它慢、它有精度损失、它对超参敏感。
但它解决了一个真实的问题——让买不起 A100 的团队也能做大模型微调。
如果你手头也有一张消费级显卡,想试试微调但怕跑不动,直接用 QLoRA 就行。先用一张卡跑起来,效果不行再想办法上多卡。
先把事情做出来,再考虑做完美。这个道理放哪都适用。
更多推荐




所有评论(0)