大模型微调方法综述
概述
大模型微调(Fine-Tuning)是指在预训练模型的基础上,使用特定领域或任务的数据对模型进行进一步训练,使其更好地适配下游任务的过程。
微调的本质是迁移学习的一种实践:预训练模型在大型通用数据集上学习到了丰富的语言知识和世界知识,通过微调可以让这些知识在特定任务上发挥更好的效果。
1. 大模型训练的两阶段范式
1.1 阶段一:预训练(Pre-training)
预训练阶段,大型模型在大规模无标签数据集上训练,目标是使模型掌握语言的统计特征和基础知识。
- 数据:海量无标注文本(网页、书籍、论文等)
- 目标:学习词汇含义、句子构造规则、文本的上下文关系
- 方式:无监督学习(如自回归语言建模、掩码语言建模)
- 产出:基座模型(Base Model),如 GLM-130B、GPT-3、LLaMA
预训练完成后,模型具备了通用的预测能力,但对特定任务的表现还不够精准。
1.2 阶段二:微调(Fine-tuning)
预训练完成的模型在针对性的任务数据集上接受进一步训练。
- 数据:特定领域的标注数据或指令数据
- 目标:适配具体任务,如情感分析、实体识别、对话生成
- 方式:有监督学习
- 产出:领域模型或对话模型,如 ChatGLM-6B、GPT-4
1.3 为什么要微调?
微调的核心价值在于赋予大模型更精细化的能力:
| 场景 | 说明 |
|---|
| 整合本地知识库 | 让模型基于企业内部文档回答问题 |
| 领域适配 | 使通用模型掌握医学、法律、金融等专业知识 |
| 任务优化 | 提升模型在特定NLP任务上的表现 |
| 风格对齐 | 让模型输出符合特定风格或格式要求 |
以多模态模型 VisualGLM 为例,作为通用多模态模型,当应用于医学影像判别时,需要输入医学影像领域的数据集进行微调,以提升在医学影像识别方面的表现。
2. 微调方法分类体系
大模型微调方法可以从多个维度进行分类:
2.1 按更新参数范围分类
| 类型 | 代表方法 | 更新参数占比 |
|---|
| 全参数微调 | Full Fine-tuning | 100% |
| 部分参数微调 | BitFit(只更新bias) | <0.1% |
| 新增参数微调 | Adapter、Prefix Tuning、Prompt Tuning | 0.1%~5% |
| 重参数化微调 | LoRA、AdaLoRA、QLoRA | 0.1%~1% |
2.2 按训练数据类型分类
- 指令微调(SFT):使用指令-回复对训练,让模型学会遵循指令
- 增量预训练(Continue Pre-training):使用领域无标注文本继续预训练
- RLHF:基于人类反馈的强化学习,对齐人类偏好
3. 七大经典微调方法详解
3.1 LoRA(Low-Rank Adaptation)
核心思想
LoRA 的核心假设是:大模型参数更新具有较低的"内在秩"。即使使用很小的秩也能达到很好的效果。
原模型参数更新可以表示为:
W=W0+ΔW
LoRA 不直接更新 W0,而是用低秩分解来近似 ΔW:
ΔW=BA⋅rα
其中 A∈Rr×k,B∈Rd×r,r 远小于 d 和 k。
操作流程
- 确定目标权重矩阵:在模型的多头自注意力和前馈网络部分识别需要微调的权重矩阵
- 引入低秩矩阵:引入维度较小的低秩矩阵 A(d×r)和 B(r×k)
- 计算低秩更新:通过矩阵乘积 BA 生成对原始权重矩阵的低秩近似调整
- 结合原始权重:新权重 = 原始权重 + BA
示例
假设有一个通用语言模型,要将其微调用于医疗健康文本处理:
- 采用 LoRA 方法,无需直接修改模型现有的大量权重
- 只需在模型的关键部位引入低秩矩阵
- 通过这些矩阵的乘积进行有效的权重调整
- 模型就能更好地适应医疗健康领域的专业语言和术语
- 同时避免了大规模权重调整和重新训练的必要
特点
- 冻结原模型:原模型参数全部冻结,只训练 A 和 B 两个小矩阵
- 推理无延迟:推理时可以将 BA 合并到原权重中
- 可插拔切换:不同任务只需切换不同的 LoRA 权重
- 生态完善:HuggingFace PEFT 库原生支持
3.2 QLoRA(Quantized Low-Rank Adaptation)
核心思想
QLoRA 是 LoRA 与深度量化技术结合的高效微调手段,核心在于:
-
4-bit 量化:将预训练模型量化为 4 位存储
- 使用低精度存储数据类型:4-bit NormalFloat(NF4)
- 计算数据类型:16-bit BrainFloat(bf16)
-
双重量化:对量化常数也进行量化,进一步压缩
-
分页优化器:优化显存管理,处理显存峰值
量化过程
在 4-bit 量化中,每个权重由 4 个比特表示:
- 确定量化范围(例如 -1 到 1)
- 将范围分成 16 个区间,每个区间对应一个 4-bit 值
- 原始的 32 位浮点数值映射到最近的量化区间值
微调阶段
- 以 4-bit 格式加载模型,大幅减少静态显存占用
- 训练时将数值反量化到 bf16 进行计算
- 只微调 LoRA 权重,梯度通过量化权重反向传播
效果
- 33B 的 LLaMA 模型可以在 24 GB 显存的消费级显卡上训练
- 效果接近全参数微调
- 训练速度比原生 LoRA 略慢
3.3 Adapter Tuning(适配器调整)
核心思想
Adapter 的目标是在保留预训练模型原始参数不变的前提下,使模型适应新任务。方法是在模型的每个层或选定层之间插入小型神经网络模块——"适配器"(Adapter)。
核心结构
每个 Adapter 包含:
- Down-project 层:将高维特征映射到低维隐空间(如 d_model → r)
- 非线性激活:引入非线性能力
- Up-project 层:将低维特征映射回高维(如 r → d_model)
- 残差连接:最差情况退化为恒等映射
输入 x → Down-project (d→r) → 激活函数 → Up-project (r→d) → 加残差 → 输出
x ────────────────────────────────────→ +
关键步骤
- 以预训练模型(如 BERT、GPT)为基础
- 在模型的每个层或指定层中插入 Adapter
- 微调过程中,原预训练模型参数保持不变
- 只训练 Adapter 的参数,使其学习如何根据任务调整模型行为
示例
如果要将通用文本生成模型微调为生成专业金融报告:
- 在模型的关键层中加入 Adapter
- 微调过程中,仅有 Adapter 的参数根据金融领域数据更新
- 模型更好地适应金融报告的写作风格和术语
- 避免对整个模型架构进行大幅度调整
LoRA vs Adapter 对比
| 维度 | LoRA | Adapter |
|---|
| 修改位置 | 在权重矩阵中引入低秩矩阵 | 在各层添加小型神经网络模块 |
| 参数更新 | 低秩矩阵参与计算时调整原权重 | 只更新 Adapter 参数 |
| 推理延迟 | 可合并到原权重,无延迟 | 不可合并,有额外延迟 |
| 多任务切换 | 方便,切换低秩矩阵即可 | 需要加载不同的 Adapter |
3.4 Prefix Tuning(前缀调整)
核心思想
Prefix Tuning 提出了一种新策略:在预训练语言模型的输入序列前添加可训练、任务特定的前缀(Prefix),从而实现针对不同任务的微调。
这意味着可以为不同任务保存不同的前缀,而不是为每个任务保存一整套微调后的模型权重,节省大量存储空间和微调成本。
前缀的本质
前缀是一种连续可微的虚拟标记(Soft Prompt / Continuous Prompt),与离散的 Token 相比:
前缀可以是:
- 固定的:手动设计的静态提示
- 可训练的:模型在训练过程中学习的动态提示
优点
- 不需要调整模型所有权重
- 通过在输入中添加前缀调整模型行为
- 节省大量计算资源
- 单一模型能够适应多种不同任务
缺点
- 占用序列长度,减少可用输入空间
- 在每层都加 prompt 参数,改动较大
- 有额外计算开销
- 主要针对 NLG 任务设计
3.5 Prompt Tuning(提示调整)
核心思想
Prompt Tuning 是在预训练语言模型输入中引入可学习嵌入向量作为提示的微调方法。这些可训练的提示向量在训练过程中更新,以指导模型输出更适合特定任务的响应。
与前缀调整的区别
| 维度 | Prompt Tuning | Prefix Tuning |
|---|
| 添加位置 | 只在输入层添加 | 每一层都添加 |
| 可训练参数 | 更少 | 更多 |
| 目的 | 模仿自然语言提示形式 | 提供输入数据的上下文信息 |
| 适用任务 | 所有类型任务 | 主要针对 NLG 任务 |
训练示例
Prompt Tuning 示例:
输入序列: [Prompt1][Prompt2] "这部电影令人振奋。"
任务: 评价这部电影的情感倾向
答案: 模型预测情感倾向(如"积极")
提示: [Prompt1][Prompt2] 作为引导模型的内部提示
Prefix Tuning 示例:
输入序列: [Prefix1][Prefix2][Prefix3] "I want to watch a movie."
任务: 根据前缀生成后续文本
答案: 模型生成文本,如 "that is exciting and fun."
提示: 前缀本身提供上下文信息
特点
- 只在输入层加入 prompt tokens,结构简单
- 随着预训练模型参数量增加,效果逼近全参数微调
- 支持 prompt ensembling:一个批次训练同一任务的不同 prompt
- 在小模型上表现不佳
3.6 P-Tuning
核心思想
P-Tuning 针对 GPT-3 人工 prompt 模板对结果非常敏感的问题,提出使用可学习的连续 prompt。与 Prompt Tuning 的区别在于使用了一个Prompt Encoder来动态生成虚拟标记嵌入。
Prompt Encoder 结构
使用双向 LSTM + 两层 MLP 对 Prompt Embedding 编码:
- 建模伪 token 之间的依赖关系
- 提供更好的初始化
- 允许 prompt 伪 token 不连续插入输入序列中
Prompt Tuning vs P-Tuning
| 维度 | Prompt Tuning | P-Tuning |
|---|
| Prompt 生成 | 静态可训练嵌入 | LSTM 动态生成 |
| 灵活性 | 固定嵌入,相对简单 | 根据输入动态生成,更灵活 |
| 适用场景 | 多种任务表现良好 | 需要精细控制的复杂任务 |
| 计算复杂度 | 低 | 较高(额外 LSTM) |
P-Tuning 使用 LSTM 的优势
- 更好的适应性:LSTM 可以捕捉输入数据中的时间序列特征,理解复杂的顺序依赖
- 改进的上下文理解:擅长处理和理解长期依赖关系
- 参数共享和泛化:LSTM 参数可在多个任务间共享,提高泛化能力
3.7 P-Tuning v2
核心改进
P-Tuning v2 是对 P-Tuning 的进一步改进,主要解决了两个问题:
P-Tuning 存在的问题:
- 优化参数受限:由于模型输入文本长度固定(通常 512),提示长度不能过长
- 深层稳定性差:模型层数很深时,第一层输入的提示对后面层的影响难以预测
P-Tuning v2 的改进:
- 深层 Prompt:不仅在第一层插入连续提示,而是在多层都插入连续提示
- 层间独立:层与层之间的连续提示相互独立
- 可训练参数量增加:从 0.01% 增加到 0.1%~3%
效果
- 在复杂的自然语言理解(NLU)任务上表现更出色
- 对小型模型的提升更明显
- 拓展到 NER 等序列标注任务
4. 其他微调方法简介
4.1 PILL(Pluggable Instruction Language Learning)
PILL 是 PEFT 的一个特定实现,关注如何通过插入可训练的模块或插件来提升模型的任务适应性。这些插件被设计为与原始模型协同工作,提高处理特定任务的效率和效果。
4.2 SSF(Scaling & Shifting Your Features)
SSF 核心思想是对模型层的输出特征进行缩放(Scaling)和位移(Shifting):
- 通过调整特征的比例和偏移量优化模型性能
- 不需要调整或重新训练模型中的所有参数
- 节省计算资源的同时保持或提升模型性能
5. 七大方法综合对比
5.1 参数与效率对比
| 方法 | 可训练参数占比 | 推理延迟 | 能否合并消除延迟 | 存储需求 |
|---|
| 全参数微调 | 100% | 无 | - | 每个任务完整模型 |
| LoRA | 0.1%~1% | 可合并为无 | ✅ 可以 | 只有低秩矩阵,很小 |
| QLoRA | 0.1%~1% | 可合并为无 | ✅ 可以 | 量化模型 + 低秩矩阵 |
| Adapter | 0.5%~5% | 有额外延迟 | ❌ 不可合并 | 只有 Adapter,很小 |
| Prefix Tuning | 0.1%~3% | 占用序列长度 | ❌ 不可合并 | 只有 prefix,很小 |
| Prompt Tuning | <0.1% | 无额外计算 | ❌ 不可合并 | 只有 embedding,极小 |
| P-Tuning / v2 | 0.1%~3% | 有额外计算 | ❌ 不可合并 | 较小 |
5.2 效果对比
| 方法 | 效果排名 | 适用场景 |
|---|
| 全参数微调 | ⭐⭐⭐⭐⭐ | 数据量大、计算资源充足 |
| LoRA | ⭐⭐⭐⭐ | 通用首选,效果接近全参数 |
| QLoRA | ⭐⭐⭐⭐ | 显存极度受限 |
| AdaLoRA | ⭐⭐⭐⭐⭐ | 需要动态分配参数预算 |
| Adapter | ⭐⭐⭐ | 需要模块化解耦 |
| Prefix Tuning | ⭐⭐⭐ | NLG 任务为主 |
| Prompt Tuning | ⭐⭐ | 超大模型、简单任务 |
5.3 场景选择指南
按资源限制选择:
- 显存极度受限:Prompt Tuning > Prefix > QLoRA > LoRA > Adapter
- 追求推理速度:LoRA(可合并)> Prompt Tuning > Prefix > Adapter
- 效果优先:全参数 > AdaLoRA > LoRA > Adapter > Prompt Tuning
- 多任务部署:LoRA(可切换)> Adapter > 全参数
按任务类型选择:
- 通用 NLP 任务:LoRA / QLoRA
- NLG 生成任务:Prefix Tuning / LoRA
- 序列标注任务:P-Tuning v2 / LoRA
- 简单分类任务:Prompt Tuning
- 需要极致效果:全参数微调 / AdaLoRA
6. 微调策略总结
6.1 微调与迁移学习
微调实际上是迁移学习的一个实例。预训练模型(在大型通用数据集上训练)被用作特定任务的起点,使得即使是小数据集的任务,也可以实现高效的学习。
6.2 选择微调策略的关键因素
选择哪种微调方法取决于多个因素:
- 任务复杂性:复杂任务需要更多可训练参数
- 可用数据量:数据量大时可考虑全参数或 LoRA 较大 rank
- 计算资源:显存、GPU 数量决定可选方法范围
- 期望性能:效果优先还是效率优先
- 部署场景:是否需要多任务切换、推理延迟要求
6.3 微调与模型泛化能力
微调时需要注意保持模型的泛化能力:
- 过度微调可能导致模型对训练数据过拟合
- 解决方案:
- 控制学习率,使用较小的学习率
- 使用早停(Early Stopping)
- 混合通用数据防止灾难性遗忘
- 选择合适复杂度的微调方法
6.4 实践经验
- 从简单开始:先用 LoRA 快速验证,效果不够再升级
- 数据质量优先:数据质量的重要性远大于数量
- 学习率谨慎:微调学习率通常比预训练小 1~2 个数量级
- 监控泛化:保留验证集监控过拟合,不要只看训练 loss
- 组合策略:可以先增量预训练注入领域知识,再用 SFT 对齐指令格式
7. 面试常见问题
Q1: LoRA 为什么能工作?低秩假设成立吗?
A: LoRA 基于"大模型参数更新具有低内在秩"的观察。实践中,很小的秩(r=4~8)就能达到接近全参数微调的效果,说明低秩假设在大多数下游任务中成立。这可能是因为下游任务只需要对原模型知识做"方向性调整",不需要改变整个参数空间。
Q2: LoRA 和 Adapter 的主要区别是什么?
A:
- 修改方式:LoRA 在权重矩阵中引入低秩矩阵;Adapter 在各层添加小型神经网络模块
- 推理延迟:LoRA 可合并到原权重,无推理延迟;Adapter 不可合并,增加延迟
- 参数位置:LoRA 修改现有权重计算方式;Adapter 增加额外计算路径
Q3: Prefix Tuning 和 Prompt Tuning 有什么区别?
A:
- 添加位置:Prefix Tuning 在每一层都添加前缀;Prompt Tuning 只在输入层添加
- 参数数量:Prefix Tuning 可训练参数更多
- 适用任务:Prefix Tuning 主要针对 NLG;Prompt Tuning 更通用
Q4: 为什么 P-Tuning v2 要在每一层都加 prompt?
A: 浅层的 prompt 对深层预测影响有限。在每一层都加入可学习 prompt 能让提示信息直接影响每一层的预测,效果更好,尤其对小模型提升明显。
Q5: 显存受限时如何选择微调方法?
A:
- 24GB 以下消费级显卡:首选 QLoRA(4-bit 量化 + LoRA)
- 40GB~80GB 专业卡:LoRA 或全参数微调小模型(7B~13B)
- 多卡环境:可以考虑 DeepSpeed + 全参数微调
Q6: 如何缓解微调中的灾难性遗忘?
A:
- 混合通用数据(领域:通用 = 1:5 到 1:10)
- 使用较小的学习率
- 使用参数高效微调方法(LoRA、Adapter),冻结原模型参数
- 弹性权重巩固(EWC),对重要参数增加正则惩罚
Q7: 全参数微调和参数高效微调如何选择?
A:
- 选全参数微调:数据量大(10k+ 高质量数据)、计算资源充足、追求极致效果
- 选参数高效微调:资源有限、快速迭代、多任务部署、防止遗忘
- 工业界实践:大部分场景 LoRA 足够,效果接近全参数且部署灵活