监督微调与参数高效微调
把「法国的首都是哪里?」这条提示词交给一个刚预训练完的模型,它可能反过来给出另外三道考试题。它读过足够多的网络文本,知道首都是巴黎,但它学会的是把文本续写下去,而不是回应文本。没有轮流对话,没有稳定的人设,没有拒绝机制,也没有固定的输出格式。知识已经在场,行为还没有形成。
补上这个差距,是把基座模型变成助手的第一步,也是成本最低的一步。第 5 章 给出的起点很具体:预训练在不适合助手行为的目标下形成了知识,而我们现在得在不重新跑一遍预训练的前提下,建立助手行为。
这个约束塑造了一切。行为上的改变得效果大、用数据少,因为高质量的指令数据靠人来写、靠人来精选,根本攒不出预训练那种规模。它还得省算力、省内存,因为适配模型的人往往不是训练它的人:下游团队手里只有一块或几块加速器,没有集群,而且想要的是许多面向具体任务的变体,而不是一个。复制并更新每个权重的完整微调,会同时破坏这两个目标。
这些约束背后有一个贯穿性的想法。适配,是在一个冻结基座之上做的一个小的、低秩的、加性的、可组合的改变。 这句话里的每个词都对应一个推论:几千条样本能重塑行为,因为改变是小的;一个 rank-16 的适配器能近似替代完整微调,因为改变是低秩的、加性的;两次微调能相加到一起,因为改变是可组合的。下面各节依次展开这三点。
这里先把两个操作机制说清楚:梯度是训练时由损失算出、发给每个权重的信号,指出该往哪个方向微调它;而冻结一个权重,就是让它保持不动,不接收这种更新,停在预训练留下的样子。
为什么几千条样本就能重塑行为
核心方法是监督微调(SFT),也叫指令微调,正是 InstructGPT 把它确立为对齐的标准第一步 (Ouyang et al. 2022)。它沿用 第 5 章 里那个下一词元目标,只是把原始网页文本换成一组精选的(提示词,回复)样本对,并对损失做掩码,让只有回复词元被计分。模型照旧靠预测下一词元来学习,变的是它所预测的那个分布。对一个提示词为 、回复为 的样本对,
其中 是提示词, 是第 个回复词元, 是模型已经看到的回复前缀, 是当前模型给出的下一词元概率。这个负对数似然惩罚的是「正确回复词元概率太低」;概率越高,损失越小。求和只在回复位置上进行。对提示词做掩码,模型就不会把容量花在学习生成用户的那一轮上,也就学会了助手角色的不对称:读提示词,给出回答。
让提示词和回复能区分开来的,是对话模板。基座模型看到的是一条没有区分的词元流。助手得知道用户那一轮在哪里结束、自己这一轮从哪里开始,于是 SFT 用角色词元把每一轮包起来,也就是 <|user|>、<|assistant|> 这类由分词器保留、由模板插入的特殊词元。模板是一份契约:推断时必须用同样的标记,否则就是在模型被调过的分布之外去服务它。这是本部分一个反复出现的道理的最小例子,即适配既关乎权重,也同样关乎格式。图 17.2 追踪一条样本怎样从模板走到被计分的损失。
令人意外的是它需要的数据竟如此之少。这正兑现了那条统一断言里的「小」。浅层对齐假说由 LIMA 论文命名,主张一个模型的知识与能力几乎全在预训练里奠定,SFT 主要教它该用哪一个格式与风格的子分布去说话 (Zhou et al. 2023)。如果这是对的,那么几千条精挑细选的样本就该够用,而 LIMA 恰好展示了这一点:一个 65B 模型在 1,000 条精选样本上调过,不用任何强化学习,就能跟那些经过远更繁重对齐的模型相抗衡 (Zhou et al. 2023)。这个教训重新定义了整个步骤。SFT 是在激发、塑造潜在能力,而不是添加新能力,这正是为什么数据质量与多样性压倒数据数量,也是为什么一个又小又嘈杂的数据集,既能教出对的风格,也能同样轻松地教出一种自信的错误风格。
这种重新定义也带来权衡。样本一少,每条样本都举足轻重,几条错误事实或一个被过度使用的格式,就会教出一个模型会自信地反复犯的毛病。狭窄的 SFT 数据会把一个僵硬的模板固化下来,这就是格式过拟合的失效,过度拒绝(over-refusal)、回答永远带项目符号,都是它的实例。
浅层对齐假说能成立到什么程度,并无定论。它的强读法,即 SFT 只是把预训练能力浮现出来、什么都不添加,被这样一类任务反驳:在足够的数据上做指令微调,明显能教出几百条样本教不出 的新技能与新格式。更准确地说,这个假说对宽泛的指令遵循风格是个好描述,对狭窄的能力获取则是个差描述,而这条界线落在哪里,取决于目标行为离基座分布有多远。把「一千条样本 就够了」当作一个关于风格的断言,而不是关于每个任务的断言。
为什么一个 rank-16 适配器能近似替代完整微调
如果适配是对行为做的一个小的、低维的改变,而不是对知识的整体重写,那么编码它的那个权重更新也该是小的。正是这个推断,让参数高效微调(PEFT)显得可信:冻结预训练权重,只训练一小组新增或选中的参数。要看清这个领域为什么走到那个占主导的方法,不妨一步步看每任务成本如何降低。
图 17.3 里的效率主线,从完整微调一路走向对它越来越廉价的近似。最早的迁移学习配方,是在一个下游任务上微调一个预训练模型的全部权重,也就是 BERT 与 GPT 立下的标准做法。它有效,但既贵又浪费:每个任务都得有模型的一份完整副本,而为了编码往往只是一处狭窄的行为改变,更新却动了每一个权重。第一个答案是适配器,即插在 Transformer 冻结层之间的小瓶颈模块,只有插进去的那些参数参与训练 (Houlsby et al. 2019)。适配器证明了一条原理:很少量的新增参数就能找回完整微调的大部分质量,但它们给每一次前向传播都加了深度,也就加了推断延迟 (Houlsby et al. 2019)。
低秩适配(LoRA)去掉了这个成本,「低秩」与「加性」也正是在这里进入那条断言。一个矩阵的秩,是它的行或列真正彼此独立的方向数目,所以低秩矩阵就是内容塌缩到远少于其维度所允许的那些方向上的矩阵。对一个冻结的权重矩阵 ,LoRA 学习一个低秩更新 (Hu et al. 2021)
其中 是冻结矩阵, 是可训练更新, 是秩预算, 让不同秩下的更新尺度保持可比。秩 ,于是 与 合起来只持有 个参数,而不是 个。只有 与 训练, 保持冻结。背后的假说是,一次微调想施加的那个更新,内在秩很低,所以一个 rank-8 或 rank-16 的分解就能抓住其中大部分 (Hu et al. 2021)。因为这次适配是对现有矩阵做的一个加性更新,而不是一个新子层,推断时乘积 会折回 ,于是被服务的 LoRA 模型零增加延迟,这跟那些外挂额外层的适配器不一样。这就是 LoRA 成为默认 PEFT 方法的原因。图 17.4 展示这两条并行路径,以及各自持有什么。
代入自己的维度与秩,看看 相对完整的 少了多少参数,以及这个比例如何随秩线性增长。
import numpy as np
d, k = 4096, 4096 # 一个权重矩阵,例如一个注意力投影
full = d * k # 完整微调触及每一个权重
ranks = [4, 8, 16, 32, 64]
print(f"完整微调: {full:,} 个可训练参数")
for r in ranks:
lora = r * (d + k) # A 是 r x k,B 是 d x r
print(f" 秩 {r:3d}: {lora:>9,} 个参数 (完整微调的 {100*lora/full:5.2f}%)")
import matplotlib.pyplot as plt
fracs = [100 * r * (d + k) / full for r in ranks]
plt.plot(ranks, fracs, "o-")
plt.xlabel("LoRA 秩 r"); plt.ylabel("可训练参数(完整微调占比 %)")
plt.title("成本随秩线性上升"); plt.grid(True); plt.show()
量化低秩适配(QLoRA)接着处理剩下的那个瓶颈:把冻结基座压到 4-bit,再在其上训练 LoRA 适配器。到那时,瓶颈已经不是可训练参数,而是在优化器的地址空间里持有冻结基座所需的内存。它把冻结的基座权重量化到 4-bit(一种由信息论动机推导出的 NormalFloat 格式,NF4),在其之上以更高精度训练 LoRA 适配器,只在前向、反向传播需要某个权重块时才对它反量化 (Dettmers et al. 2023)。因为基座从不更新,它的量化误差是固定的、可容忍的;因为适配器很小,它们留在 bf16(一种 16 位浮点格式)。结果是一个 65B 模型把适配这一步,装进了大约单块 48GB 显卡能提供的内存里 (Dettmers et al. 2023),这正是需要一个集群和只需要一台工作站之间的区别。有了 QLoRA,对一个前沿规模开放模型的适配,从一个多加速器作业变成了单卡作业,而开放模型微调生态之所以形成如今的形态,很大程度上正源于此。
这种低成本是拿保真度换来的,而这些取舍值得逐一讲清楚。
- 完整微调与 LoRA。 完整微调容量最大,当适配幅度大、或离基座分布远时,是稳妥之选。 LoRA 拿一个小的质量差距(对指令微调通常可忽略,对需要新知识的任务则更大),换来可训练参数的百倍削减,以及一个基座配多个可热插拔适配器的能力。秩是关键控制参数:太低则欠拟合 任务,太高则耗费内存而没有收益,还开始变得像一次完整微调。后来的大规模实践改变了默认做法:把 LoRA 施加到所有线性层、以完整微调约十倍的学习率训练时,只要适配器容量没有 成为瓶颈,LoRA 就能追平完整微调;在 RL 后训练里,哪怕秩非常低也能追平 (Schulman and Thinking Machines Lab 2025)。
- QLoRA 的量化误差。 把基座放在 4-bit,会给每个冻结权重引入一个固定误差。对大多数指令微调来说,这低于噪声底,因为适配器会绕着它学习,但它设下了一个能力上限,精度敏感 的任务可能遇到这个上限。这笔取舍,是拿内存换一个小的、有界的精度风险。
成本随秩线性上升,但它换来的质量会饱和:拖动滑块,看任务质量先快速上升,等秩超过更新的内在维度之后就变平,这正是为什么会存在一个合理区间。
为什么两次微调能被相加到一起
一旦适配是一个小的加性改变,这些改变就能组合,而这正是那条统一断言的最后一个词。模型合并把若干微调后的检查点合成一组权重,无需再训练。最简单的形式是权重平均。任务算术把它 进一步形式化:定义一个任务向量 ,即一个微调后模型与其基座之间的差,这些向量能像权重空间里的方向那样相加、相减、缩放 (Ilharco et al. 2023)。把两个任务向量相加,得到一个两个任务都擅长的模型;把其中一个取负,就把模型从某种行为上推开 (Ilharco et al. 2023)。这之所以根本可行,是因为微调只把一个模型在 损失地形(把每一组权重取值映射到其训练损失的那张曲面)上移动了一小段,而在这么小的邻域里曲面几乎是平的,于是这个位移近似是一个向量,而向量可以组合。
图 17.3 里的合并支线,是从跟效率主线不同的方向来的。模型汤(model soups)表明,把若干从相同初始化、用不同超参数微调出来的模型权重做平均,往往比挑出单个最好的那个 更强,且零推断成本 (Wortsman et al. 2022)。任务算术把平均推广成一套带符号的任务向量代数 (Ilharco et al. 2023)。它暴露的摩擦是干扰:当两个任务向量在某个参数的符号上对不上时,朴素相加会把两者的贡献都抵消掉。TIES-merging 的对策是修剪小幅度的改变、为每个参数选定一个 符号、只合并意见一致的更新 (Yadav et al. 2023);DARE 则在合并前丢弃并重新缩放增量的一大部分 (Yu et al. 2024)。正是这些方法,让一个社区能靠组合各路专才来拼出一个有能力的模型,而不必去运行一条庞大的对齐流水线。
合并以可靠性换取近乎为零的成本,而这笔取舍沿两条线展开。
- 合并与重新微调。 合并几乎不要钱:不训练,不要数据,只对检查点做算术。它也是近似的。合并后的模型是一种折中,可能不如一个真正在任务并集上训练出来的模型,而任务向量之间的 干扰,可能把每个父模型都曾有过的某种能力抹掉。当父模型廉价、一个够好的组合就能接受时,就合并;当组合必须可靠时,就在并集上训练。
运维形态
一次 LoRA 微调,是对标准训练循环做的一个小改动:用分解后的更新把目标线性层包起来,冻结其余一切,只训练 与 。如今实际的默认做法是把所有线性层都包进去,MLP 与 MoE 块也在
内,并以完整微调约十倍的学习率训练适配器;早年只包注意力投影的习惯,即便参数量相同,效果也更差 (Schulman and Thinking Machines Lab 2025)。读者可以在 Hugging Face
PEFT 库的 LoraLayer, peft/src/peft/tuners/lora/layer.py 里找到规范的参考实现,在
bitsandbytes 里找到 4-bit 的 NF4 基座。它的运维形态值得记在心里:磁盘上一个冻结的基座、一个装着小适配器文件的目录,以及一个只加载一次基座、按请求热插拔适配器的服务层,这正是
PEFT 所支撑的部署模式。
有三种失效模式反复出现,每个推论对应一种,各有各的修法。一个欠拟合的 LoRA,即秩对这次适配太小,表现是模型把任务学得不稳,一旦输入稍有变化就回退;提高秩。一个坏掉的对话模板,即服务用 的角色标记跟训练时不同,看起来像一个有能力却无视指令的模型,因为它正被在分布之外提示;把模板精确对齐。还有合并干扰,即组合两个适配器却让两者都退化,表现是合并后的模型比任一 父模型都更差;从朴素平均换成一个感知符号的合并,或者改在并集上训练。
服务层反过来塑造了这里的方法。因为 LoRA 的更新在推断时折回基座权重,它零增加延迟,也不增加 KV 缓存,这正是它为什么胜过那些插入子层的适配器。又因为一个服务器能持有一个基座、按请求热插拔许多小适配器,第 31 章 里那种廉价的多租户服务模式,才让按客户做 LoRA 适配在经济上说得通。适配方法的形态,由服务它的成本所决定。
延伸阅读
- Zhou et al., “LIMA: Less Is More for Alignment,” 2023. arXiv:2305.11206LIMA 表明,仅用 1,000 条精心筛选的提示-回复对对 65B LLaMa 模型进行监督微调(无需 RLHF)即可实现强对齐效果,支持了"表层对齐假说"。
- Hu et al., “LoRA: Low-Rank Adaptation of Large Language Models,” 2021. arXiv:2106.09685LoRA 冻结预训练权重,向每个 Transformer 层注入可训练的低秩矩阵对,与全量微调相比可将可训练参数减少 10,000 倍、将 GPU 显存需求降低 3 倍,且不引入额外推理延迟。
- Dettmers et al., “QLoRA: Efficient Finetuning of Quantized LLMs,” 2023. arXiv:2305.14314QLoRA 通过将冻结的 4 位量化模型的梯度反向传播至 LoRA 低秩适配器,并引入 NF4、双重量化和分页优化器,实现在单张 48GB GPU 上对 65B 参数大语言模型进行参数高效微调。
- Houlsby et al., “Parameter-Efficient Transfer Learning for NLP” (adapters), 2019. arXiv:1902.00751向 BERT 各层插入适配器模块,仅训练全量参数高效微调(PEFT)的 3.6
- Wortsman et al., “Model Soups: Averaging Weights of Multiple Fine-Tuned Models Improves Accuracy Without Increasing Inference Time,” 2022. arXiv:2203.05482对多个微调模型的权重取平均(称为"模型汤")可在不增加推理成本的前提下,优于最佳单一模型并提升分布外鲁棒性。
- Ilharco et al., “Editing Models with Task Arithmetic,” 2023. arXiv:2212.04089任务算术提出任务向量(微调权重减去预训练权重所得方向),通过对其取负或相加即可在无需重新训练的情况下编辑模型行为。
- Yadav et al., “TIES-Merging: Resolving Interference When Merging Models,” 2023. arXiv:2306.01708TIES-MERGING 是一种无需训练的模型合并方法,通过裁剪冗余参数、解决符号冲突、仅对符号对齐的参数求平均,将多个微调模型合并为单一多任务模型。
- Yu et al., “Language Models are Super Mario: Absorbing Abilities from Homologous Models as a Free Lunch” (DARE), 2024. arXiv:2311.03099DARE 通过随机丢弃并重缩放监督微调(SFT)的增量参数,使多个任务专用语言模型无需重新训练即可合并为单一模型。
- Ouyang et al., “Training Language Models to Follow Instructions with Human Feedback” (InstructGPT), 2022. arXiv:2203.02155
- Schulman & Thinking Machines Lab, “LoRA Without Regret” (LoRA on all linear layers at roughly 10x the full fine-tuning learning rate), 2025. thinkingmachines.ai大规模实验表明,把 LoRA 施加到所有线性层(含 MLP 与 MoE)并以完整微调约十倍的学习率训练时,效果与完整微调相当;只作用于注意力层会明显欠佳,而在 RL 后训练中即便秩为 1,LoRA 也能追平完整微调。
评论
登录后评论