浅谈LoRA,理清跟增量微调的区别

前言

曾在游戏世界挥洒创意,也曾在前端和后端的浪潮间穿梭,如今,而立的我仰望AI的璀璨星空,心潮澎湃,步履不停!愿你我皆乘风破浪,逐梦星辰!

核心

其实,LoRA 核心就一句话:“用局部微调的方法去逼近全量微调的效果。”


📌 如何理解?

  1. 全量微调(Full Fine-tuning)

    • 需要更新模型所有参数,计算量和存储开销大。
    • 如果模型有 100 亿个参数,就要微调 100 亿个参数,需要大量 GPU 显存
  2. LoRA(Low-Rank Adaptation)

    • 冻结原始模型权重,不直接修改参数。
    • 只在部分层(如 Attention 层)插入低秩矩阵(A, B)用较小的参数量去拟合完整的微调效果
    • 训练时 只更新 A, B,最终计算: W=W0+ABW = W_0 + AB
    • 参数量大幅减少,但仍然能近似达到全量微调的效果。

📌 直观理解:

  • 全量微调 就像 重新装修一整个房子(耗时、耗钱)。
  • LoRA 只是在关键点 增加可移动家具改变风格但不动房子本身(快速、低成本)。

📌 直观数学示例

假设原始模型参数矩阵:

W0∈R ^ (4×6)

如果直接全参数微调,我们需要更新 4 x 6 = 24 个参数。


✅ 全量微调

W=W0+ΔW

其中:

ΔW∈R8×10

需要训练 80 个参数,计算量大。


✅ LoRA 微调

ΔW=AB

其中:

  • A∈R8 × 2(8×2 低秩矩阵
  • B∈R2 x 102×10 低秩矩阵

参数总量:

(8×2)+(2×10)=16+20=36

相比全量微调的 80 个参数,参数量大幅减少,但 AxB 仍然可以逼近 W0

📌 结果

  • 训练的参数量减少,但最终效果接近全量微调。
  • 计算复杂度降低,适合大模型(GPT, LLaMA)。

📌 LoRA 微调 vs. 增量微调(Incremental Fine-tuning)

LoRA(Low-Rank Adaptation)和增量微调(Incremental Fine-tuning)都属于高效微调方法,但它们在 参数更新方式、存储方式、计算开销 方面有显著不同。


1️⃣ 主要区别

对比项LoRA(局部低秩微调)增量微调(Incremental Fine-tuning)
原始权重冻结,不修改 $W_0$复制一份 $W_0$,修改部分参数
训练参数仅训练低秩矩阵 $A, B$,计算量低训练部分或全部参数,计算量大
计算复杂度$O(d_{out} \times r + r \times d_{in})$(远小于全参数)$O(d_{out} \times d_{in})$(部分更新)
存储开销只存储 $A, B$,存储开销小存储新的 $W'$(部分更新)
推理方式$W = W_0 + AB$(可合并)切换到新模型 $W'$ 进行推理
适用场景适用于大模型(如 GPT、LLaMA),低显存设备适用于长期训练,持续优化模型

📌 总结

  • LoRA仅用两个小矩阵 $A, B$ 调整 $W_0$,不修改原始权重,节省计算量
  • 增量微调修改部分参数(如 Adapter 层),但比 LoRA 占用更多计算资源

2️⃣ LoRA 微调原理

LoRA 采用:

W=W0+ΔWW = W_0 + \Delta W

其中:

ΔW=AB\Delta W = AB

  • $A$(低秩矩阵,$d_{out} \times r$)
  • $B$(低秩矩阵,$r \times d_{in}$)
  • LoRA 仅训练 $A, B$,不修改 $W_0$,所以存储开销小。

3️⃣ 增量微调(Incremental Fine-tuning)原理

增量微调的策略通常有:

  1. Adapter 层:在原始模型 $W_0$ 之外添加新的参数层: W′=Adapter(W0)W' = \text{Adapter}(W_0)
  2. 部分参数更新:只训练Transformer 某些层的参数
    for param in model.encoder.layer[-2:].parameters():
        param.requires_grad = True  # 仅微调最后两层
  3. 长期训练模式:支持多个阶段训练,每个阶段都增量更新参数

4️⃣ 计算复杂度对比

(1) LoRA

如果原始 Transformer 权重矩阵为:

W0∈Rd{out}×d{in}

LoRA 只需训练:

A∈Rd{out}×r, B∈Rr×d{in} 

计算复杂度:

O(d{out}×r+r×d{in}), 显存占用大幅减少。


(2) 增量微调

假设只微调最后 N 层 Transformer,参数量:

O(N×d{out}×d{in})

  • 计算量比 LoRA 大,但比全参数微调(Fine-tuning)小。

5️⃣ 代码对比

(1) LoRA 代码
from peft import LoraConfig, get_peft_model
from transformers import AutoModelForCausalLM

model_name = "facebook/opt-1.3b"
model = AutoModelForCausalLM.from_pretrained(model_name)

lora_config = LoraConfig(
    r=8,  # 低秩参数
    lora_alpha=32,
    target_modules=["q_proj", "v_proj"]
)

model = get_peft_model(model, lora_config)
  • 只训练 q_proj, v_proj 层的 LoRA 矩阵
  • 不修改原始 $W_0$,只增加 $A, B$ 训练参数

(2) 增量微调代码
from transformers import AutoModelForCausalLM

model_name = "facebook/opt-1.3b"
model = AutoModelForCausalLM.from_pretrained(model_name)

# 仅微调最后两层 Transformer
for param in model.transformer.h[-2:].parameters():
    param.requires_grad = True
  • 仅更新最后两层 Transformer 权重,减少计算量
  • 比 LoRA 存储开销大

6️⃣ 适用场景

场景LoRA 微调增量微调
大语言模型(GPT-3, LLaMA)适合(低计算量)❌ 计算太大
持续优化的 AI 模型❌ LoRA 训练完就定型✅ 适合持续优化
低显存设备(8GB 显存)适合(节省显存)❌ 需要更高显存
高精度任务(如 BERT QA)❌ 可能损失精度✅ 适合
多任务迁移学习✅ LoRA 参数可迁移❌ 需要重新训练

7️⃣ 总结

对比项LoRA 微调增量微调
是否修改原始参数不修改 W_0✅ 修改部分参数
训练参数量🎯 少($O(d_{out} x r))🚀 中($O(N xd_{out} x d_{in}))
计算量🎯 小(适合大模型)🚀 较大(适合小模型)
存储开销🏆 最小,只存 A,B📈 需要存储新 W
推理方式✅ 可合并参数❌ 需要加载新权重
适用场景🎯 适合 LLM(GPT, LLaMA)🚀 适合任务优化(BERT QA)

### 其他模型微调技术 除了 LoRA 技术外,还有多种模型微调方法被广泛应用于降低资源消耗和提高效率的任务中。以下是几种常见的替代方案: #### 1. **P-Tuning 和 P-Tuning v2** 这些方法通过引入连续提示(continuous prompts)来调整预训练语言模型的行为,而无需修改原始模型的权重。这种方法的核心思想是在输入序列前附加一组可学习的嵌入向量作为提示[^5]。 ```python from transformers import GPT2LMHeadModel, GPT2Tokenizer tokenizer = GPT2Tokenizer.from_pretrained('gpt2') model = GPT2LMHeadModel.from_pretrained('gpt2') # 添加可学习的 prompt tokens prompt_tokens = torch.nn.Parameter(torch.randn((num_prompt_tokens, model.config.hidden_size))) ``` #### 2. **Adapter Tuning** 适配器微调是一种轻量级的方法,在不改变原模型结构的情况下,插入小型神经网络模块(即适配器),仅对这些新增加的部分进行优化。这种方式显著减少了需要更新的参数数量[^6]。 ```python from adapters import AdapterConfig, BertModelWithHeads config = AdapterConfig(mh_adapter=True, output_adapter=True, reduction_factor=8) model.add_adapter("task_name", config=config) # 训练期间冻结基础模型并只更新adapter部分 for param in model.base_model.parameters(): param.requires_grad = False ``` #### 3. **BitFit** 此方法主张仅仅调节每一层中的偏置项(bias terms),而不是整个权重矩阵。由于每层只有一个较小维度的bias vector需要重新训练,因此极大地降低了计算成本与内存需求[^7]。 ```python import torch.optim as optim def set_bitfit(model): for name, param in model.named_parameters(): if 'bias' not in name: param.requires_grad_(False) set_bitfit(model) optimizer = optim.Adam([p for p in model.parameters() if p.requires_grad], lr=learning_rate) ``` #### 4. **Prefix Tuning** 类似于Prompt Learning的概念,但是更进一步地设计了一套固定的prefix embeddings加入到attention机制里参与运算过程之中。相比起完全重写所有的transformer layers weights来说更加高效经济实用得多[^8]。 ```python class PrefixEncoder(nn.Module): def __init__(self, prefix_length, hidden_dim): super().__init__() self.prefix_embedding = nn.Embedding(prefix_length * num_layers, hidden_dim) def forward(self, batch_size): prefixes = self.prefix_embedding.weight.reshape(num_layers, -1).unsqueeze(0).expand(batch_size,-1,-1) return prefixes ``` 以上列举了几种主流且有效的减少大规模预训练模型fine-tune开销的技术手段,它们各自有其特点以及适用场景,请依据具体项目需求选取最合适的策略实施应用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值