lora原理和代码实现

本篇文章结合代码来介绍大模型高效微调技术LoRA,并给出简单的代码实现。

什么是LoRA

LoRA是一种高效的参数微调技术,引入可训练的低秩分解矩阵来调整模型参数,来适应特定的任务和领域

为什么需要LoRA

  1. ft整个大模型训练成本过高
  2. 大模型中参数量巨大,可能是冗余的,参数有更小的内在维度

LoRA是如何实现的

下面本节将从基本原理与代码实现两个角度介绍LoRA

LoRA的基本原理

在LoRA的实现中,我们引入了两个低秩矩阵A和B。在训练过程中,我们冻结了预训练模型的参数,仅对降维矩阵A和升维矩阵B进行训练。最终的输出可以表示为h = Wx + BAx。

其中,A矩阵通过高斯随机初始化,而B用0初始化,保证了训练初期△W仍然为0,使得模型优化初始点和原始大模型保持一致。

picture 4

通过这种方式,我们可以显著减少微调所需的参数量。假设原始维度d = 1k,秩为r = 2 , r << d

全参微调: △W = d * d = 100w
lora微调: △W = d * r + r * d = 4K

微调参数量节省了 100w / 4k = 250倍。

在训练完成后,我们可以将A * B^T加到W上,这样在推理时不会引入额外的延迟,从而实现高效的模型推理。

LoRA在Transformer中的应用

本质上可以将这种方法应用到任何一个参数矩阵中,来减少可训练的参数量。

在Transformer的自注意力模块中,就有权重矩阵Wq, Wk, Wv, Wo,在MLP模块中,就有升维矩阵up_proj和降维矩阵down_proj。

picture 5

LoRA代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
import torch
import torch.nn as nn
import torch.nn.functional as F
import math

class LinearLoRA(nn.Module):
def __init__(self,
in_features,
out_features,
rank,
alpha):

super().__init__()
self.in_features = in_features
self.out_features = out_features
self.rank = rank
self.alpha = alpha

# 预训练的权重矩阵
self.pre_trained_weight = nn.Linear(in_features, out_features)
# 冻结,设置为不可训练
self.pre_trained_weight.weight.requires_grad = False
self.pre_trained_weight.bias.requires_grad = False

# 低秩矩阵A和B
self.lora_A = nn.Parameter(torch.zeros(in_features, rank))
# 对A矩阵进行高斯初始化
nn.init.kaiming_normal_(self.lora_A, a = 0.01)

self.lora_B = nn.Parameter(torch.zeros(rank, out_features))
self.scale = self.alpha / self.rank

def forward(self, X):
# X shape :[batch_size, seqence_len, in_Feature]

# part 1
part1 = self.pre_trained_weight(X)

# part 2
part2 = X @ self.lora_A @ self.lora_B
part2 = self.scale * part2

output = part1 + part2
return output

运行一下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# 测试代码
in_features = 64
out_features = 64
rank = 4
alpha = 8

batch_size = 2
seq_len = 8

X = torch.randn(batch_size, seq_len, in_features)

lora_layer = LinearLoRA(in_features= in_features, out_features= out_features, rank= rank, alpha= alpha)

output = lora_layer(X)
print(output.shape)

LoRA与其他高效微调技术的对比

  1. Adapter
    在预训练模型中插入小的可训练的适配器模块(比如两层前馈网络),在训练时原始模型参数冻结,而adapter模块被训练。
    缺点:插入了额外模块增加层数,影响推理延迟

  2. Prefix Tuning
    在输入前添加一些可训练的“前缀”向量,前缀向量可以看做是特定任务的Prompt,用于引导模型进行输出。
    缺点:比较难训练,留给前缀的序列长度挤压了输入的序列长度,效果不如ft

  3. P-tuning
    前缀可以是通过神经网络生成的连续提示向量,分布在句子的不同位置。

参考资料

LoRA 原理和 PyTorch 代码实现


lora原理和代码实现
https://abigail61.github.io/2025/03/23/lora原理和代码实现/
作者
Yajing Luo
发布于
2025年3月23日
许可协议