「7B 模型微调要多少显存」是每个团队进入微调领域问的第一个问题,而答案的差距可以大到十倍——全量微调要 112GB 起步,LoRA 只要 20GB 上下,QLoRA 能把 65B 模型塞进单张 48GB 卡。这背后的方法家族叫 PEFT(Parameter-Efficient Fine-Tuning,参数高效微调):冻结基座模型的绝大部分权重,只训练一小部分新增参数。但方法一多,选择困难症就来了:LoRA、QLoRA、Prefix Tuning、Adapter 各自的机制不同、代价不同、适用场景不同。本文从全量微调的显存账本讲起,把每个方法的数学内核与工程代价讲清楚,最后给出一张选型决策表。
一、为什么需要 PEFT:全量微调的账本
显存去哪了
训练时显存由四块组成:权重本身、激活值、梯度、优化器状态。以 AdamW 加混合精度训练计,每个可训练参数的静态开销约为:bf16 权重 2 字节 + bf16 梯度 2 字节 + Adam 的两个 fp32 动量状态 8 字节(再加 fp32 主权重备份 4 字节),合计约 16 字节/参数。7B 模型全量微调仅静态部分就要约 112GB,加上激活值(与 batch 和序列长度成正比)实际上 8 卡 A100 是起步配置——这还没算 checkpoint 大小:全量微调的产物是整个模型的副本,多任务场景下每个任务存 14GB,运维成本线性上涨。PEFT 的解法是釜底抽薪:可训练参数缩到千分之一量级,优化器状态与梯度按可训练参数计算,静态开销从百 GB 级掉到百 MB 级,只剩基座权重的前向激活开销。
两类路线的划分
PEFT 方法按「新增参数挂在哪」分两大类。注入式:在层间插入新模块——Adapter 系列在 Transformer 层内部插瓶颈网络;Prefix 系列在前向序列前加虚拟 token。重参数化式:不改结构,把权重更新表达为低秩矩阵——LoRA 在每个目标权重旁挂一对低秩矩阵,训练结束后还能合并回权重、零推理开销。两大类的取舍核心是「推理时付不付代价」:注入式改动模型结构、部署时要带着 adapter 走;重参数化式训练完可以物归原主。这个区别在多任务服务架构里是决定性的。
二、LoRA:低秩假设的胜利
数学内核与参数核算
LoRA(Hu et al.,微软,2021)的出发点是一个经验观察:微调引起的权重变化矩阵 ΔW 具有远低于其维度的内在秩——大矩阵的更新集中在少数方向上。于是把 ΔW 近似为两个小矩阵的乘积:W' = W + BA,其中 A 是 r×d 的降维矩阵,B 是 d×r 的升维矩阵,r(秩)取 8 到 64 之间,前向时输出缩放为 Wx + (BAx)·(α/r),α 是缩放超参。参数量省多少可以手算:Llama-2-7B(hidden 4096,32 层)对 q、k、v、o 四个注意力投影加三层 MLP 挂 r=8 的 LoRA,每个模块新增 2×r×d(或 2×r×中间维)参数,合计约 2000 万——只占 7B 总参数的约 0.3%。LoRA 论文在 GPT-3 175B 上给出的两个著名数字:训练显存需求从约 1.2TB 降到约 350GB;任务 checkpoint 从 350GB 压到 35MB,缩小一万倍。
为什么它成了默认选择
LoRA 胜出的三个原因。推理零开销:训练结束把 BA 合并回权重,线上服务与原模型无异——Adapter 做不到这点。质量兜底:在 GLUE、GPT-3 指令跟随等基准上,r=4 到 8 的 LoRA 多次追平甚至超过全量微调,这打破了「参数少必然掉点」的直觉,也反过来说明全量微调的大量参数更新本身是冗余的。生态成熟:PEFT 库一行配置挂载,所有主流训练框架原生支持,核显玩家到万卡集群用的是同一套代码。工程细节三个坑:学习率要调高(LoRA 参数是新增的,常用 1e-4 到 2e-4,约是全量微调的十倍);秩不是越大越好,任务越「窄」(格式变换、风格迁移)小秩越够用,知识注入类任务才需要更大秩与更多目标模块;挂载位置从 q、v 扩展到全部线性层通常再涨一点分。
flowchart TD
S["微调需求"] --> Q1{"显存预算能装下全量微调?"}
Q1 -->|"能(多卡集群)"| F["全量微调<br/>效果上限最高、最费钱"]
Q1 -->|"不能"| Q2{"任务性质?"}
Q2 -->|"风格 / 格式 / 领域语感"| L["LoRA<br/>r=8-16,qkvo+MLP 全挂"]
Q2 -->|"显存极限(单卡 24-48G)"| QL["QLoRA<br/>NF4 基座 + LoRA,65B 单卡可训"]
Q2 -->|"多任务同时服务、互不干扰"| AD["Adapter / 多套 LoRA 动态挂载<br/>按请求切换"]
Q2 -->|"推理预算受限、提示词注入即可"| PT["Prefix / P-Tuning v2<br/>仅训虚拟 token,最轻"]
L --> M["训练后合并回权重<br/>推理零开销"]
QL --> M
AD --> S1["部署带 adapter 文件<br/>多任务热切换"]
PT --> S2["只保存 prompt 向量<br/>切换最灵活"]
三、QLoRA:把基座也压进显存
NF4 三件套
QLoRA(Dettmers et al.,华盛顿大学,2023)解决的是另一维的瓶颈:LoRA 冻结的基座权重本身也是 14GB(7B bf16)到 130GB(65B)的显存占用。它的三件套:一是 NF4(4-bit NormalFloat)量化——利用预训练权重的分布近似零均值正态这一先验,设计一个让量化桶在正态分位数上均匀分布的 4-bit 数据类型,比常规 int4 的信息损失更小;二是双重量化——对量化的缩放常数再做一次量化,进一步省元数据开销(平均每参数再省约 0.4 bit);三是分页优化器——优化器状态在显存峰值时临时换页到 CPU 内存,防止单步梯度尖峰导致 OOM。三件套叠加的效果是论文标题级的:65B 模型的微调塞进单张 48GB 卡,24 小时训出的 Guanaco 在 Vicuna 基准上达到 ChatGPT 99.3% 的水平。
使用边界
QLoRA 不是无代价的:反量化计算(矩阵乘时把 NF4 权重现场升回 bf16)带来约两到四成的吞吐损失,训练速度慢于纯 LoRA;极端低比特下的精度损失对「知识密集」任务比对「格式与风格」任务更敏感——QLoRA 论文自己的消融也显示 4-bit 基座在部分任务上差于 16-bit 基座。工程结论:QLoRA 是「显存预算不足时的最优解」而不是默认解,单卡 experiments 与资源紧张的边缘场景用它,集群里资源够就直接 LoRA。
四、Prefix Tuning 与 Adapter:另外两条路线
Prefix Tuning:把「学」放在输入端
Prefix Tuning(Li & Liang,2021)与 P-Tuning v2(2022)把可训练参数放在输入序列里:给每层(P-Tuning v2)或仅输入层(Prefix 原版)前缀插入若干虚拟 token 的 key-value 向量,训练只动这些向量。参数量可以小到 0.1% 以下,任务切换只是换一组向量,部署上极其灵活——这正是它被提示词管理系统青睐的原因。代价在效果曲线上:P-Tuning v2 的实验清楚显示,参数效率的优势只在大模型上兑现(约 10B 以上时能追平全量微调),模型越小掉点越明显,7B 以下通常明显弱于 LoRA。另一个隐性代价是占上下文:虚拟 token 挤占有效序列长度,长文本任务要算这笔账。
Adapter:结构注入的祖师爷与延迟税
Adapter(Houlsby et al.,2019)是最早的 PEFT 工作:在每个 Transformer 层的注意力与 FFN 之后插入一个降维-升维的瓶颈网络(down-project 到 64 维再升回来,残差连接),只训瓶颈参数。它的历史地位在于证明了「冻结主干加微量参数」这条路走得通,但工程上有两笔税。结构税:adapter 是串行模块,推理时每一步都要过一遍,无法像 LoRA 那样合并——自回归解码是逐 token 循环,串行开销被乘以序列长度,移动端与低延迟场景实测损失明显(后续 AdapterDrop 研究专门量化并建议裁剪低层 adapter 来省钱)。部署税:多任务服务要管理「基座权重加多套 adapter」的组合态,服务框架需要 adapter 加载与热切换的支持。它的当代定位因此很明确:只有「多任务同时在线、需要互不干扰地热切换」这一种场景还值得优先考虑 adapter,其余场景 LoRA 的合并部署更干净。
五、横向对比与实操
一张表看清取舍
方法对比(7B 基座、常规配置的量级参考):LoRA 可训练参数约 2000 万(0.3%),显存 20GB 上下,推理零开销(可合并),效果接近全量微调——默认选择。QLoRA 同样参数量,基座压到 4-bit 后单卡 48G 能训 65B,代价是吞吐损失与轻微精度税——显存紧张时的选择。P-Tuning v2 参数可低于 0.1%,显存最省,但小模型掉点、占上下文——超轻量多任务与提示词管理的选择。Adapter 参数 0.5% 到 8%,有推理延迟税与部署组合态成本——多任务热切换的选择。全量微调无参数效率但有最高效果上限——预算充足、任务与基座能力差距大(新语言、全新领域)时的选择。
PEFT 库的最小实操与显存对照
from peft import LoraConfig, get_peft_model
from transformers import AutoModelForCausalLM
model = AutoModelForCausalLM.from_pretrained("meta-llama/Llama-2-7b-hf",
torch_dtype="bfloat16", device_map="cuda")
cfg = LoraConfig(
r=16, lora_alpha=32, lora_dropout=0.05,
target_modules=["q_proj", "k_proj", "v_proj", "o_proj",
"gate_proj", "up_proj", "down_proj"],
task_type="CAUSAL_LM",
)
model = get_peft_model(model, cfg)
model.print_trainable_parameters()
# 典型输出:trainable params: 39,976,448 || all params: 6,778,311,168
# trainable%: 0.5898
训练完成后用 merge_and_unload 把 BA 合并回权重再导出,线上部署就是一个普通模型文件;要保留多任务,则按任务各存一份几十 MB 的 adapter 目录,加载时按请求挂载。显存实测的量级参考(batch 4、序列 2048):全量微调 7B 需要 8 卡 A100 40G 级别,bf16 LoRA 约 20GB 起,NF4 QLoRA 能压到 10GB 上下——数字随序列长度与 batch 线性变化,立项前在自己的配置上实测一次。
六、常见坑与选型总结
最后是踩坑清单。坑一:学习率照抄全量微调的 1e-5,LoRA 训不动的最常见原因——新增参数要十倍学习率。坑二:秩迷信,r 从 8 加到 256 通常只带来过拟合不带来质量,先确认任务类型再定秩。坑三:只挂 q、v 就想注入知识,知识密集任务把 MLP 三个投影也挂上。坑四:QLoRA 量化配置与合并时基座精度不一致,合并回 bf16 时要做一次小样本回归验证。坑五:多 adapter 动态加载时忘了显存预留,高峰期 OOM。选型的压缩版结论:默认 LoRA(r=8 到 16、全线性层挂载、训练后合并);显存不够降级 QLoRA;多任务热切换才考虑 adapter 或多套 LoRA 挂载;超轻量场景用 P-Tuning v2。PEFT 的哲学值得记住:它不只是省卡的工具,更是一个架构观点——大模型的知识已经足够,微调的大部分工作是在「教它使用方式」而不是「灌它新知识」,而教使用方式根本不需要动一千亿个参数。
小结
PEFT 全家桶的知识地图可以画成三层。机制层:LoRA 用低秩分解把权重更新压缩到 0.3% 的参数量并支持训练后合并、推理零开销;QLoRA 用 NF4 加双重量化把冻结基座压进单卡显存,代价是吞吐与轻微精度税;Prefix 系把参数放进虚拟 token、轻到 0.1% 以下但小模型掉点;Adapter 用串行瓶颈网络开了这条路,但推理延迟与部署组合态让它退守多任务热切换 niche。工程层:默认答案几乎总是 LoRA(全线性层、r=8 到 16、lr 1e-4 量级),显存是唯一强制降级到 QLoRA 的理由。认知层:PEFT 的流行折射出一个判断——参数化知识与使用方式是两回事,绝大多数下游任务属于后者。拿着这张地图回到开头那个问题:「7B 微调要多少显存」的正确回答是「先说任务,再说预算」——因为方法选对了,答案可以差十倍。
读者留言
COMMENTS 暂无还没有留言,来说第一句?