高效微调算法 (Parameter-Efficient Fine-tuning, PEFT) 详解

引言

随着预训练语言模型 (Pre-trained Language Models, PLMs) 规模的持续膨胀,全参数微调 (Full Fine-tuning) 模式的局限性日益凸显。 全参数微调在下游任务上取得了显著的性能提升,但其高昂的计算和存储成本 ,以及为每个下游任务维护完整模型副本 的模式,在大规模应用场景中变得难以承受。 高效微调算法 (Parameter-Efficient Fine-tuning, PEFT) 应运而生,旨在以极低的参数调整代价,实现媲美全参数微调的性能。 本章将深入剖析 PEFT 算法的核心原理、技术细节及其应用策略。

1.全参数微调 (Full Fine-tuning) 的局限性与 PEFT 的优势

全参数微调 (Full Fine-tuning) 是微调 PLMs 的传统方法。 它在下游任务训练过程中,更新预训练模型的所有参数,以使模型适应特定任务的需求。 全参数微调在诸多 NLP 任务上取得了卓越的性能, 但其固有的局限性限制了其在大规模应用场景中的部署:

全参数微调的局限性:

  1. 参数量庞大: 全参数微调需要更新 PLMs 的所有参数, 对于参数规模巨大的模型 (例如,数十亿、千亿参数), 微调过程需要消耗大量的计算资源 (GPU 算力) 和时间。

  2. 存储成本高昂: 全参数微调为每个下游任务维护一个完整模型副本, 当下游任务数量增多时, 存储成本线性增长, 难以 масштабироваться.

  3. 灾难性遗忘 (Catastrophic Forgetting): 全参数微调容易导致灾难性遗忘, 即模型在适应新任务的同时, 会遗忘在预训练阶段学习到的通用知识, 尤其是在下游任务数据量较小的情况下。

PEFT 的优势:

高效微调算法 (PEFT) 旨在克服全参数微调的局限性, 其核心优势在于:

  1. 参数效率 (Parameter Efficiency): PEFT 算法仅微调少量 (甚至极少量) 模型参数 , 大幅降低了计算和存储成本。 例如, Adapter Tuning, Prefix-Tuning, Prompt-Tuning, LoRA 等算法, 微调参数量通常只占原始模型参数量的 0.01% - 5% 左右。

  2. 存储效率 (Storage Efficiency): PEFT 算法无需为每个下游任务维护完整模型副本。 通常情况下, 只需要存储少量的微调参数 (例如,Adapter 模块参数,Prefix 参数,LoRA 适配器参数), 原始预训练模型参数保持冻结。 这极大地降低了存储成本, 更易于大规模部署。

  3. 避免灾难性遗忘 (Mitigating Catastrophic Forgetting): 由于 PEFT 算法冻结了大部分预训练模型参数, 模型能够更好地保留预训练阶段学习到的通用知识, 从而有效缓解灾难性遗忘问题。

  4. 即插即用 (Plug-and-Play): PEFT 算法通常以模块化 的方式集成到预训练模型中, 例如, Adapter 模块可以方便地插入到 Transformer 模型的每一层。 微调后的 PEFT 模块可以即插即用, 方便模型部署和迁移。

2. Adapter Tuning 算法详解

Adapter Tuning 是一种经典且有效的 PEFT 算法。 其核心思想是在预训练模型中插入少量新增的 Adapter 模块 , 并在微调阶段只训练这些 Adapter 模块的参数 , 而冻结原始预训练模型的参数

算法详解:

  1. Adapter 模块设计: Adapter 模块通常采用瓶颈结构 (Bottleneck Structure) , 包含一个 Down-Projection 层 ,一个 非线性激活层 ,和一个 Up-Projection 层 。 瓶颈结构可以有效地降低参数量 , 同时捕捉任务相关的特征。 常见的 Adapter 模块结构如下:

    复制代码
    class Adapter(nn.Module):
        def __init__(self, config):
            super().__init__()
            self.down_proj = nn.Linear(config.hidden_size, config.adapter_size)
            self.activation = nn.ReLU() # 或其他非线性激活函数
            self.up_proj = nn.Linear(config.adapter_size, config.hidden_size)
            self.adapter_norm = nn.LayerNorm(config.hidden_size)
    
        def forward(self, hidden_states):
            residual = hidden_states
            down = self.down_proj(hidden_states)
            up = self.up_proj(self.activation(down))
            output = self.adapter_norm(up + residual) # 残差连接
            return output

    其中,config.adapter_size 为 Adapter 模块的瓶颈维度,通常远小于 config.hidden_size (例如,adapter_size = 64, hidden_size = 768)。 Adapter 模块还通常包含 Layer Normalization残差连接 (Residual Connection), 以提高训练稳定性和性能。

  2. Adapter 模块插入: 将 Adapter 模块插入到预训练模型 Transformer 结构的关键位置 , 例如, Transformer 层的 Feed-Forward Network (FFN) 之后Attention 层之后 。 通常情况下, 会在 Transformer 模型的每一层都插入 Adapter 模块。

  3. 微调训练: 在下游任务微调阶段, 冻结原始预训练模型的所有参数只训练新插入的 Adapter 模块的参数。 训练目标为最小化下游任务的损失函数。

Adapter Tuning 的优点:

  • 参数高效: Adapter 模块参数量远小于原始模型参数量, 微调参数量占比极低。
  • 结构简单,易于实现: Adapter 模块结构简单, 易于集成到现有预训练模型中。
  • 即插即用: 微调后的 Adapter 模块可以方便地插入和移除, 模型部署和迁移灵活。
  • 性能可观: 在许多下游任务上, Adapter Tuning 能够取得接近全参数微调的性能。

Adapter Tuning 的局限性:

  • 性能上限: 相比全参数微调, Adapter Tuning 的性能可能存在一定的差距, 尤其是在需要模型深度适应下游任务的情况下。
  • 超参数敏感: Adapter 模块的结构和超参数 (例如,adapter_size) 对性能有一定影响, 需要进行调优。

3. Prefix-Tuning 与 Prompt-Tuning 算法深度解析

Prefix-Tuning 和 Prompt-Tuning 是一类基于 Prompt 的高效微调算法。 其核心思想是固定预训练模型参数只优化少量与 Prompt 相关的参数 , 通过引导模型"理解"下游任务, 实现高效微调。

3.1 Prefix-Tuning 算法

Prefix-Tuning 算法通过在输入文本的前缀 (Prefix) 部分添加少量可训练的参数, 引导预训练模型生成期望的输出。

算法详解:

  1. Prefix 向量设计: Prefix-Tuning 引入Prefix 向量 , 作为输入文本的前缀。 Prefix 向量是一组可训练的参数 , 其维度通常较小。 例如, 对于 Transformer 模型, Prefix 向量可以是一组 Embedding 向量hidden states

  2. Prefix 向量注入: 将 Prefix 向量注入到 Transformer 模型的每一层 。 注入方式可以是拼接 (Concatenation)加法 (Addition) 等。 例如, 可以将 Prefix 向量拼接在每一层 Transformer 块的 Key (K)Value (V) 矩阵之前。

  3. 微调训练: 在下游任务微调阶段, 冻结原始预训练模型的所有参数只训练新引入的 Prefix 向量。 训练目标为最大化下游任务的生成概率。

Prefix-Tuning 的优点:

  • 参数极度高效: Prefix 向量参数量极小, 微调参数量占比几乎可以忽略不计。
  • 生成任务友好: Prefix-Tuning 天然适用于文本生成等任务, 通过 Prefix 引导模型生成特定风格或内容的文本。
  • 性能可观: 在生成任务上, Prefix-Tuning 能够取得接近全参数微调的性能。

Prefix-Tuning 的局限性:

  • 上下文长度限制: Prefix 向量会占用输入文本的上下文长度, 限制了模型能够处理的最大输入长度。
  • 任务类型限制: Prefix-Tuning 更适用于生成任务, 在判别任务上的效果可能不如 Adapter Tuning 或 LoRA 等算法。
  • 调优难度: Prefix 向量的长度和注入方式等超参数对性能有一定影响, 需要进行调优。

3.2 Prompt-Tuning 算法

Prompt-Tuning 算法进一步简化了 Prefix-Tuning 的思想。 它直接将可训练的 Prompt 向量 拼接在输入文本之前, 引导预训练模型完成下游任务。

算法详解:

  1. Prompt 向量设计: Prompt-Tuning 引入 Prompt 向量 , 作为输入文本的前缀。 Prompt 向量也是一组可训练的参数 , 通常是 Embedding 向量。 Prompt 向量的长度通常较短, 例如, 10-100 个 token。

  2. Prompt 向量拼接: 将 Prompt 向量直接拼接在输入文本之前, 形成新的输入序列。 例如, 对于文本分类任务, 可以将 Prompt 向量拼接在输入文本之前, 引导模型预测文本的类别。

  3. 微调训练: 在下游任务微调阶段, 冻结原始预训练模型的所有参数只训练新引入的 Prompt 向量。 训练目标为最小化下游任务的损失函数。

Prompt-Tuning 的优点:

  • 极简高效: Prompt-Tuning 算法极其简单, 实现和使用都非常方便。 微调参数量极小。
  • 易于理解和解释: Prompt 本身具有一定的语义信息, Prompt-Tuning 的机制更易于理解和解释。
  • 快速实验: Prompt-Tuning 训练速度快, 方便快速实验和迭代。

Prompt-Tuning 的局限性:

  • 性能瓶颈: 相比 Prefix-Tuning 和其他更复杂的 PEFT 算法, Prompt-Tuning 的性能可能存在一定的差距, 尤其是在需要模型深度适应下游任务的情况下。 Hard Prompt 的调优难度也较高。
  • Prompt 设计敏感: Prompt 的设计对性能影响较大, 需要进行仔细的 Prompt Engineering连续型 Prompt (Continuous Prompt) 虽然缓解了 Prompt Engineering 的难度, 但可解释性较差。

4 LoRA (Low-Rank Adaptation) 低秩适配算法

LoRA (Low-Rank Adaptation) 是一种基于低秩分解 (Low-Rank Decomposition) 的高效微调算法。 其核心思想是冻结预训练模型权重只训练少量低秩适配器 (Low-Rank Adapters) , 通过模拟权重更新的方式, 实现模型微调。

算法详解:

  1. 低秩分解: LoRA 假设模型权重矩阵的更新 DeltaW 具有低秩特性 。 即可以将 DeltaW 分解为两个低秩矩阵的乘积: DeltaW=BA, 其中 BinmathbbRdtimesr, AinmathbbRrtimesk, 秩 rllmin(d,k). r 称为 LoRA 秩 (LoRA Rank), 通常设置为较小的值 (例如, r = 8, 16)。

  2. 适配器注入: 对于预训练模型中的权重矩阵 (例如, Transformer 模型的 Attention 层的权重矩阵 W_q,W_k,W_v,W_o 和 FFN 层的权重矩阵), 并行添加 低秩适配器 。 适配器由两个线性层组成: 一个 Down-Projection 层 A 和一个 Up-Projection 层 B。

  3. 前向计算: 在前向计算时, 原始权重矩阵 W_0 和低秩适配器矩阵 BA 的输出并行计算 , 然后求和作为最终输出: h=W_0x+BAx=W_0x+DeltaWx.

  4. 微调训练: 在下游任务微调阶段, 冻结原始预训练模型权重 W_0只训练低秩适配器矩阵 B 和 A。 训练目标为最小化下游任务的损失函数。

LoRA 的优点:

  • 参数极其高效: 低秩适配器参数量远小于原始模型参数量, 微调参数量占比极低。
  • 推理零延迟: 在推理阶段, 可以将低秩适配器矩阵 BA 与原始权重矩阵 W_0 合并 , 得到新的权重矩阵 W=W_0+BA. 因此, LoRA 在推理时不会引入额外的计算延迟
  • 实现简单: LoRA 实现相对简单, 易于集成到现有预训练模型中。
  • 性能优秀: LoRA 在各种下游任务上, 通常能够取得接近全参数微调的性能, 尤其是在大规模模型上。

LoRA 的局限性:

  • 秩 r 调优: LoRA 秩 r 的选择对性能有一定影响, 需要进行调优。 秩 r 越大, 模型容量越大, 性能可能越好, 但微调参数量也会增加。
  • 并非所有权重矩阵都适合 LoRA: LoRA 主要应用于 Transformer 模型中的 Attention 权重矩阵FFN 权重矩阵。 对于其他类型的权重矩阵, LoRA 的有效性可能需要进一步验证。

5 BitFit 与 IA3 等其他 PEFT 算法简介

除了 Adapter Tuning, Prefix-Tuning, Prompt-Tuning 和 LoRA 之外, 还有一些其他的 PEFT 算法, 例如 BitFit 和 IA3 (Infused Adapter by Inhibiting and Amplifying Activations)。

5.1 BitFit 算法

BitFit 算法是一种极简 的 PEFT 算法。 它只微调预训练模型中的 Bias 项参数 , 而冻结所有权重矩阵参数

算法核心思想:

  • Bias 项微调: 只微调模型中 Bias 项 (偏置项) 的参数, 例如, 线性层和 Layer Normalization 层的 Bias 项。

  • 权重冻结: 冻结所有权重矩阵参数

BitFit 的优点:

  • 参数极度高效: Bias 项参数量远小于权重矩阵参数量, 微调参数量占比极低。
  • 实现极其简单: BitFit 算法实现极其简单, 只需在训练时设置只更新 Bias 项参数即可。
  • 出人意料的有效性: 实验表明, BitFit 在某些任务上, 能够取得 surprisingly good 的性能, 甚至接近全参数微调。

BitFit 的局限性:

  • 性能上限较低: 由于只微调 Bias 项参数, 模型容量受限, 性能上限相对较低, 可能无法充分适应复杂的下游任务。
  • 任务依赖性: BitFit 的性能可能对下游任务的类型和数据量比较敏感。

5.2 IA3 (Infused Adapter by Inhibiting and Amplifying Activations) 算法

IA3 (Infused Adapter by Inhibiting and Amplifying Activations) 算法 通过在 Transformer 模型的每一层注入少量可训练的缩放向量 (Scaling Vectors) , 并冻结原始预训练模型参数, 实现高效微调。

算法核心思想:

  • 缩放向量注入: 在 Transformer 模型的 Attention 层FFN 层关键位置 , 注入可训练的缩放向量 。 例如, 可以注入到 Attention 输出之后FFN 输出之后

  • 激活值缩放: 使用缩放向量对激活值进行逐元素缩放 (Element-wise Scaling)。 缩放向量控制了不同特征通道的激活强度, 从而实现模型微调。

  • 权重冻结: 冻结原始预训练模型的所有参数只训练缩放向量

IA3 的优点:

  • 参数高效: 缩放向量参数量极小, 微调参数量占比极低。
  • 性能优秀: IA3 在各种下游任务上, 能够取得接近全参数微调的性能。
  • 可解释性: 缩放向量可以解释为对不同特征通道的重要性加权, 具有一定的可解释性。

IA3 的局限性:

  • 实现相对复杂: IA3 的实现相对 Adapter Tuning 和 LoRA 略微复杂, 需要仔细设计缩放向量的注入位置和方式。
  • 超参数调优: 缩放向量的维度和注入位置等超参数对性能有一定影响, 需要进行调优。

6 PEFT 算法性能对比与选择策略

不同的 PEFT 算法各有优缺点, 适用于不同的场景和任务。 下表对几种常见的 PEFT 算法进行了性能对比 (仅供参考,实际性能可能因模型、任务和超参数而异):

|------------------|-----------|-----------------------|----------|----------|-------------------------|
| 算法名称 | 微调参数量 | 性能水平 (相对 Full FT) | 实现难度 | 推理延迟 | 适用场景 |
| Full Fine-tuning | 高 | 基线 (100%) | 简单 | 无 | 所有任务,追求极致性能 |
| Adapter Tuning | 中 | 较高 (95% - 99%) | 简单 | 轻微 | 各种任务,追求性能与效率平衡 |
| Prefix-Tuning | 极低 | 较高 (90% - 98%) | 简单 | 无 | 生成任务,参数效率优先 |
| Prompt-Tuning | 极低 | 中等 (85% - 95%) | 极简 | 无 | 快速实验,轻量级任务 |
| LoRA | 极低 | 较高 (95% - 99%) | 简单 | 无 | 各种任务,追求性能与效率的极致平衡,推理零延迟 |
| BitFit | 极低 | 中等 (80% - 90%) | 极简 | 无 | 轻量级任务,参数效率极致 |
| IA3 | 极低 | 较高 (95% - 99%) | 较复杂 | 轻微 | 各种任务,追求高性能 |

PEFT 算法选择策略:

  • 追求极致性能: 如果对性能要求极高, 且计算资源充足, Full Fine-tuning 仍然是首选。

  • 追求性能与效率平衡: Adapter Tuning , LoRA , IA3 是更均衡的选择, 能够在保证较高性能的同时, 大幅降低计算和存储成本。 LoRA 在推理延迟方面更具优势

  • 参数效率优先,生成任务: Prefix-Tuning 是参数效率最高的算法之一, 尤其适用于生成任务, 例如文本摘要、机器翻译等。

  • 极简轻量级微调: Prompt-TuningBitFit 适用于快速实验轻量级任务, 例如, 快速验证模型效果, 或在资源受限的设备上进行微调。

在实际应用中, 需要根据具体的任务需求、资源限制和性能指标, 选择合适的 PEFT 算法。 也可以尝试组合使用多种 PEFT 算法, 例如, Adapter Tuning + LoRA, 以进一步提升性能或效率。

总结

本章深入详解了高效微调算法 (PEFT), 重点介绍了 Adapter Tuning, Prefix-Tuning, Prompt-Tuning, LoRA, BitFit 和 IA3 等经典算法, 并对比分析了不同 PEFT 算法的性能特点和适用场景。 PEFT 算法为大规模预训练模型的低成本、高效应用提供了关键技术支撑, 是未来 NLP 领域的重要发展方向。 下一章, 我们将探讨预训练模型在实际 NLP 任务中的应用案例, 深入了解预训练模型如何赋能各种 NLP 应用场景。

欢迎关注我的微信公众号 智语Bot,与我互动交流,共同学习进步!

参考资料 (请根据实际情况补充更偏向技术文档或论文的链接)

相关推荐
赴33511 小时前
opencv 银行卡号识别案例
人工智能·opencv·计算机视觉·银行卡号识别
后端小肥肠12 小时前
公众号卡在 vs 漫画赛道?Coze 一键出稿:输入标题就生成,小白也能冲 10w+
人工智能·aigc·coze
微盛AI企微管家12 小时前
企业微信AI功能升级:选对企业微信服务商协助四大AI场景落地
大数据·人工智能·企业微信
eqwaak012 小时前
科技信息差(9.10)
网络·人工智能·分布式·ar·智能硬件
虫无涯12 小时前
如何使用LangChain的Python库结合DeepSeek进行多轮次对话?
人工智能
mortimer12 小时前
精通BAT脚本:为你的Windows AI项目打造“一键启动”的完美体验
人工智能
Baihai_IDP12 小时前
MCP 是为开发者设计的工具,而非为 LLM 而设
人工智能·面试·llm
胡乱编胡乱赢12 小时前
在pycharm终端安装torch
ide·深度学习·pycharm·安装torch
IT_陈寒12 小时前
SpringBoot性能翻倍的7个隐藏配置,90%开发者从不知道!
前端·人工智能·后端
深耕AI12 小时前
PyTorch自定义模型结构详解:从基础到高级实践
人工智能·pytorch·python