【大模型Wiki】11 · 参数高效微调:LoRA 与 PEFT
参数高效微调:LoRA 与 PEFT
新增篇目(原笔记 35 中仅提到 ChatGLM 的 P-Tuning,本篇系统整理 2026 年主流的 PEFT 方法)。
工具:https://github.com/huggingface/peft
一、为什么需要参数高效微调
全量微调一个 7B 模型(FP16 + AdamW)需要约 112GB+ 显存(权重 14G + 梯度 14G + 优化器状态 56G + 激活),个人和中小团队根本玩不起。PEFT(Parameter-Efficient Fine-Tuning) 冻结原模型、只训练极少量新增参数:
| 方法 | 可训练参数占比 | 原理 |
|---|---|---|
| Adapter | ~1% | 层间插入小瓶颈 MLP(推理有额外延迟) |
| P-Tuning / Prompt Tuning | <0.1% | 只训练可学习的连续提示向量(ChatGLM 官方方案) |
| LoRA | 0.1%~1% | 低秩分解旁路(当前事实标准) |
| QLoRA | 同 LoRA | 底座 4bit 量化 + LoRA,消费级显卡微调 70B |
| DoRA | 同 LoRA | 在 LoRA 上再分解幅度/方向,精度更高 |
为什么全量微调这么"贵"?关键在优化器状态。AdamW 为每个参数维护 m(一阶动量)和 v(二阶动量),都是 FP32,加上参数本身的 FP32 副本,每个可训练参数要 4+4+4 = 12 字节的优化器/主权重开销,叠加 2 字节的梯度、2 字节的模型权重,单是参数相关就约 18 字节/参数。7B × 18 ≈ 126GB,加上前向激活,轻松破 112GB。PEFT 的精髓就在于:把"可训练参数"砍到 0.1% 量级,优化器状态开销便随之降到可忽略,原模型权重只需以冻结形式常驻显存。
PEFT 的额外好处:
- 多任务轻量切换:一个底座 + N 个几 MB 的 LoRA 适配器,按任务热插拔,不必为每个任务存一份完整模型。
- 避免灾难性遗忘:冻结底座,新任务只学"增量",原能力基本不丢。
- 可合并:训练完把适配器合并回底座,推理零额外开销(见第三节)。
二、LoRA 原理
核心假设:微调引起的权重变化矩阵 ΔW 是低秩的——变化集中在少数几个"方向"上,可以用两个小矩阵的乘积近似。
这个假设并非拍脑袋。Aghajanyan 等人 2020 年的研究《Intrinsic Dimensionality Explains the Effectiveness of Language Model Fine-Tuning》证明:预训练语言模型在微调时,其有效"内在维度"(intrinsic dimension)非常小——即使把更新限制在一个几百到几千维的子空间里,也能达到接近全量微调的效果。换句话说,模型从"通用"到"适配某个具体任务"所需的改变,本质上只发生在少数几个方向上,这正是低秩分解成立的理论基础。

冻结的 W (d×k)
输入 x ──────┬──────────────► h = Wx
│
│ ΔW = B·A
└─► A (r×k) ─► B (d×r) ─┐
r << min(d,k) ▼
h = Wx + (α/r)·B·A·x
2.1 低秩假设的数学直觉(ΔW = BA,秩 r 的含义)
设某线性层原始权重为 \(W_0 \in \mathbb{R}^{d \times k}\),微调后我们希望它变成 \(W_0 + \Delta W\)。LoRA 不直接学 \(\Delta W\)(那仍是 \(d\times k\) 的大矩阵),而是把它分解为:
其中 \(r \ll \min(d, k)\) 就是秩(rank)。
- 矩阵乘积 \(BA\) 的秩最多为 \(r\)(因为 \(B\) 只有 \(r\) 列、\(A\) 只有 \(r\) 行),所以 \(\Delta W\) 被强制限制在一个秩不超过 \(r\) 的低维子空间里——这就是"低秩"二字的字面含义。
- 参数量从 \(d\times k\) 降到 \(r\times(d+k)\)。当 \(d=k=4096\)、\(r=16\) 时,原矩阵约 16.7M 参数,LoRA 仅 \(16\times 4096 + 4096\times 16 \approx 131K\),不到 1%,却已能承载该层的绝大多数有效更新。
- \(r\) 越大,表达能力越强、越接近全量微调,但参数量与过拟合风险也上升。\(r\) 太小则不足以表示任务所需的更新方向。经验甜点区通常在 8~64;极少数超大容量需求会上到 128/256。
前向计算变为:
- \(W_0\) 冻结不更新;\(A, B\) 是唯一可训练参数。
- 因子 \(\frac{\alpha}{r}\)(alpha 缩放)很关键:它把 LoRA 更新的幅度与秩 \(r\) 解耦。直觉是——\(\Delta W = BA\) 的"规模"会随 \(r\) 增大而自然变大(因为更多项相加),除以 \(r\) 做归一化、再用 \(\alpha\) 统一调节"LoRA 分支相对底座的权重"。常见配置 \(\alpha = 2r\),此时 \(\alpha/r = 2\),表示 LoRA 增量在训练初期以约 2 倍于某种基准的尺度进入。\(\alpha\) 调大 → LoRA 影响更强(更快拟合但也更易过拟合);\(\alpha\) 调小 → 更保守。
2.2 为什么冻结原权重
- 保留预训练知识:底座里编码了海量通用语言/世界知识,冻结它就不会在适配小任务时被"冲掉",避免灾难性遗忘。
- 训练更稳定:可训练参数极少,优化曲面简单,对学习率不那么敏感,不易发散。
- 可插拔:冻结底座意味着同一份底座权重可以被 N 个任务共享,每个任务只存自己的 \(A,B\)(通常几十 MB),切换/合并都极便宜。
- 显存友好:底座权重以冻结形式存在(可 offload 到 CPU 或量化),只需为 \(A,B\) 维护优化器状态,这正是它能在消费卡上跑大模型的根本原因。
初始化细节:
- \(A\) 用随机高斯初始化(小方差,如 \(kaiming\_uniform\) 风格);\(B\) 初始化为全零。
- 这样训练起点 \(\Delta W = BA = 0\),模型输出与未微调的底座完全一致,训练从"原模型行为"平滑开始,不会因随机旁路引入初始扰动。
- 随训练进行,\(A\) 先学到方向、\(B\) 再把幅度拉起来,最终收敛到有意义的低秩更新。
2.3 推理时可合并
训练完成后,把 \(\frac{\alpha}{r}BA\) 直接加回冻结权重 \(W_0\),得到合并后的权重 \(W'\),零额外延迟——推理时只剩一次普通矩阵乘,没有旁路开销。这与 Adapter(推理时要额外过瓶颈 MLP,有串行延迟)形成鲜明对比,是 LoRA 胜过 Adapter 成为事实标准的关键原因之一。
不同任务训练不同的 A/B(几十 MB),共享同一个底座权重。
以 d=4096、k=4096、r=16 为例:全量微调该层需 16.7M 参数,LoRA 只需 2×4096×16 ≈ 131K,不到 1%。
2.4 QLoRA:把底座压到 4-bit 再 LoRA
再进一步:把冻结的底座量化为 4-bit(NF4),LoRA 部分保持 BF16 训练。7B 模型微调显存降到 ~10GB,一张 24G 消费卡能微调 33B 级模型——这是"人人可微调"的功臣。
QLoRA 的两项关键创新(Dettmers et al., 2023):
- NF4(NormalFloat 4-bit):专为"近似标准正态分布"的 LLM 权重设计的信息论最优 4-bit 数据类型。普通 INT4 是均匀量化,对集中在 0 附近、长尾的权重分布不友好;NF4 把 16 个 4-bit 码本点按标准正态分布的分位数均匀铺设,使量化误差最小。
- 双重量化(Double Quantization):量化本身需要"量化常数"(scale/zero-point),这些常数也要占显存。双重量化即对"量化常数"再做一次量化,把平均每个参数 0.5 字节的常数开销再压缩到 ~0.127 字节,省下约 3/4 的常数显存——对 65B 级别模型可省下数 GB。
- 此外引入 分页优化器(Paged Optimizers):用 NVIDIA 统一内存(UVM)在显存紧张时把优化器状态分页到 CPU,避免梯度爆发时 OOM 崩溃。
QLoRA 的显存账本(以 7B 为例):
- 底座 NF4:7B × 0.5 字节 ≈ 3.5 GB(+双重量化常数约 0.13GB)。
- LoRA 旁路(BF16)+ 其梯度 + 优化器状态:仅可训练参数(约 0.1%~1%)相关,几 GB 量级。
- 激活/KV:随 batch 与序列长度,约 2–4 GB。
- 合计 约 10 GB 出头,RTX 3090/4090(24GB)即可。33B 在 24GB 卡(分页)、65B 在 48GB 卡上均可 LoRA。
2.5 PEFT 家族的其他方法(与 LoRA 对比)
| 方法 | 训练什么 | 参数量 | 推理开销 | 特点 / 适用 |
|---|---|---|---|---|
| Prompt Tuning (Lester 2021) | 输入侧的软提示向量 | <0.1% | 无(拼到输入) | 只改 embeddings 前缀,最简单但能力上限低 |
| Prefix Tuning (Li & Liang 2021) | 每层 K/V 前拼接的可训练前缀 | ~0.1–1% | 有(每层前缀参与注意力) | 在每层注入可训练"上下文",比 Prompt Tuning 强 |
| P-Tuning v2 (Liu 2022) | 每层连续提示(类似 prefix) | ~0.1–3% | 有 | ChatGLM 官方方案,多任务稳定 |
| Adapter (Houlsby 2019) | 层间瓶颈 MLP | ~1–3% | 有(串行延迟) | 精度好但有推理延迟,已多被 LoRA 替代 |
| LoRA (Hu 2021) | 低秩旁路 A/B | 0.1–1% | 可合并、零延迟 | 事实标准 |
| AdaLoRA (Zhang 2023) | 以 SVD 参数化 ΔW,自适应分配秩 | 同量级 | 可合并 | 把总秩预算按层/模块重要性动态分配,难任务更省 |
| (IA)³ (Liu 2022) | 对激活做缩放的向量 | 极小 | 无 | 极轻量,适合超大模型多任务 |
| DoRA (Liu 2024) | 在 LoRA 上拆幅度/方向 | 同 LoRA | 可合并 | 精度更高,略增计算 |
要点:
- Prefix / P-Tuning:不碰权重,而是往注意力里"塞"一段可训练的前缀上下文,相当于让模型自己学会"怎么读这个任务"。P-Tuning v2 在每层都加,是 ChatGLM 系的官方微调法。
- AdaLoRA:普通 LoRA 给每一层、每一模块均匀分配同一个 \(r\);AdaLoRA 认为"不同层的重要性不同",于是对 \(\Delta W\) 做 SVD 参数化,并据敏感度把有限的秩预算自适应倾斜到更重要的层/模块,在相同参数预算下通常优于均匀 LoRA。
- (IA)³ / DoRA:更进阶的变体,前者极轻,后者在 LoRA 之上再分解"幅度(magnitude)"和"方向(direction)"做归一化,精度更稳。
三、实战:PEFT + transformers
3.1 基础 LoRA 训练
from peft import LoraConfig, get_peft_model
from transformers import AutoModelForCausalLM
model = AutoModelForCausalLM.from_pretrained(
"Qwen/Qwen3-8B", torch_dtype="bfloat16", device_map="auto")
lora_config = LoraConfig(
task_type="CAUSAL_LM",
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"], # 现代做法:全线性层
)
model = get_peft_model(model, lora_config)
model.print_trainable_parameters()
# trainable params: 42M || all params: 8B || trainable%: 0.52%
# 之后正常用 Trainer/transformers 训练循环即可
逐参数讲解:
task_type="CAUSAL_LM":告诉 PEFT 这是因果语言模型(自回归),决定如何注入 LoRA 与计算损失。序列标注用SEQ_CLS、Seq2Seq 用SEQ_2_SEQ_LM等。r=16:低秩维度(见 2.1)。容量/开销的旋钮,常用 8/16/32/64。lora_alpha=32:缩放因子 \(\alpha\)。与 \(r\) 配合得到有效系数 \(\alpha/r = 2\)。想让 LoRA 更强可调大(如 64 → 系数 4)。lora_dropout=0.05:在 LoRA 旁路输入上加 dropout,抑制过拟合,对小数据集尤其有用。target_modules:把 LoRA 注入哪些线性层。- 只注注意力(
q/k/v/o_proj)是早期做法,省参数但容量有限。 - 现代做法把全部线性层都注上(
q/k/v/o+ FFN 的gate/up/down_proj),因为 FFN 也承载大量任务知识,全注效果最好、参数量仍极小(如上例仅 0.52%)。 - 不同模型层名不同:Llama/Qwen 系是
*_proj;ChatGLM 可能是query_key_value;不确定时用model.named_modules()打印找线性层名。
- 只注注意力(
3.2 QLoRA 训练(4-bit 底座)
import torch
from transformers import (AutoModelForCausalLM, AutoTokenizer,
BitsAndBytesConfig)
from peft import LoraConfig, get_peft_model, prepare_model_for_kbit_training
# 1) 4-bit 量化配置(NF4 + 双重量化)
bnb_cfg = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_quant_type="nf4", # 用 NF4 而非普通 int4
bnb_4bit_compute_dtype=torch.bfloat16, # 计算时反量化到 bf16
bnb_4bit_use_double_quant=True, # 双重量化,省常量显存
)
model = AutoModelForCausalLM.from_pretrained(
"meta-llama/Llama-3.1-70B", quantization_config=bnb_cfg,
device_map="auto")
# 2) 让冻结的 4-bit 模型支持梯度流(修补 layernorm/embedding)
model = prepare_model_for_kbit_training(model)
lora_config = LoraConfig(
r=32, lora_alpha=64, 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, lora_config)
model.print_trainable_parameters()
# 70B 仅在 48G 卡上即可 LoRA(底座约 35GB NF4 + 少量可训练状态)
关键踩坑:
- 4-bit 底座上做 LoRA 必须
prepare_model_for_kbit_training,否则某些归一化层/embedding 不支持 4-bit 梯度会报错。 bnb_4bit_compute_dtype用 bf16 比 fp16 在长训练里更稳。- QLoRA 训练时底座权重仍是 4-bit(不更新),只有 LoRA 在 bf16 更新——这就是它省显存的秘密。
3.3 合并与导出
merged = model.merge_and_unload() # LoRA 权重并入底座
merged.save_pretrained("qwen3-8b-my-task")
merge_and_unload() 把 \(\frac{\alpha}{r}BA\) 加回 \(W_0\) 并释放 LoRA 旁路,得到的 merged 是普通 PreTrainedModel,可像原模型一样 from_pretrained 加载、无推理开销。
其它导出形式:
- 只存适配器(不合并):
model.save_pretrained("lora-adapter")仅保存几 MB 的adapter_model.safetensors,部署时与底座分离加载(PeftModel.from_pretrained(base, "lora-adapter")),方便多任务热插拔。 - 转 GGML/GGUF:用
llama.cpp的convert工具把合并后的模型量化成端侧格式。 - 合并后继续量化:合并得到的 FP16 模型可再过 AWQ/GPTQ(见第 6 篇)压成 4-bit 上线。
注意:合并是不可逆的(LoRA 增量已固化进权重),若还想保留"多任务切换"能力,应分开存适配器而非合并。
3.4 一整套工具链
| 工具 | 定位 |
|---|---|
| LLaMA-Factory | 零代码 WebUI:SFT/DPO/LoRA 全流程,支持主流开源模型(推荐入门) |
| Unsloth | 单卡微调提速 2 倍、省显存 70%,LoRA 专用 |
| ms-swift | 魔搭官方,中文生态全 |
| transformers + PEFT + TRL | 手工组合,最灵活 |
| Axolotl | YAML 配置式,社区模板多 |
# LLaMA-Factory 示例:一条命令完成 QLoRA SFT
llamafactory-cli train examples/train_qlora/qwen3_lora_sft.yaml
# Unsloth:手动加载即自动获得 2x 提速 + 省显存
from unsloth import FastLanguageModel
model, tokenizer = FastLanguageModel.from_pretrained(
"Qwen/Qwen3-8B", max_seq_length=2048, load_in_4bit=True)
model = FastLanguageModel.get_peft_model(
model, r=16, lora_alpha=32,
target_modules=["q_proj","k_proj","v_proj","o_proj",
"gate_proj","up_proj","down_proj"],
)
# 之后照常用 Trainer;Unsloth 重写了反向核,显存/速度双优
3.5 显存占用估算(实战对照表)
下表给出"训练"阶段的显存量级(仅权重+优化器+梯度,不含大 batch 激活),便于选卡:
| 底座 | 方式 | 可训练参数 | 训练显存约 |
|---|---|---|---|
| 7B | 全量微调 FP16 | 100% (7B) | ~112 GB(多卡) |
| 7B | LoRA(FP16 底座) | ~0.5% | ~16–20 GB(单 24G 卡) |
| 7B | QLoRA(4-bit 底座) | ~0.5% | ~8–10 GB(单 12–24G 卡) |
| 13B | QLoRA | ~0.5% | ~12–16 GB |
| 33B | QLoRA | ~0.5% | ~20–24 GB |
| 70B | QLoRA | ~0.5% | ~40–48 GB(单 48G 卡) |
一句话:QLoRA 让你用消费级显卡微调原本需要数十张 A100 的模型,这是 2024 年以来开源微调爆发的技术前提。
3.6 端到端训练示例(TRL + SFT + LoRA)
下面给出一个"从数据到可部署模型"的完整最小闭环,用 HuggingFace TRL 的 SFTTrainer(兼容 PEFT):
import torch
from datasets import load_dataset
from transformers import (AutoModelForCausalLM, AutoTokenizer,
BitsAndBytesConfig, TrainingArguments)
from trl import SFTTrainer
from peft import LoraConfig
# 1) 4-bit 底座(QLoRA)
bnb = BitsAndBytesConfig(load_in_4bit=True,
bnb_4bit_quant_type="nf4",
bnb_4bit_compute_dtype=torch.bfloat16,
bnb_4bit_use_double_quant=True)
model = AutoModelForCausalLM.from_pretrained(
"Qwen/Qwen3-14B", quantization_config=bnb, device_map="auto")
tokenizer = AutoTokenizer.from_pretrained("Qwen/Qwen3-14B")
tokenizer.pad_token = tokenizer.eos_token # 防 pad 警告
# 2) LoRA 配置
lora = LoraConfig(r=32, lora_alpha=64, lora_dropout=0.05,
target_modules=["q_proj","k_proj","v_proj","o_proj",
"gate_proj","up_proj","down_proj"],
task_type="CAUSAL_LM")
# 3) 数据:指令数据需 apply_chat_template 变成对话格式
data = load_dataset("tatsu-lab/alpaca", split="train")
def fmt(ex):
msg = [{"role":"user","content":ex["instruction"]+ex["input"]},
{"role":"assistant","content":ex["output"]}]
return {"text": tokenizer.apply_chat_template(msg, tokenize=False)}
data = data.map(fmt)
# 4) 训练参数
args = TrainingArguments(
output_dir="./qwen3-14b-lora", per_device_train_batch_size=4,
gradient_accumulation_steps=4, num_train_epochs=3,
learning_rate=2e-4, fp16=False, bf16=True,
logging_steps=10, save_strategy="epoch", optim="paged_adamw_8bit",
)
trainer = SFTTrainer(model=model, args=args, train_dataset=data,
peft_config=lora, tokenizer=tokenizer,
dataset_text_field="text",
max_seq_length=2048)
trainer.train()
trainer.save_model("./qwen3-14b-lora-final") # 只存 LoRA 适配器
要点说明:
optim="paged_adamw_8bit"与 4-bit 底座最搭,显存最省;学习率对 LoRA 通常取1e-4 ~ 3e-4,比全量微调大一个量级(因可训练参数少,需更强步长)。dataset_text_field="text"配合apply_chat_template后的纯文本字段,最简单可靠;也可传formatting_func自定义。- 训练完只得到几 MB 适配器,部署时
PeftModel.from_pretrained(base, "./qwen3-14b-lora-final")即可,或merge_and_unload()合并上线。
3.7 如何选秩 r 与目标模块(经验表)
| 场景 | 推荐 r | alpha | target_modules | 说明 |
|---|---|---|---|---|
| 简单格式/指令适配 | 8 | 16 | 仅 q/v_proj | 省参数,够用 |
| 通用指令微调(7~14B) | 16~32 | 32~64 | 全线性层 | 社区最常用甜点 |
| 代码/数学专项(难任务) | 32~64 | 64~128 | 全线性层 | 需更大容量 |
| 超大模型(70B+)多任务 | 16 | 32 | 全线性层 | 控制总参数 |
| 追求极限精度(DoRA) | 同 LoRA | 同 LoRA | 全线性层 | DoRA 略优于 LoRA |
经验法则:
- 先全线性层 + r=16 起步,看验证集;不够再加 r,过拟合则降 r 或加
lora_dropout、减 epoch。 - 不要盲目堆 r:r 从 16 提到 64 参数量翻 4 倍、收益却递减,多数任务 32 已封顶。
- 难任务优先加数据而非加 r:LoRA 的容量瓶颈更多由"数据覆盖度"决定,r 只是上限。
四、微调 vs RAG vs 提示工程
| 方式 | 解决什么 | 不解决什么 |
|---|---|---|
| 提示工程 | 简单指令、格式控制 | 知识注入、风格深度定制 |
| RAG | 知识新鲜/私有(事实性) | 行为、格式、领域语言习惯 |
| LoRA 微调 | 任务风格、输出格式、领域术语、行为习惯 | 高频更新的事实知识(会过时) |
| 全量微调/继续预训练 | 领域语言大迁移(医疗/法律语料) | 成本极高 |
经验法则:知识用 RAG,行为用微调,两者可叠加。先试提示工程,收益不够再上 LoRA,最后才考虑全量训练。
更细的取舍:
- 知识时效性强、需可溯源(公司文档/最新法规)→ RAG 优先,因为微调进权重后难更新、且可能"记错出处"。
- 需要稳定的输出格式、固定的语气人设、特定领域术语用法(如客服话术、代码风格)→ LoRA 微调,因为 RAG 只能喂上下文、改不了"说话方式"。
- 二者叠加最常见:RAG 提供事实、LoRA 提供"按我们的风格回答"的能力。
五、2026 年补充:RL 时代之后的"微调"
- SFT 仍是起点:用高质量指令数据教会"格式与任务"
- DPO:偏好对直接优化,无需 RM,开源社区后训练标配
- GRPO/RLVR(DeepSeek-R1 路线):用可验证奖励(数学答案对错、代码测试通过)做强化学习,激发推理能力——小团队可用 verl、TRL 的 GRPOTrainer 在 LoRA 规模上复现"思考能力"的涌现
- 开源数据集:tulu-3、OpenHermes、中文的 COIG/Belle 可直接起步
在 RL 后训练里,LoRA 依然有用武之地:
- LoRA 做 RL 的策略更新:verl / TRL 的
GRPOTrainer支持只更新 LoRA 旁路,显存仅为全量 RL 的零头,个人开发者也能在单卡上跑"推理模型微调"。 - DPO 与 LoRA 天然契合:DPO 只需偏好对(chosen/rejected),在 LoRA 上做直接偏好优化,无需训练奖励模型(RM),社区后训练标配。
- 一个常见误区:RLVR 在 LoRA 上"涌现"推理能力需要足够大的底座(一般 ≥ 7B)和足够多的可验证样本;在 1.5B 这种过小模型上,LoRA + RLVR 收益有限,应优先用蒸馏(见第 6 篇)。
六、常见踩坑与最佳实践
target_modules写错层名:不同模型线性层命名不同,写错会导致 LoRA 没注入或报错。先用print([n for n,_ in model.named_modules() if 'proj' in n])核对。r与alpha失衡:若alpha/r过小(如 r=64, alpha=16 → 0.25),LoRA 增量被压得太弱、学不动;一般保持alpha = 2r。- 数据集格式:PEFT 本身不处理数据,需配合
transformers的DataCollatorForLanguageModeling或 TRL 的 SFT 脚本;指令数据记得做 chat 模板(apply_chat_template),否则学不到对话格式。 - QLoRA 未
prepare_model_for_kbit_training:会报"梯度不支持 4-bit"类错误。 - 合并后精度异常:合并前的 LoRA 必须训练收敛;半路合并会丢失更新。合并后用一小批样本对比合并前后输出是否一致(应几乎相同)。
- 多 LoRA 堆叠:可同时加载多个适配器并设权重(
model.set_adapter(["a","b"])、set_adapter_scale),但叠加过多可能相互干扰。 - 保存与加载一致性:部署时若用
PeftModel.from_pretrained加载适配器,底座的torch_dtype/量化配置必须与训练时一致,否则数值漂移。
七、参考
- LoRA 论文:https://arxiv.org/abs/2106.09685
- QLoRA:https://arxiv.org/abs/2305.14314
- PEFT 文档:https://huggingface.co/docs/peft
- LLaMA-Factory:https://github.com/hiyouga/LLaMA-Factory
- AdaLoRA:https://arxiv.org/abs/2303.10512
- (IA)³:https://arxiv.org/abs/2205.05638
- DoRA:https://arxiv.org/abs/2402.09353

浙公网安备 33010602011771号