English interface selected · this article is currently written in Chinese.
全参数微调与 LoRA 怎样选择:更新空间、显存与量化
English overview →具备清晰骨架、初步数学推导或工程验证,持续补充论据与实测。
数字花园
🌿 什么是数字花园与思想演进?
遵循 Maggie Appleton 与 Andy Matuschak 的常青笔记理念:这里不是按时间沉底的流水账,而是持续修剪打磨的知识生态。文章按成熟度经历:
- 🌱 萌芽 (Seedling): 发散灵感、读书摘录、开放猜想
- 🌿 演进 (Budding): 结构渐明、初步代码推导、积极修正
- 🌳 常青 (Evergreen): 逻辑闭环、持久经得起检验的基石
- 🔬 实验待证 (Speculative): 结合沙盒与仿真探针的理论探索
指令数据和监督范围确定以后,我们还要决定:更新整个模型,还是只训练一小部分新增参数?
LoRA 经常被介绍成“用很少参数微调大模型”。这句话方向没错,但容易掩盖几个问题:少的是哪部分参数,基础模型还占不占内存,长输入的激活怎么办,以及少量更新是否足够表达当前任务?
本篇先用一个小矩阵解释 LoRA,再讨论全参数、LoRA 和 QLoRA 的选择。所有资源数字都是注明假设的计算,不是本地设备实测。
全参数微调允许直接修改原有权重
考虑一个线性层:
的形状为 。全参数微调可以直接更新这个矩阵,并更新其他被设为可训练的参数。
这样提供较大的调整空间,但训练时通常还要为可训练权重保存梯度和优化器状态。它不是只在内存里放一份模型就够了。
“全参数”也应以实际配置为准。某些项目仍冻结嵌入或其他部分,所以报告里最好给出可训练参数清单和数量,而不只写一个名称。
LoRA 把增量写成两个小矩阵的乘积
LoRA 冻结基础矩阵 ,把更新写成:
其中 ,, 是秩上限, 是缩放系数。原始 LoRA 使用 。LoRA,第 4 节
前向计算相当于原层输出加上一条较窄的分支:
先把输入映射到 维,再映射回输出维度。训练只调整选定的新增矩阵,而不是把整张 都变成可训练参数。
这里说的是更新矩阵低秩,不是原始权重被压缩成低秩,也不是模型所有能力只有 个维度。
手算一个秩为一的更新
设输入三维、输出二维,,取:
则:
第二行是第一行的一半,所以这张增量矩阵的秩为一。固定这组因子时,增量输出都沿着 给出的方向;训练可以改变因子,因此这个方向不是从初始化起就永远固定的。对输入 ,先算 ,再算 。
若 ,原输出就加上 。用完整矩阵 直接乘 ,应该得到同一结果。
这个小例子里,原矩阵只有六个参数,而两个因子合计五个,并没有节省很多。LoRA 的参数优势通常在矩阵维度远大于 时更明显,不能只凭“秩为一”就推断节省巨大。
参数比例怎样计算
原矩阵参数量是 ,两个因子合计:
假设一个 的矩阵使用 :原矩阵有 16,777,216 个参数,LoRA 因子有 65,536 个,约为原矩阵的 0.390625%。
这只是单个目标矩阵的新增可训练参数比例。如果给更多层添加适配器,或额外训练嵌入、输出头、偏置,整体数量会不同。基础矩阵仍然存在,不能从模型总参数里直接减掉它。
选择目标层也与秩不同:较高的秩只扩大已经选中的矩阵的更新空间,不能代替对未选模块的直接更新。两者应分别记录。
为什么不能把两个因子都初始化为零
原始 LoRA 的一种初始化方式是让 随机、 为零,使初始增量为零。这让训练开始时的线性层与基础层输出一致。LoRA 初始化说明
如果两个因子都为零,对乘积的普通梯度在这一步也会为零: 的梯度依赖 , 的梯度依赖 ,这条分支就无法靠这种初始化开始学习。
在 随机、 的设置里,第一步 的梯度可能为零,但 通常可以收到信号;随后 不再为零, 才开始改变。看到某个因子最初不变,不应立即断言实现错误。
实际库也支持其他初始化和缩放变体。比如固定版本 PEFT 文档区分了标准缩放和 rank-stabilized 选项,后者使用不同的秩缩放方式。比较实验时不能只写同一个 ,却忽略缩放与初始化已经变化。PEFT 0.17.0 LoRA 配置
少训练权重,不等于不需要反向经过基础模型
基础权重冻结后,通常不必保存它们的参数梯度和优化器状态。但训练适配器仍需要知道输出如何随适配器变化,梯度也可能经过冻结层传播到更早的可训练部分。
因此,激活、临时计算缓冲、基础权重和适配器状态仍会占用内存。输入变长、batch 变大,也仍可能导致内存不足。
一个仅用于理解组成的 FP32 AdamW 假设是:每个可训练参数需要四字节权重、四字节梯度,以及两个各四字节的状态,共十六字节。实际实现可能有额外副本、不同精度、分片或其他优化,不应把十六字节当作通用实测常数。
用这个假设估算时,LoRA 降低的是可训练状态的一部分;基础权重依然按其存储精度计算,激活另算。总显存节省比例一般不等于前面的 0.390625%。
QLoRA 进一步处理基础权重的存储
QLoRA 在量化的冻结基础模型上训练低秩适配器。论文讨论 NF4、双重量化和分页优化器等设计,并区分低比特存储与较高精度计算:权重使用时需要按计算方式进行反量化。QLoRA,第 3 节
所以,“4 bit 微调”不能理解为模型所有计算、梯度和状态都只有四位,也不表示直接对四位基础权重执行普通全参数更新。
假设十亿个权重,每个理想地占四位,仅原始编码就需要五亿字节,约 0.466 GiB;若每个占十六位,则为二十亿字节,约 1.863 GiB。这里没有计入量化元数据、未量化模块、适配器、激活与运行时缓冲。
实际可用性还取决于设备和算子支持。论文中的硬件与结果不能直接保证某台笔记本运行相同方案。选择之前,要核对实现支持并测量,而不是按理论编码大小宣布“一定放得下”。
合并适配器以后,仍要做回归检查
对普通线性 LoRA,在相同数值语义下,可以把 加入基础权重,得到用于推理的合并矩阵。这样不必继续单独执行适配器分支。
但浮点舍入、量化、重新量化和实现路径都可能改变数值。尤其是在量化基础权重上合并、再导出另一种格式时,不应该把代数等式当作完整部署一致性证明。
至少用固定输入比较合并前后的 logits 或目标概率,再比较关键任务输出。若生成采用采样,先用适合数值检查的固定方式,否则很难区分计算差异与采样变化。
适配器还依赖正确的基础模型、层名、词表和模板。只保存一个小文件,却丢掉这些版本信息,不能构成完整交付。
怎样选择,才有可解释的比较
对本卷的结构化提取任务,可以从资源允许的一个基线开始,而不是假设 LoRA 必然优于全参数,或全参数必然更准确。
| 方案 | 主要开放的调整 | 需要测量的代价 |
|---|---|---|
| 全参数微调 | 原有可训练权重直接更新 | 参数状态、训练时间、能力变化 |
| LoRA | 选定模块的低秩增量 | 基础权重、激活、适配器状态与适配能力 |
| QLoRA | 量化基础模型上的适配器 | 量化误差、算子支持、反量化与运行时开销 |
公平比较不要求盲目使用完全相同的学习率,因为不同参数化可能需要不同设置。但应给方案相近的调参预算,固定数据、任务评价和预算口径,并记录实际资源消耗。
若比较不同秩,保持目标模块、缩放定义、数据和评价一致,再明确其余参数如何选择。若改了目标模块又改了秩,结果是整套方案的比较,不是孤立的“秩越大越好”。
第一轮验收先看适配器是否真的在工作
训练前打印可训练参数及其形状,确认没有意外解冻整个基础模型,也没有一个适配器都没插上。
训练后比较基础参数是否符合冻结约定、适配器是否发生变化,以及加载同一适配器后能否恢复相同输出。再在独立材料上测字段正确、缺失处理和格式遵循。
如果模型只更擅长固定模板,先检查数据覆盖和划分,不要把所有失败都归因于秩不够。较大的更新空间不能自动修复相互矛盾的示范。
本篇的矩阵和存储计算可独立核对;三类方案的本地训练效果仍需实际对照,本文不预设胜者。
两个检查理解的问题
第一,一个矩阵的 LoRA 参数只有原矩阵的约 0.39%,为什么不能说整个训练只需要原来 0.39% 的内存?请按权重、梯度、优化器状态和激活拆开回答。
第二,两次 LoRA 实验的秩相同,但目标层和缩放方式不同。它们是否具有相同更新能力与训练尺度?你会补充哪些配置记录?
最后一篇讨论怎样判断 SFT 改善了什么,把训练选择落到可复核的任务结果上。
文章概念网络
从章节进入正文概念。实线表示所属层级,虚线连接跨章节重复出现的概念,不代表因果关系。
55 / 55 个节点 · 正文标记术语与关键词概念
全参数微调与 LoRA 怎样选择:更新空间、显存与量化
回到原文 ↗最后更新于 2026-10-20
引用本文
@article{2026-10-20-llm-training-sft-05-adaptation,
author = {枫语},
title = {全参数微调与 LoRA 怎样选择:更新空间、显存与量化},
journal = {枫语},
year = {2026},
month = {oct},
url = {https://meiluosi.github.io/posts/2026-10-20-llm-training-sft-05-adaptation/}
}