Loading

【大模型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)非常小——即使把更新限制在一个几百到几千维的子空间里,也能达到接近全量微调的效果。换句话说,模型从"通用"到"适配某个具体任务"所需的改变,本质上只发生在少数几个方向上,这正是低秩分解成立的理论基础。

LoRA 低秩分解

        冻结的 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\) 的大矩阵),而是把它分解为:

\[\Delta W = B A,\quad A \in \mathbb{R}^{r \times k},\; B \in \mathbb{R}^{d \times r} \]

其中 \(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。

前向计算变为:

\[h = W_0 x + \Delta W x = W_0 x + \frac{\alpha}{r} B A x \]

  • \(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 推理时可合并

\[W' = W_0 + \frac{\alpha}{r} B A \]

训练完成后,把 \(\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 篇)。

六、常见踩坑与最佳实践

  1. target_modules 写错层名:不同模型线性层命名不同,写错会导致 LoRA 没注入或报错。先用 print([n for n,_ in model.named_modules() if 'proj' in n]) 核对。
  2. r 与 alpha 失衡:若 alpha/r 过小(如 r=64, alpha=16 → 0.25),LoRA 增量被压得太弱、学不动;一般保持 alpha = 2r。
  3. 数据集格式:PEFT 本身不处理数据,需配合 transformers 的 DataCollatorForLanguageModeling 或 TRL 的 SFT 脚本;指令数据记得做 chat 模板(apply_chat_template),否则学不到对话格式。
  4. QLoRA 未 prepare_model_for_kbit_training:会报"梯度不支持 4-bit"类错误。
  5. 合并后精度异常:合并前的 LoRA 必须训练收敛;半路合并会丢失更新。合并后用一小批样本对比合并前后输出是否一致(应几乎相同)。
  6. 多 LoRA 堆叠:可同时加载多个适配器并设权重(model.set_adapter(["a","b"])、set_adapter_scale),但叠加过多可能相互干扰。
  7. 保存与加载一致性:部署时若用 PeftModel.from_pretrained 加载适配器,底座的 torch_dtype/量化配置必须与训练时一致,否则数值漂移。

七、参考

posted @ 2026-09-19 05:42  Stellan7  阅读(36)  评论(0)    收藏  举报