LoRA 浅析

发布于:2025-06-20 ⋅ 阅读:(16) ⋅ 点赞:(0)

1. 核心思想

LoRA 是一种参数高效的微调方法,旨在减少微调大型语言模型 (LLMs) 所需的计算资源和存储空间。其核心思想是:

  • 冻结预训练模型权重: 在微调过程中,保持预训练 LLM 的原始权重不变。
  • 引入低秩矩阵: 对于 LLM 中的某些层(通常是 Transformer 层的 Query/Key/Value 投影矩阵),引入一对小型的低秩矩阵 A 和 B。
  • 仅训练新增参数: 只训练这些新增的低秩矩阵 A 和 B,而原始预训练权重保持不变。

即只训练新增低秩矩阵的参数,该低秩矩阵带来的参数量远小于整体的参数量,为何采用秩这个概念:
矩阵的秩(rank)本质上是反映了矩阵的“信息量”或“独立性”的概念,在 LoRA 中,秩控制了分解矩阵的“复杂度”或“容量”。如果秩太低,分解后的矩阵可能无法捕捉到足够的特征,从而影响模型的性能;如果秩太高,参数量可能无法大幅度减少。因此选择一个合适的秩同样重要

来源LoRA 论文
来源于 LoRA论文

2. 原理详解

  • 线性层的秩分解: LLM 中的线性层可以表示为矩阵乘法:y = Wx,其中 W 是预训练的权重矩阵。

  • LoRA 的修改:

    LoRA 在此基础上增加了一个并行路径:

    y = Wx + BAx
    
    • A 是一个形状为 (r, in_features) 的矩阵,其中 r 是秩。
    • B 是一个形状为 (out_features, r) 的矩阵。
    • r 通常远小于 in_featuresout_features,因此 BA 是一个低秩矩阵。
  • 训练过程: 在微调过程中,W 被冻结,只有 A 和 B 被训练。

  • 推理过程: 可以选择将 BA 和 W 合并,也可以分开计算。

注意:与全参数微调相比,LoRA 的性能可能略有下降,尤其是在需要模型进行较大改变的任务上

import torch
import torch.nn as nn

class LoRALinear(nn.Module):
    def __init__(self, linear_layer, r: int):
        super().__init__()
        self.linear = linear_layer
        self.r = r
        self.lora_A = nn.Parameter(torch.randn(r, linear_layer.in_features))
        self.lora_B = nn.Parameter(torch.zeros(linear_layer.out_features, r))
        self.scaling = linear_layer.out_features / r

        nn.init.kaiming_uniform_(self.lora_A, a=5**0.5)

        self.weight = None # For merged weights

    def forward(self, x: torch.Tensor):
        if self.weight is not None:
            return F.linear(x, self.weight, self.linear.bias)
        else:
            return self.linear(x) + (x @ self.lora_A.T @ self.lora_B.T) * self.scaling

    def merge(self):
         if self.weight is None:
            self.weight = self.linear.weight + self.lora_B @ self.lora_A

在具体实现中存在一个缩放系数scaling,缩放系数用于调节低秩分解后的参数在微调过程中的影响力。在 LoRA 中,模型的权重 W 被低秩分解为两个矩阵 AB,并在模型的训练过程中对这些矩阵进行微调。缩放系数用于控制这些低秩矩阵对最终模型输出的影响力。

在使用的经验中,缩放系数通常设置为秩的 2 倍表现性能最优


网站公告

今日签到

点亮在社区的每一天
去签到