LoRA为什么只对部分层微调?

1. 减少计算成本

LoRA 的目标之一是降低微调过程中的计算和存储开销。如果对整个模型的所有层进行微调,即便采用低秩矩阵分解,也会增加大量的额外参数,影响效率。因此,LoRA 选择只对关键层进行微调,比如 Transformer 模型中的自注意力层的权重矩阵(尤其是 Query 和 Key 投影矩阵)。这些层在模型的整体输出中具有显著影响,通过对它们进行微调,就可以有效调整模型的表现,而无需微调整个模型。

2. 模型的分层结构

大型语言模型(如 GPT 和 BERT)具有分层结构,不同层在模型的表达能力上有不同的贡献。实践表明,在 Transformer 模型的自注意力层中,尤其是 Query 和 Key 矩阵部分进行调整,能够对模型的上下文理解和信息提取产生较大影响,而这些是许多 NLP 任务的关键。因此,LoRA 针对这些部分进行微调可以最大化利用参数量的减少,同时保持对模型性能的提升。

大型语言模型的多层堆叠的分层结构,每一层在模型的表达能力上有不同的贡献。这些层往往可以解构为不同的功能模块,例如低层、中层和高层,各自承担不同的任务和信息处理功能。

  • 低层(底层):Transformer 模型的底层通常处理较为细粒度的词汇级别的特征和语法结构。它们侧重于捕捉词语之间的局部依赖关系,如短距离的词汇交互和句法信息。这些层帮助模型掌握基础的语言模式,但对于复杂的上下文理解贡献较小。
  • 中层:中间层更多地参与句子的语义理解和全局上下文的构建。这些层在建模词与词之间的长距离依赖关系上扮演关键角色,对上下文中的多义词的正确理解起着决定性作用。因此,中层在模型的语言理解和生成能力上具有较大的贡献,它们将句法信息转化为语义信息,是语言理解的核心部分。
  • 高层(顶层):高层更偏向于处理全局语义、逻辑推理和任务特定的信息。它们将下层提取的语义信息进一步汇总、融合,适用于分类、回答问题等高级任务。这些层更擅长为特定任务提供定制化的特征,因此在特定的下游任务中,模型的高层具有较大的适应性。

简而言之,底层负责捕捉局部特征,中层聚焦于全局语义理解,而高层则承担高级任务的信息处理。在这些层中,自注意力机制又扮演十分重要的角色,我们都知道q、k、v是注意力的三个核心,实践表明,q和k矩阵有更重要的影响。这是因为这些矩阵负责计算序列中各个位置的相似性,从而决定了哪些词语之间需要建立关联。微调 Query 和 Key 矩阵能够显著影响模型对上下文关系的捕捉能力,尤其在处理长距离依赖关系和复杂的语义交互时,这种微调尤为有效。

  • Query 矩阵:通过微调 Query 矩阵,模型可以更好地定位哪些输入词汇需要关注哪些上下文信息。它影响了模型如何提取与当前词相关的上下文信息,尤其在长文本的理解中,起到了至关重要的作用。
  • Key 矩阵:Key 矩阵则决定了哪些词汇提供了与上下文相关的重要信息。微调这个部分有助于模型更好地理解句子中的关键要素,尤其是对关键词的捕捉能力。

3. 避免过拟合和保持模型稳定性

如果对模型的所有层进行微调,可能会引入过多的可训练参数,导致过拟合问题。通过限制微调的范围,LoRA 能够在不显著改变模型原有能力的前提下,只对关键部分进行适应性调整,减少了在新任务上过拟合的风险。此外,冻结大部分模型参数还能保持原模型的稳定性,不会破坏预训练过程中学到的通用知识。

4. 低秩矩阵的适用性

LoRA 的核心技术是低秩矩阵分解,假设权重更新可以用低秩的结构表示。并不是所有的网络层都适合用这种方式来表达更新。例如,在前馈网络层(Feed-Forward Networks)中的权重更新可能需要更多自由度,低秩矩阵在这些层的表现可能不如在自注意力层有效。因此,LoRA 主要应用在适合低秩近似的部分层,确保性能与效率的平衡。

为什么前馈网络层不适合使用低秩分解?

在前馈网络层(Feed-Forward Networks,FFN)中,权重矩阵主要用于处理模型中的非线性特征变换,负责从输入中提取更加复杂和高维度的特征。这个过程往往需要较大的参数空间,意味着权重矩阵需要有较高的自由度来捕捉丰富的特征表示。因此,强行将这些矩阵进行低秩分解可能会限制模型的表达能力,导致性能下降。换句话说,前馈网络的权重更新往往需要全秩矩阵才能充分表达输入数据中的多样性,而低秩矩阵可能不足以捕捉所有的复杂模式。

要注意LoRA微调的前提假设是权重矩阵的更新可以近似为低秩的结构。由于像Query 和 Key 这样的矩阵主要用于计算词与词之间的相似性或注意力分数,这些相似性矩阵本质上往往具有低秩结构。在大多数语言任务中,很多词之间的关系是局部化的或存在冗余,因此可以通过低秩矩阵来近似表示。但是,对于其他层(如前馈层)而言,输入信息可能更加复杂和多样,低秩结构的假设并不总是成立,因此无法用低秩分解有效表示。

5. 参数共享与扩展

许多大型预训练模型中的层具有参数共享和重复结构,某些层的权重具有类似的功能和表达能力。微调部分层的权重往往能够带来全局性能的提升,无需重复地在每一层进行相同的操作。因此,LoRA 通过选择性微调关键层,达到了用更少参数实现全局效果的目标。

总结

综上所述,LoRA 通常只微调模型的部分层,原因在于这种方式既能有效减少计算成本,又能针对性地调整模型的关键层,最大化性能提升。此外,通过限制可训练参数的范围,LoRA 还能避免过拟合并保持模型的稳定性。因此,LoRA 的设计在效率和性能之间找到了一个平衡点。

### 自定义 LoRA 进行模型微调 在实现自定义 LoRA(低秩适应)以用于模型微调的过程中,主要关注于如何通过修改特定网络中的权重来达到高效微调的目的。对于预训练的 Stable Diffusion (SD) 模型而言,在不改变大部分原有参数的情况下仅需调整少量新增加或选定部分现有参数即可完成针对新任务的学习过程[^2]。 具体来说,为了创建并应用自定义 LoRA : #### 定义新的线性变换函数 可以基于 PyTorch 或其他框架编写一段代码片段用来构建具有特殊结构的全连接或其他类型的神经元间联系形式。这里展示了一个简单的例子——利用 Python 和 PyTorch 实现带有 LoRA 特性的 Linear Layer 类: ```python import torch.nn as nn from typing import Tuple, Optional class LoraLinear(nn.Module): """A linear layer with Low-Rank Adaptation.""" def __init__(self, in_features: int, out_features: int, rank: int = 4, alpha: float = 0.1): super().__init__() self.linear = nn.Linear(in_features, out_features) self.lora_A = nn.Parameter(torch.randn(rank, in_features)) self.lora_B = nn.Parameter(torch.zeros(out_features, rank)) self.alpha = alpha def forward(self, input_tensor: torch.Tensor) -> torch.Tensor: base_output = self.linear(input_tensor) lora_effect = F.linear(F.linear(input_tensor, self.lora_A), self.lora_B.t()) adjusted_output = base_output + self.alpha * lora_effect return adjusted_output ``` 此 `LoraLinear` 类继承自 `nn.Module`, 并实现了两个额外可学习矩阵 A 和 B 来表示低维空间内的变化量;当输入张量经过标准线性映射后再乘以此增量即完成了对原始输出特征向量的有效调节。 #### 替换原 SD 模型指定位置上的模块实例 接下来要的就是遍历整个网络架构图谱找到那些希望被替换掉的标准组件,并将其替换成上述定制版本的对象。这一步骤通常涉及到递归访问子节点以及判断当前处理对象是否满足条件等操作逻辑。 最后值得注意的是,在实际项目开发过程中还需要考虑诸如保存/加载优化器状态字典、冻结某些不需要更新梯度计算的部分等问题,这些都属于较为细节化的技术要点。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值