LoRA(Low-Rank Adaptation) 是一种通过低秩矩阵分解实现参数高效微调的技术。其核心思想是:冻结预训练模型参数,仅通过训练两个低秩矩阵来模拟参数变化量。以下是通俗解释与代码实现:

一、原理图解(3步理解)
1、旁支结构: 在原始模型层(如线性层)旁添加两个小矩阵 A A A(降维)和 B B B(升维),其中秩 r ≪ d r≪d rd(原矩阵维度)。

更新后的权重矩阵可以表示为:

W ′ = W + Δ W = W + A ⋅ B W' = W + \Delta W = W + A⋅ B W=W+ΔW=W+AB

其中, Δ W = A ⋅ B \Delta W = A ⋅ B ΔW=AB是低秩更新矩阵.

2、训练过程: 只更新 A A A B B B ,原始参数 W W W 保持冻结。
3、推理合并: 训练后将 Δ W \Delta W ΔW W W W 合并,不增加推理耗时。
在微调过程中,只训练低秩矩阵 A和B,而冻结原始模型的权重,从而大幅减少计算开销。
在这里插入图片描述
在这里插入图片描述

LoRA大大节省微调大模型的参数量;效果和全量微调差不多;微调完的LoRA模型权重可以Merge回原来的权重,不会改变模型结构,推理时不增加额外计算量;你可以通过改变r参数,最高情况等同于全量微调。

特点
高效性:由于只训练低秩矩阵,参数量大幅减少(通常为原始模型参数的0.1%-1%),计算和存储开销显著降低。
模块化:LoRA的适配模块(低秩矩阵)可以独立于原始模型保存和加载,便于在不同任务之间切换。
兼容性:可以与多种模型架构(如Transformer)和任务(如文本分类、生成、翻译)结合使用。
避免灾难性遗忘:由于原始模型权重被冻结,LoRA在适配新任务时不会破坏预训练模型的通用知识。
可扩展性:可以与其他高效微调方法(如Adapter、Prefix Tuning)结合使用,进一步提升性能。

应用场景:

  • 资源受限的环境:在计算资源有限的情况下高效微调大模型。
  • 多任务学习:通过为不同任务训练独立的低秩矩阵,快速适配多个任务。
  • 持续学习:在保留预训练知识的同时,逐步适配新任务。

二、Pytorch代码实现(以线性层为例)

import torch
import torch.nn as nn

class LoRALinear(nn.Module):
    def __init__(self, in_dim, out_dim, rank=8, alpha=16):
        super().__init__()
        self.rank = rank
        self.scaling = alpha / rank  # 缩放系数
        
        # 原始权重(冻结)
        self.weight = nn.Parameter(torch.randn(out_dim, in_dim), requires_grad=False)
        
        # LoRA矩阵(可训练)
        self.lora_A = nn.Parameter(torch.randn(rank, in_dim))  # 降维矩阵
        self.lora_B = nn.Parameter(torch.zeros(out_dim, rank)) # 升维矩阵(初始化为0)

    def forward(self, x):
        # 原始输出 + LoRA调整项
        original = x @ self.weight.T
        lora_adjust = (x @ self.lora_A.T) @ self.lora_B.T  # 低秩分解
        return original + self.scaling * lora_adjust

关键点:

  • lora_B 初始化为0,确保训练开始时旁路无影响
  • scaling 系数平衡新旧参数权重(通常设为 α / r α/r α/r

三、实战示例(Hugging Face场景)

from transformers import AutoModel
from peft import LoraConfig, get_peft_model

# 加载预训练模型
model = AutoModel.from_pretrained("bert-base-uncased")

# 配置LoRA参数(仅微调注意力层的q_proj和v_proj)
lora_config = LoraConfig(
    r=8, 
    lora_alpha=16,
    target_modules=["query", "value"],  # 指定微调模块
    lora_dropout=0.1,
    bias="none"
)

# 应用LoRA
model = get_peft_model(model, lora_config)
print(f"可训练参数量: {model.print_trainable_parameters()}")
# 输出示例:0.8M/110M (仅0.7%参数被训练)

四、超参数选择建议
在这里插入图片描述
通过这种方式,LoRA能以1-10%的参数量实现接近全参数微调的效果,实际应用中,可结合Hugging Face的 peft 库快速实现适配。

LoRA的核心优势在于参数高效性而非训练高效性:虽然其可训练参数(低秩矩阵A和B)显著减少(例如从175B降至百万级),但在单卡训练时速度提升有限。这是因为整个预训练模型(PLM)仍需参与前向和反向传播计算,梯度计算过程涉及全部模型参数,而不仅仅是旁路的低秩矩阵。
具体来说:

这里是引用

LoRA的梯度计算包括两个步骤:
1、需要计算整个PLM的梯度
2、使用这些梯度来计算注入矩阵的梯度

Logo

欢迎加入 MCP 技术社区!与志同道合者携手前行,一同解锁 MCP 技术的无限可能!

更多推荐