LoRA / QLoRA 的真正难点,是管理一份可撤回的参数增量
LoRA 省的是可训练参数、梯度与优化器状态;QLoRA 再压低冻结基座的存储。真正决定结果能否解释和上线的,是模板、Loss 分母、数据切分、目标层、完整显存账、基座身份与回滚证据。
LoRA 限制更新空间,QLoRA 改写冻结基座的存储方式
两者不是同一个旋钮。Low-Rank Adaptation(LoRA,低秩适配)把权重更新参数化为两个小矩阵;Quantized LoRA(QLoRA,量化 LoRA)保留这条可训练路径,同时把冻结基座存成 4-bit 并在计算前按块反量化。二者都不让基座权重参与优化器更新。
直接更新 W
基座参数、梯度和优化器状态都可能进入训练账。容量最大,但 checkpoint、显存、版本隔离和回滚成本最高。
冻结 W₀,训练 A/B
主要节省可训练参数、其梯度与优化器状态;冻结权重仍要驻留或流入计算,激活也不会凭空消失。
再压低 W₀ 存储
用 NF4 等格式保存冻结基座,前向时反量化到 BF16 等计算 dtype;LoRA 参数仍以浮点训练。
不自动保证质量与容量
低秩、4-bit、单卡都只是具体实验和实现条件。数据、目标层、长度、kernel 与硬件变化都会改结论。
原始 LoRA 在 GPT-3 175B 的特定设置中报告:训练显存约从 1.2TB 降到 350GB、checkpoint 约从 350GB 降到 35MB,并带来约 25% 训练吞吐提升。它使用特定目标层与训练栈;这些数字说明可能性,不是“任意模型都省 3× 显存、快 25%”的承诺。
同一段对话,模板、移位和 Mask 能定义出三种不同训练任务
聊天模型最终仍预测下一个 Token。Chat Template(聊天模板)决定角色控制 Token,Causal Shift(因果移位)决定第 t 个 Logit 对齐第 t+1 个目标,Loss Mask(损失掩码)决定哪些目标参与交叉熵。把三者混成“Tokenizer 会处理”最容易制造静默错误。
训练通常不加 generation prompt
完整 assistant 答案已经在序列中;额外插入“开始生成”标记可能重复控制 Token。必须按基座模板说明验证,而不是套通用字符串。
assistant-only 与 completion-only 是两条轴
assistant_only_loss=True 依赖模板暴露 generation 区间;prompt-completion 数据的 completion_only_loss 则选择 completion。两者可组合,但含义不同。
先数有效标签,再开始训练
长 prompt 可能把全部答案截掉。每个 batch 记录有效 assistant Token 数;为 0 就阻断,而不是让 NaN 或空梯度进入后续步骤。
教师强制不是自由生成
teacher-forced token accuracy 看到了真实答案前缀,只能检查局部预测。任务成功率必须从只有 prompt 的输入自由生成,再由确定性规则或校准 grader 判定。
先用 2.5 万参数项目验证链路,再把合同迁移到真实基座
本站项目不下载模型,只用一个本地因果 Transformer 验证 LoRA 数据流、训练 split 专用 Tokenizer、固定留出集、理论内存账、基座指纹、adapter 保存加载、合并/反合并,以及禁用回基座。它是实现冒烟,不是能力 benchmark。
对称整数教学量化
每输出通道 scale,数值限制到 −7…7,再放入 int8 容器。没有真正打包两个 4-bit 值,也不是 NF4、double quantization 或 paged optimizer。
成熟 kernel 与基座格式
按当前 PEFT 文档配置 load_in_4bit、nf4、double quant、BF16 compute dtype,并先运行 prepare_model_for_kbit_training。
examples/lora-qlora/ ├── train.py # 模型、LoRA、教学 4-bit、训练与产物验证 ├── requirements.txt # 只依赖 PyTorch └── README.md # 运行、边界、安全与排错 adapter-out/ ├── adapter.pt # 本地可信教学张量;weights_only=True 加载 ├── adapter_config.json # 目标层、rank、alpha、基座/Tokenizer/模板 SHA-256 ├── tokenizer.json # 仅用 train split 拟合;未知字符 → <unk> └── run_manifest.json # 数据/基座/adapter 指纹、环境、指标与内存账
同一脚本切换两种模式
默认项目只需要 CPU。run manifest 记录 source、seed、基座和数据 split;loader 对 model config、基座、Tokenizer、chat template、目标层、shape 与 dtype 错配 fail closed。
cd examples/lora-qlora
python3 -m venv .venv
source .venv/bin/activate
python -m pip install -r requirements.txt
python train.py --mode lora --epochs 80 --rank 4 --alpha 8 \
--lr 0.03 --batch-size 5 --output adapter-out
python train.py --mode qlora --epochs 80 --rank 4 --alpha 8 \
--lr 0.03 --batch-size 5 --output adapter-qlora冻结浮点基座
epoch 001 | train_nll 3.5990
epoch 080 | train_nll 0.2131
heldout_loss 3.4875 -> 0.5533
heldout_teacher_forced_token_accuracy 0.000 -> 0.800
base_params 24,576 | adapter_params 1,080
parameter_optimizer_lower_bound_mib 0.063
reload 0.00000000 | merge 0.00000572 | unmerge_roundtrip 0.00000000
disable_to_base 0.00000000 | reenable 0.00000000
equivalence_gate PASS · roundtrip≤1e-7 · merge≤1e-5 逻辑 4-bit 冻结基座
epoch 001 | train_nll 3.5963
epoch 080 | train_nll 0.1381
heldout_loss 3.4913 -> 1.0081
heldout_teacher_forced_token_accuracy 0.000 -> 0.800
base_params 24,576 | adapter_params 1,080
parameter_optimizer_lower_bound_mib 0.036
reload 0.00000000 | merge 0.00000477 | unmerge_roundtrip 0.00000000
disable_to_base 0.00000000 | reenable 0.00000000
equivalence_gate PASS · roundtrip≤1e-7 · merge≤1e-5 留出 Loss 下降证明这条教学链路在当前数据上学到信号;0.8 是教师强制 Token 指标,不是四道题自由生成成功率。训练时间故意不列为固定期望值,因为机器负载会变;固定 seed 也不保证跨 PyTorch 版本、平台或 CPU/GPU 逐位一致。
先冻结比较合同,再一次移动一个旋钮
rank、alpha、目标层、学习率、有效 batch、训练 Token 与量化计算 dtype 会共同改变容量和优化。所谓“LoRA 推荐参数”只有在模型 revision、数据、模板、训练预算与评测分母一起固定时才有意义。
| 变量 | 先记录什么 | 常见起点 | 不能外推成什么 |
|---|---|---|---|
| target modules | 真实模块名、形状、层数、是否包含 output head | 先做 q/v 小基线,再比较 q/k/v/o 或 all-linear | “q/v 永远最好”或“all-linear 永远无损” |
| rank r | 每层 A/B 参数数与总可训练参数 | 从小 rank 建基线,再按留出收益扩容 | rank 越大质量必然越高 |
| scaling | 经典 α/r,还是 rsLoRA 的 α/√r | 改变 rank 时保持缩放定义可比较 | 只报 alpha、不报 rank 与变体 |
| learning rate | 优化器、scheduler、warmup、gradient clipping | 短跑 range test,再看稳定区间 | 脱离 batch/数据复制某个“标准 lr” |
| effective batch | micro-batch × accumulation × data-parallel ranks | 按有效 Token 数对齐,不只看样本条数 | 只报单卡 micro-batch |
| training budget | 有效目标 Token、optimizer steps 与 wall time | 主要按 Token/step 对齐,时间作资源结果 | “都跑一小时”就是公平比较 |
目标任务
自由生成成功率、格式正确率或人工 rubric;报告置信区间与关键 slice,不拿训练 Loss 代替。
基座能力回归
通用、拒答、安全与原有领域冻结集;比较 enabled、disabled、merged 三种状态。
资源与服务
同硬件实测峰值 allocated/reserved、tokens/s、wall time、加载/切换延迟和并发下吞吐。
产物与恢复
固定输入 Logit 对账、基座 revision 校验、adapter hash、合并后复测及一键切回上一验证版。
“7B 的 4-bit 只要 3.5GB”只是裸权重下界
权重位数只能回答一部分问题。LoRA 训练还要容纳 adapter 参数、梯度和优化器;QLoRA 还需要量化 scale、反量化临时缓冲与 kernel workspace;两者都要支付激活、Attention 中间量、CUDA context 和 allocator reserved/碎片。
7×10⁹ × 2 bytes,只算权重裸数据。
7×10⁹ × 0.5 bytes,还没算 scale 和运行时。
压缩量化常数开销,不是把全部模型再缩 0.37×。
长序列、batch、未 checkpoint 的层会抬高峰值。
训练峰值至少拆成六本账
“参数理论值”与“进程峰值”要同时保留;前者解释结构,后者决定硬件能否运行。
- 冻结基座量化 code、scale、未量化模块与可能的 master/cast buffer
- AdapterA/B、可选 bias/modules_to_save、梯度和 Adam moments
- 激活batch、sequence、hidden、层数、checkpointing 与 attention kernel
- 临时区反量化 buffer、GEMM workspace、通信与 gradient bucket
- 运行时CUDA context、library cache、模型对象与 dataloader
- Allocatorallocated、reserved、碎片与瞬时峰值分开报告
小 adapter 不代表输入梯度和激活也小
论文对使用 FLAN v2 训练的 LLaMA-7B、batch 1 示例列出约 26MB LoRA 权重与约 567MB 输入梯度;启用 gradient checkpointing 后,平均每条序列约 18MB。对应 Figure 8 使用 sequence length 512,并明确只估算 adapter 与基座权重、不含 attention。数字不能直接拼成任意任务的峰值预算。
Adapter 文件很小,它依赖的身份与证据并不小
PEFT adapter 不包含完整基座。要可复现,至少绑定 immutable base revision、Tokenizer/chat template、目标层、rank/scaling、数据版本、环境与评测;要可恢复,还要明确“加载为 adapter”“在当前方法与量化配置支持时 merge_and_unload”“不合并卸载”三种不同状态。
优先安全张量格式
真实 PEFT 项目优先 safetensors。本站为保持单一 PyTorch 依赖而保存本地 adapter.pt,强制 weights_only=True,仍明确禁止加载不可信文件。
先验基座,再拷张量
模块名字或 shape 对上并不证明语义对上;必须核对 base revision/hash、Tokenizer/template 和 target set。本站示例不匹配即拒绝加载。
先验支持,再合并到新目录
并非所有 PEFT 方法或量化设置都支持 merge;不支持就保留 adapter 路径。支持时也会失去禁用、多 adapter 与 PEFT 方法;不要覆盖唯一基座,并重新评测独立模型。
热切换仍有兼容合同
当前 PEFT hotswap 只支持 LoRA;新 adapter 必须命中原目标层集合或其子集。编译模型若 rank/scaling 不同,要在 compile 前按最大 rank 执行 prepare;路由成功仍不等于质量与隔离通过。
不要从“Loss 降了”直接跳到“可以上线”
失败排查应沿数据、梯度、量化、评测和产物五条证据链定位。每一条都要能给出可观察证据和阻断动作,而不是继续调大 rank 或 gradient clipping 掩盖问题。
| 现象 | 优先证据 | 高概率原因 | 阻断 / 修复 |
|---|---|---|---|
| 有效标签数为 0 | 反解 token/label,逐条数非 −100 | 答案被截断、generation 区间缺失、mask 偏一位 | 阻断 batch;修模板/截断后重建数据版本 |
| 可训练参数异常 | 逐层打印 requires_grad、目标层和 shape | 模块名没匹配,或误解冻基座/bias/head | 阻断训练;白名单匹配并断言参数数 |
| QLoRA 仍 OOM | allocated/reserved 峰值、sequence、kernel trace | 激活、临时缓冲、context、碎片或不支持的 kernel | 降 micro-batch/长度,开 checkpointing,按硬件复核 backend |
| 加载后输出变化 | base hash、adapter hash、固定输入逐层 Logit | 基座/模板/targets/scaling/dtype 不一致 | 拒绝加载;找回正确 revision,不绕过 fingerprint |
| 训练好、留出差 | 实体级去重、split 分布、自由生成错误簇 | 泄漏、过拟合、模板错或任务覆盖不足 | 重划 split;减少预算/容量,补代表性数据 |
| 禁用后没回基座 | 检查 bias、modules_to_save、merged state | 训练了 adapter 外参数,或已 merge_and_unload | 按真实状态恢复上一基座;修订回滚合同 |
七项证据同时通过,才进入 canary
- base、Tokenizer、chat template 使用不可变 revision/hash
- 数据来源、去重、train/held-out split 与有效 label 分母已冻结
- 目标层、rank、scaling、bias、modules_to_save 与可训练参数数已对账
- 自由生成目标指标、关键 slice、基座回归与安全集均不越界
- 同硬件实测峰值显存、吞吐、时间与并发,不拿裸权重代替
- 保存→加载、禁用,以及后端支持时的合并模型,分别通过固定 Logit 与任务复测
- 模型卡写明许可、数据、评测、适用范围、限制、owner 与回滚触发器
一手来源与证据边界
优先使用论文、官方文档、官方模型卡和代码仓库。页面中的数字只代表来源所述设置,不自动外推到其他模型与数据。
冻结基座、矩形低秩更新、A/B 初始化、α/r 缩放,以及 GPT-3 175B 实验中的参数、显存与 checkpoint 口径。
原始 loralib 的实现接口、merge 行为和论文代码边界。
NF4、double quantization、paged optimizers、反量化计算路径、65B/48GB 与内存分解实验的原始口径。
论文训练脚本、配置和复现实验入口;用于区分本站教学量化与真实 QLoRA。
4-bit BitsAndBytesConfig、NF4、double quant、BF16 compute dtype、prepare_model_for_kbit_training 与 all-linear 示例。
target_modules、rank、alpha、rsLoRA、bias、modules_to_save 与初始化的当前参数语义。
adapter_model、adapter_config、README、base_model_name_or_path、revision 与 safetensors 默认产物。
load、disable、unload、merge_and_unload 及合并后失去 PEFT 控制能力的边界。
仅 LoRA、目标层同集/子集,以及不同 rank/scaling 在 torch.compile 前的 prepare 约束。
角色消息如何变成控制 Token、训练/推理 generation prompt 和重复 special token 风险。
prompt-completion、completion-only loss、assistant-only loss 及 generation 区间模板要求。
Python/PyTorch 下限、NVIDIA/CPU/Intel XPU/Gaudi 等当前后端支持与动态硬件边界。
类别索引目标下 ignore_index=-100 的损失、梯度与 mean 分母定义。
相同 seed 不保证跨 PyTorch 版本、平台或 CPU/GPU 完全复现。
base model、数据、许可、训练参数、评测结果、预期用途与限制的发布说明。
pickle 反序列化风险、扫描局限与优先使用 safetensors 的安全原因。
安全、快速且仅保存张量的数据格式;用于解释生产 adapter 与本站本地 .pt 教学格式的差异。