· 预计阅读 13 分钟

LoRA / QLoRA:为什么低成本微调可行?


本篇解决什么

本篇是「小模型训练系列」第 7 篇:从全参微调的成本、LoRA 的低秩增量、rank/alpha/dropout 与 QLoRA 的显存账本出发,解释为什么低成本微调不是少训练一点,而是把可训练能力放在更聪明的位置上。

适合谁读

正在沿着「小模型训练系列」系统学习,希望把概念、工程和真实判断串起来的读者。

AI大模型训练LoRAQLoRA微调

上一篇讲 Tokenizer 和样本构造时,我们把训练入口拆到了很细:

文本会被切成 token,聊天会被套进模板,labels 和 loss mask 会决定模型到底在哪些位置学习。

也就是说,模型不是在“读一篇文章”,而是在一格一格地看训练胶片。

现在问题来了:

如果已经知道胶片怎么放进放映机,下一步自然是:

我们到底要不要改整台放映机?

这就是微调要解决的问题。

很多人第一次听到“微调大模型”,脑子里会出现一个很朴素的想象:

原来的模型不够懂我
那我就把它重新训练一下
让它变成我的模型

这句话方向没错,但如果真的按“重新训练整台模型”去做,成本会立刻把人按在地上。

因为一个模型不是一个文档,不是一个配置文件,也不是一个可以随手改几行的脚本。

它更像一座已经建好的城市。

全参微调像是把城市里的每一条路、每一盏灯、每一栋楼都打开施工权限。理论上自由度最大,现实里也最贵、最危险、最容易把原来的秩序弄乱。

LoRA 做的事情更像:

不重修整座城市,只在关键路口加几条可学习的临时匝道。

这些匝道很小,但如果放在对的位置,就能改变车流方向。


📌 本篇聚焦的问题

  • 全参微调为什么这么贵
  • LoRA 为什么只训练一小部分参数,也能改变模型行为
  • rankalphadropout 到底在调什么
  • LoRA adapter 应该理解成什么
  • QLoRA 为什么能进一步压低显存
  • 显存到底花在了哪些地方
  • LoRA 适合改什么,不适合改什么
  • 小模型微调时,怎样在成本、效果和稳定性之间做选择

这一篇的核心观点是:

低成本微调不是“少训练一点”,而是把可训练能力放在更聪明的位置上。


🏗️ 1. 全参微调:把整栋楼都打开施工权限

先从最直观的方案说起:全参微调。

一个语言模型里面有很多参数。参数可以理解成模型内部的“旋钮”和“线路”。训练时,Loss 会告诉这些参数怎么调整,优化器再一步步更新它们。

全参微调的意思是:

模型里几乎所有参数,都允许被训练更新。

这当然很强。

因为你给了训练过程最大的自由度。模型可以在很多层、很多矩阵、很多路径上重新塑形。

但问题也很明显:

自由度越大,成本越高。
自由度越大,越容易改坏。
自由度越大,越需要大量高质量数据支撑。

像装修房子一样。

如果只是想把书房变成更适合工作的地方,不一定要把承重墙、水电、地暖、屋顶全拆了。

全拆当然能改得彻底,但也会带来三个麻烦:

  1. 工程量大
  2. 钱包吃不消
  3. 改完不一定比原来更稳

模型也是一样。


💸 2. 贵在哪里:不是只有模型本身占显存

很多人会以为,训练时显存主要用来放模型参数。

这只说对了一部分。

训练时,显存通常要装下好几类东西:

显存对象可以理解成什么
模型权重模型本体,所有已经学到的参数
梯度每个可训练参数该往哪里改
优化器状态优化器记账本,比如 Adam 的动量和方差
激活值前向计算中间结果,反向传播要用
batch / 序列输入 token、mask、labels 等

所以训练不是“模型多大,就需要多少显存”。

更像是:

模型本体
+ 梯度
+ 优化器账本
+ 中间过程缓存
+ 输入样本
= 训练显存压力

这就是为什么一个模型“能加载”,不等于它“能训练”。

推理时只要让模型往前算;训练时还要记住怎么回头改。

如果把模型比作一支动画制作团队,推理只是播放成片,训练则要把分镜、草稿、涂层、修改记录和导演批注全摊开。

桌子一下就不够用了。


🧠 3. 为什么不一定要改所有参数

既然全参微调这么贵,那能不能只改一小部分?

答案是:很多时候可以。

原因在于,微调经常不是让模型从零学会语言,也不是让模型重新认识世界。

底座模型已经会很多东西:

  • 会读句子
  • 会接上下文
  • 会写代码
  • 会回答问题
  • 会总结、翻译、推理
  • 会遵守一定格式

微调通常想做的是:

让模型更像某个领域
让模型更听某种指令
让模型更稳定输出某种格式
让模型更符合某种语气和边界

这更像“方向调整”,不是“从头造人”。

如果底座已经是一辆能跑的车,微调很多时候不是重新造发动机,而是换轮胎、调悬挂、校准方向盘。

LoRA 的直觉就来自这里:

既然目标只是让模型产生一个有限的方向变化,就不一定要开放所有参数。


🪄 4. LoRA 的核心:给原模型加一条小小的增量路径

模型内部有大量矩阵。

可以把一个矩阵想象成“把输入向量变成输出向量的机器”。Attention 里面有 Q、K、V、O 等投影矩阵,MLP 里面也有各种投影矩阵。

普通微调会直接修改原始矩阵:

W 变成 W'

LoRA 不直接改 W

它做的是:

原来的 W 冻住
另外训练一个很小的增量 ΔW
最后用 W + ΔW 来工作

可以画成这样:

flowchart LR
  A[输入向量 x] --> B[冻结的原始权重 W]
  A --> C[可训练的小路径 ΔW]
  B --> D[原模型输出]
  C --> E[增量修正]
  D --> F[合并后的输出]
  E --> F

这就是 LoRA 的核心味道:

原模型负责保留大能力,小增量负责学新方向。

像给一条成熟铁路旁边加一个小道岔。主轨道不拆,但列车可以在关键位置稍微改变去向。


🧩 5. “低秩”到底是什么意思

LoRA 的全名里有一个关键词:Low-Rank。

中文常翻译成“低秩”。

这个词听起来像数学课要开始点名了,但其实可以先抓住直觉。

假设一个大矩阵 W 很大:

W: 4096 × 4096

如果直接训练一个完整的 ΔW,它也要这么大:

ΔW: 4096 × 4096

这大约是 1677 万个参数。

LoRA 不直接训练这么大的 ΔW,而是把它拆成两个小矩阵相乘:

ΔW = B × A

比如 rank 设为 8:

A: 8 × 4096
B: 4096 × 8

这样参数量大概是:

8 × 4096 + 4096 × 8 = 65536

从 1677 万,变成 6.5 万左右。

直觉上,这就是:

不让模型在所有方向上乱改
只给它少数几个可学习的调整方向

如果全参微调像给城市所有道路都开施工权限,LoRA 就像只允许几个关键路口新开匝道。

路口选得对,交通就能明显变化。


🎚️ 6. Rank:给模型几支“调音旋钮”

rank 是 LoRA 里最常见的参数之一。

可以把它理解成:

允许 LoRA 学多少条独立的变化方向。

rank 越小,LoRA 越轻,能表达的变化越少。
rank 越大,LoRA 越重,能表达的变化更多,但也更容易过拟合,显存和计算成本也会上升。

大概可以这样理解:

rank像什么可能适合
4几个很小的调音旋钮简单风格、格式适配
8常见的轻量适配指令、语气、领域小任务
16更强的表达能力稍复杂领域、更多样本
32+更大的改造空间数据足够、任务更复杂时再考虑

这不是绝对规则。

更重要的是:rank 不是越大越好。

如果数据很少,rank 太大,模型可能不是“学会了能力”,而是“背住了训练集的口音”。

像给一个刚学乐器的人 64 个调音旋钮,他不一定会更会演奏,可能只是更容易把声音调乱。


🔊 7. Alpha:这条 LoRA 路径声音开多大

alpha 常常和 rank 一起出现。

它可以理解成 LoRA 增量的音量旋钮。

LoRA 的输出并不是原封不动加到模型里,而是通常会有一个缩放:

输出 = 原模型输出 + LoRA 增量 × 缩放系数

alpha 越大,LoRA 的影响越强。
alpha 太小,训练出来的 adapter 可能像声音太轻,模型几乎听不到。
alpha 太大,模型可能被 adapter 拉得太猛,原本的能力被扰动。

可以这样想:

rank 决定有几支调音旋钮
alpha 决定这些旋钮拧出来的声音有多大

所以 LoRA 调参不是玄学乱试,而是在调两个东西:

  1. 变化方向的数量
  2. 变化信号的强度

🌧️ 8. Dropout:训练时故意让 adapter 少依赖一点自己

LoRA 里有时还会看到 dropout

它的作用可以理解成:训练时随机让一部分信号暂时失效,避免模型过度依赖某些路径。

像排练一支乐队时,偶尔让某个乐器停一下,看整支队伍还能不能稳住。

如果数据少、任务窄,适当 dropout 可能有帮助。
如果数据质量高、任务明确,dropout 太大又可能让学习变慢。

它不是必须越高越好,也不是必须开。

更准确的说法是:

dropout 是一种防止 adapter 过度记忆训练样本的保险丝。


🧷 9. Adapter:不是外挂知识库,而是行为补丁

LoRA 训练出来的那一小部分参数,常被叫做 adapter。

这个词很容易被误解。

很多人会以为 adapter 像一个小知识库:

把公司资料放进 adapter
模型就记住公司知识

这不准确。

LoRA adapter 更像一个行为补丁:

让模型在某些输入模式下
更倾向于某些输出方式

它可以让模型更像客服、更像代码助手、更像某个领域的写作风格、更稳定地遵守格式。

但它不适合承担所有事实知识更新。

比如:

目标更适合什么
临时查最新价格RAG / 检索
企业文档经常更新RAG / 数据库
固定输出格式LoRA / SFT
稳定领域术语和表达习惯LoRA
让模型学会某种流程判断LoRA + 高质量样本
一次性很短的风格要求Prompt

这也是后面会专门讲 RAG vs 微调的原因。

知识放在哪里,取决于它变不变、怎么用、要不要被模型内化成行为。


🧮 10. LoRA 为什么真的能省显存

回到显存账本。

全参微调时,几乎所有权重都要参与训练,所以需要:

模型权重
+ 全部参数的梯度
+ 全部参数的优化器状态
+ 激活值

LoRA 冻结原模型,只训练 adapter。

所以很多开销消失了:

原模型权重:需要加载,但不更新
原模型梯度:通常不需要
原模型优化器状态:不需要
LoRA 参数:需要训练
LoRA 梯度:需要
LoRA 优化器状态:需要

表格更清楚:

项目全参微调LoRA
原模型权重需要需要
原模型梯度需要大多不需要
原模型优化器状态需要不需要
LoRA adapter需要
adapter 梯度需要
adapter 优化器状态需要
总体成本低很多

这就是 LoRA 的经济学:

贵的模型本体只负责提供能力,便宜的 adapter 负责学习方向。


📦 11. QLoRA:把大模型本体压缩存放,再训练小 adapter

LoRA 已经省了很多。

但原模型本体还是要放进显存。

如果底座模型很大,哪怕不训练它,只是加载它,也会占很多空间。

QLoRA 继续往前走一步:

把冻结的底座模型用更低精度量化存放,再训练 LoRA adapter。

可以这样理解:

LoRA:
底座模型正常放着,不训练
只训练小 adapter

QLoRA:
底座模型压缩放着,不训练
只训练小 adapter

画成流程就是:

flowchart TB
  A[预训练底座模型] --> B[4-bit 量化存放]
  B --> C[冻结底座权重]
  C --> D[前向计算提供能力]
  E[LoRA Adapter] --> F[训练更新]
  D --> G[模型输出]
  F --> G

如果说 LoRA 是“不拆主楼,只加小改造”,那么 QLoRA 就是:

主楼用压缩档案方式存着,施工只发生在小改造模块上。

它让更大的模型有机会在更小的显卡上做微调。

但也要注意:QLoRA 不是免费午餐。

它可能带来:

  • 计算过程更复杂
  • 训练速度不一定更快
  • 量化配置会影响稳定性
  • 对实现框架和显卡支持有要求

所以 QLoRA 的关键词不是“更强”,而是“更省显存”。


🧊 12. 量化不是把模型变聪明,而是把模型放小

这里要单独停一下。

很多人会把量化理解成一种神奇优化:

量化了,所以模型更好?

不。

量化主要是把模型用更少的位数表示。

就像一张高清照片压缩成更小文件,存储更省,但细节可能有损失。

在 QLoRA 里,量化的目标是:

让冻结的底座模型更省显存
把训练预算留给 LoRA adapter

它不是让模型凭空更聪明。

如果底座模型本来能力不够,QLoRA 不会把它变成另一个等级的模型。
如果数据质量很差,QLoRA 也不会自动拯救训练目标。
如果样本构造错了,QLoRA 只会更省钱地把错误学进去。

这句话有点冷,但很重要:

QLoRA 降低的是训练门槛,不是降低训练质量要求。


🔧 13. LoRA 通常加在哪里

LoRA 可以加在模型不同位置。

常见位置包括:

  • attention 的 q_proj
  • attention 的 k_proj
  • attention 的 v_proj
  • attention 的 o_proj
  • MLP 的上投影 / 下投影

不是所有位置都必须加。

如果任务只是轻度风格适配,可能加少一点就够。
如果任务涉及更复杂的领域表达和推理组织,可能需要更多位置。
如果数据很少,位置加太多反而容易过拟合。

这像给城市加匝道。

不是匝道越多越好,而是要加在真正影响车流的路口。

训练前可以问三个问题:

  1. 任务主要改变输出风格,还是改变领域判断?
  2. 数据量能支撑多大的 adapter 自由度?
  3. 评估集能不能发现模型被改坏?

第三个问题最容易被忽略。

没有评估集,调 LoRA 就像闭着眼给车改方向盘。


🧯 14. LoRA 常见误区

误区一:LoRA 参数越多越好

不一定。

参数越多,模型越有能力适应训练集,也越有能力记住训练集的噪声。

如果数据很小、格式单一、答案重复,rank 太高可能会让模型变成“训练集复读机”。

误区二:训练 Loss 下降就代表成功

不一定。

Loss 下降只说明模型更像训练目标。

如果训练目标有问题,Loss 下降就是模型更像错误目标。

这就是为什么下一篇必须讲评估体系。

误区三:QLoRA 一定比 LoRA 更好

QLoRA 更主要的价值是省显存。

如果显存足够,普通 LoRA 可能更简单、更稳定。
如果显存紧张,QLoRA 才特别有意义。

误区四:LoRA 可以替代 RAG

不完全可以。

LoRA 适合把稳定能力写进模型行为里。
RAG 适合处理经常变化、需要可追溯来源的知识。

把每天变化的资料硬塞进 LoRA,通常不是好主意。

误区五:一个 adapter 可以解决所有任务

不一定。

不同任务可能需要不同 adapter。客服、代码、写作、医疗问答、法律问答,本质目标不同。

一个 adapter 太贪心,最后可能什么都沾一点,什么都不够稳。


🧭 15. Prompt、RAG、LoRA、全参微调怎么选

这张表可以先当地图。

目标优先考虑
临时改变语气Prompt
固定输出格式Prompt / LoRA
接入大量外部文档RAG
文档经常更新RAG
稳定领域表达习惯LoRA
让模型学会固定流程判断LoRA + 高质量样本
大规模改变模型能力边界全参微调
显存很紧但想训练较大底座QLoRA

一个比较稳的思路是:

能用 Prompt 解决,就先别训练。
知识经常变,就优先检索。
行为要稳定内化,再考虑 LoRA。
LoRA 不够,再考虑更重的训练方案。

这不是保守,而是工程上最可靠的顺序。

训练是有成本的,错误训练也会留下痕迹。


🧪 16. 一个小模型微调的实际流程

如果要真的做一次 LoRA / QLoRA 微调,流程可以这样拆:

flowchart TB
  A[选择底座模型] --> B[准备训练样本]
  B --> C[统一 chat template]
  C --> D[设置 LoRA target modules]
  D --> E[选择 rank / alpha / dropout]
  E --> F[训练 adapter]
  F --> G[验证集与回归测试]
  G --> H[合并或加载 adapter 推理]
  H --> I[上线后收集反馈]

每一步都有一个关键问题:

步骤要问的问题
选底座模型它原本能力够不够
准备样本数据是不是在教正确行为
chat template训练和推理格式是否一致
target modulesLoRA 加在了哪些关键位置
rank / alpha自由度和影响力是否过大或过小
训练Loss 是否正常,但不过度迷信
验证模型是否真的完成任务
推理adapter 是否正确加载或合并
反馈上线后有没有退化和边界问题

这里最重要的不是某个参数,而是闭环。

没有闭环,微调只是一次漂亮的实验。

有闭环,微调才会变成可复用的能力工程。


📉 17. 显存账本:哪里最容易爆

小模型训练里,显存常常不是被一个东西吃掉,而是被几类东西一起挤爆。

常见压力来自:

  1. 底座模型大小
  2. 序列长度
  3. batch size
  4. optimizer 状态
  5. 是否启用梯度检查点
  6. LoRA rank 和 target modules 数量
  7. 精度设置

很多人一看到 OOM,就只想换显卡。

但在工程上,先看这几个旋钮:

旋钮降显存效果代价
降 batch size明显训练更慢,梯度更抖
降 seq_len明显长样本学不到
开 gradient checkpointing明显计算变慢
用 LoRA明显表达能力受 adapter 限制
用 QLoRA更省底座显存实现更复杂,速度未必更快
降 rank有帮助adapter 能力变弱
少加 target modules有帮助适配能力可能不足

所以显存优化不是一个开关,而是一张账本。

每省一块地方,都要问:

它牺牲了什么?


🧠 18. 小模型微调的判断:先别贪大

对个人学习和小团队项目来说,LoRA / QLoRA 最好的地方不是“便宜”两个字。

而是它让训练变得可试错。

全参微调太重,失败一次成本很高。
LoRA 更轻,失败了也更容易回滚。
adapter 可以保存、对比、替换、合并,也可以为不同任务保留不同版本。

这让微调从“一次豪赌”变成“多轮迭代”。

对小模型来说,这非常关键。

因为一开始很难一次就知道:

  • 数据该怎么配比
  • rank 该设多少
  • 哪些模块该加 LoRA
  • 模型会不会过拟合
  • 哪些能力会退化

轻量微调的意义,就是让这些问题能被逐步回答。


🧾 19. 训练前先做这张决策表

真的开训前,可以先填这张表。

问题如果答案不清楚,会有什么风险
底座模型为什么选它训练成本花在错误底座上
目标能力是什么adapter 学成一团模糊风格
数据量和质量够不够rank 越大越容易过拟合
prompt 是否已经能解决白白训练
知识是否经常更新应该用 RAG 却硬塞微调
评估集准备好了吗Loss 下降但不知道有没有变好
上线怎么回滚adapter 出问题无法快速撤回

这张表比很多训练参数更重要。

因为参数只决定怎么训练,决策表决定该不该训练。


🌱 20. 这一篇的核心结论

  1. 全参微调自由度最大,但成本高、风险也高
  2. 训练显存不只放模型,还要放梯度、优化器状态和中间激活
  3. 很多微调目标只是方向调整,不需要修改所有参数
  4. LoRA 冻结原模型,只训练一个低秩增量路径
  5. rank 决定可学习变化方向的数量
  6. alpha 决定 LoRA 增量影响原模型的强度
  7. dropout 是防止 adapter 过度记忆样本的保险丝
  8. QLoRA 把冻结底座量化存放,再训练 LoRA adapter
  9. 量化主要是省显存,不是让模型自动变聪明
  10. LoRA 适合稳定行为适配,不适合替代所有知识检索

如果把前几篇串起来,现在训练链路已经更完整了:

flowchart LR
  A[数据决定方向] --> B[Tokenizer 切分世界]
  B --> C[样本构造定义目标]
  C --> D[LoRA / QLoRA 决定怎么低成本改模型]
  D --> E[评估体系判断是否真的变好]

低成本微调真正厉害的地方,不是“便宜地训练一个模型”。

而是:

在不破坏底座能力的前提下,用很小的可训练空间,把模型推向一个更明确的任务方向。

这也是为什么 LoRA / QLoRA 会成为个人和小团队训练小模型时最重要的工程入口之一。

它让模型训练从昂贵的重工业,变成可以反复打磨的手艺活。


📌 下一篇预告

《评估体系:模型到底有没有真的变好?》

下一篇会讲一个更现实的问题:

训练跑完了,Loss 下降了,样例看起来也不错。

但是模型真的变好了吗?

会拆开这些问题:

  • training loss 和 validation loss 分别说明什么
  • 为什么 Loss 下降不等于用户体验变好
  • 如何设计任务评估集和回归集
  • 人工验收应该看哪些维度
  • 为什么要保留“训练前模型”的对照组
  • 小模型上线前,怎样判断能不能用

核心观点是:模型有没有变好,不由训练日志决定,而由任务闭环决定。


🗺️ 后续章节路线

顺序章节方向要解决的问题
第 8 篇评估体系:模型到底有没有真的变好?training loss、validation loss、任务评估、回归集与人工验收
第 9 篇RAG vs 微调:知识应该放进检索,还是写进参数?知识更新频率、事实性、成本、召回边界与能力边界
第 10 篇推理与部署:模型能力如何稳定跑起来?量化、KV Cache、吞吐、并发、延迟与部署成本
第 11 篇工具调用与 Agent:模型如何从会说话变成会做事?Function Calling、工具参数、权限边界、日志与人工确认
第 12 篇Memory 与工作流:模型如何承接长期任务?对话记忆、任务状态、上下文压缩、恢复现场与流程编排
第 13 篇行业模型与业务闭环:训练如何进入真实场景?领域数据、流程反馈、人工审核、持续评估与灰度改进
第 14 篇系列总结:从数据到 Agent 的小模型工程地图把训练、微调、评估、RAG、部署和 Agent 串成完整路线

从这一篇开始,系列进入真正的工程选择层:

不是只问“能不能训练”,而是问“用什么成本、改哪些部分、如何证明真的变好”。

持续学习,持续记录,持续筛选

如果这篇对你有用,可以继续沿着主题读下去。

福星家和会长期记录 AI 技术、生活成长、真实好物与正向文化观察。产品体验、人物故事、教育内容、生活方式、文化作品和内容共创都欢迎邮件沟通,合作内容会清楚标注。