引言
随着预训练语言模型 (Pre-trained Language Models, PLMs) 规模的持续膨胀,全参数微调 (Full Fine-tuning) 模式的局限性日益凸显。 全参数微调在下游任务上取得了显著的性能提升,但其高昂的计算和存储成本,以及为每个下游任务维护完整模型副本的模式,在大规模应用场景中变得难以承受。 高效微调算法 (Parameter-Efficient Fine-tuning, PEFT) 应运而生,旨在以极低的参数调整代价,实现媲美全参数微调的性能。 本章将深入剖析 PEFT 算法的核心原理、技术细节及其应用策略。
1.全参数微调 (Full Fine-tuning) 的局限性与 PEFT 的优势
全参数微调 (Full Fine-tuning) 是微调 PLMs 的传统方法。 它在下游任务训练过程中,更新预训练模型的所有参数,以使模型适应特定任务的需求。 全参数微调在诸多 NLP 任务上取得了卓越的性能, 但其固有的局限性限制了其在大规模应用场景中的部署:
全参数微调的局限性:
-
参数量庞大: 全参数微调需要更新 PLMs 的所有参数, 对于参数规模巨大的模型 (例如,数十亿、千亿参数), 微调过程需要消耗大量的计算资源 (GPU 算力) 和时间。
-
存储成本高昂: 全参数微调为每个下游任务维护一个完整模型副本, 当下游任务数量增多时, 存储成本线性增长, 难以 масштабироваться.
-
灾难性遗忘 (Catastrophic Forgetting): 全参数微调容易导致灾难性遗忘, 即模型在适应新任务的同时, 会遗忘在预训练阶段学习到的通用知识, 尤其是在下游任务数据量较小的情况下。
PEFT 的优势:
高效微调算法 (PEFT) 旨在克服全参数微调的局限性, 其核心优势在于:
-
参数效率 (Parameter Efficiency): PEFT 算法仅微调少量 (甚至极少量) 模型参数, 大幅降低了计算和存储成本。 例如, Adapter Tuning, Prefix-Tuning, Prompt-Tuning, LoRA 等算法, 微调参数量通常只占原始模型参数量的 0.01% - 5% 左右。
-
存储效率 (Storage Efficiency): PEFT 算法无需为每个下游任务维护完整模型副本。 通常情况下, 只需要存储少量的微调参数 (例如,Adapter 模块参数,Prefix 参数,LoRA 适配器参数), 原始预训练模型参数保持冻结。 这极大地降低了存储成本, 更易于大规模部署。
-
避免灾难性遗忘 (Mitigating Catastrophic Forgetting): 由于 PEFT 算法冻结了大部分预训练模型参数, 模型能够更好地保留预训练阶段学习到的通用知识, 从而有效缓解灾难性遗忘问题。
-
即插即用 (Plug-and-Play): PEFT 算法通常以模块化的方式集成到预训练模型中, 例如, Adapter 模块可以方便地插入到 Transformer 模型的每一层。 微调后的 PEFT 模块可以即插即用, 方便模型部署和迁移。
2. Adapter Tuning 算法详解
Adapter Tuning 是一种经典且有效的 PEFT 算法。 其核心思想是在预训练模型中插入少量新增的 Adapter 模块, 并在微调阶段只训练这些 Adapter 模块的参数, 而冻结原始预训练模型的参数。
算法详解:
-
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), 以提高训练稳定性和性能。 -
Adapter 模块插入: 将 Adapter 模块插入到预训练模型 Transformer 结构的关键位置, 例如, Transformer 层的 Feed-Forward Network (FFN) 之后 或 Attention 层之后。 通常情况下, 会在 Transformer 模型的每一层都插入 Adapter 模块。
-
微调训练: 在下游任务微调阶段, 冻结原始预训练模型的所有参数, 只训练新插入的 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) 部分添加少量可训练的参数, 引导预训练模型生成期望的输出。
算法详解:
-
Prefix 向量设计: Prefix-Tuning 引入Prefix 向量, 作为输入文本的前缀。 Prefix 向量是一组可训练的参数, 其维度通常较小。 例如, 对于 Transformer 模型, Prefix 向量可以是一组 Embedding 向量 或 hidden states。
-
Prefix 向量注入: 将 Prefix 向量注入到 Transformer 模型的每一层。 注入方式可以是拼接 (Concatenation) 或 加法 (Addition) 等。 例如, 可以将 Prefix 向量拼接在每一层 Transformer 块的 Key (K) 和 Value (V) 矩阵之前。
-
微调训练: 在下游任务微调阶段, 冻结原始预训练模型的所有参数, 只训练新引入的 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 向量 拼接在输入文本之前, 引导预训练模型完成下游任务。
算法详解:
-
Prompt 向量设计: Prompt-Tuning 引入 Prompt 向量, 作为输入文本的前缀。 Prompt 向量也是一组可训练的参数, 通常是 Embedding 向量。 Prompt 向量的长度通常较短, 例如, 10-100 个 token。
-
Prompt 向量拼接: 将 Prompt 向量直接拼接在输入文本之前, 形成新的输入序列。 例如, 对于文本分类任务, 可以将 Prompt 向量拼接在输入文本之前, 引导模型预测文本的类别。
-
微调训练: 在下游任务微调阶段, 冻结原始预训练模型的所有参数, 只训练新引入的 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), 通过模拟权重更新的方式, 实现模型微调。
算法详解:
-
低秩分解: LoRA 假设模型权重矩阵的更新 DeltaW 具有低秩特性。 即可以将 DeltaW 分解为两个低秩矩阵的乘积: DeltaW=BA, 其中 BinmathbbRdtimesr, AinmathbbRrtimesk, 秩 rllmin(d,k). r 称为 LoRA 秩 (LoRA Rank), 通常设置为较小的值 (例如, r = 8, 16)。
-
适配器注入: 对于预训练模型中的权重矩阵 (例如, Transformer 模型的 Attention 层的权重矩阵 W_q,W_k,W_v,W_o 和 FFN 层的权重矩阵), 并行添加 低秩适配器。 适配器由两个线性层组成: 一个 Down-Projection 层 A 和一个 Up-Projection 层 B。
-
前向计算: 在前向计算时, 原始权重矩阵 W_0 和低秩适配器矩阵 BA 的输出并行计算, 然后求和作为最终输出: h=W_0x+BAx=W_0x+DeltaWx.
-
微调训练: 在下游任务微调阶段, 冻结原始预训练模型权重 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-Tuning 和 BitFit 适用于快速实验和轻量级任务, 例如, 快速验证模型效果, 或在资源受限的设备上进行微调。
在实际应用中, 需要根据具体的任务需求、资源限制和性能指标, 选择合适的 PEFT 算法。 也可以尝试组合使用多种 PEFT 算法, 例如, Adapter Tuning + LoRA, 以进一步提升性能或效率。
总结
本章深入详解了高效微调算法 (PEFT), 重点介绍了 Adapter Tuning, Prefix-Tuning, Prompt-Tuning, LoRA, BitFit 和 IA3 等经典算法, 并对比分析了不同 PEFT 算法的性能特点和适用场景。 PEFT 算法为大规模预训练模型的低成本、高效应用提供了关键技术支撑, 是未来 NLP 领域的重要发展方向。 下一章, 我们将探讨预训练模型在实际 NLP 任务中的应用案例, 深入了解预训练模型如何赋能各种 NLP 应用场景。
欢迎关注我的微信公众号 智语Bot,与我互动交流,共同学习进步!
参考资料 (请根据实际情况补充更偏向技术文档或论文的链接)
-
Parameter-Efficient Transfer Learning for NLP:https://arxiv.org/abs/1902.00751(Adapter Tuning)
-
Prefix-Tuning: Optimizing Continuous Prompts for Generation:https://arxiv.org/abs/2101.00190(Prefix-Tuning)
-
GPT Understands, Too:https://arxiv.org/abs/2103.10385(Prompt-Tuning)
-
LoRA: Low-Rank Adaptation of Large Language Models:https://arxiv.org/abs/2106.09685(LoRA)
-
BitFit: Simple Parameter-Efficient Fine-tuning for Transformer-based Masked Language-models:https://arxiv.org/abs/2106.10199(BitFit)
-
IA^3: Infused Adapters by Inhibiting and Amplifying Activations:https://arxiv.org/abs/2205.05638(IA3)
-
The Power Efficient