LoRA 低秩微调大模型
FreeGuideOnline
最新
2026-07-13
python import torch import torch.nn as nn import torch.nn.functional as F
### 定义一个 LoRALayer
我们对线性层进行包装:
```python
class LoRALinear(nn.Module):
def __init__(self, in_features, out_features, r=4, lora_alpha=16, lora_dropout=0.0):
super().__init__()
self.in_features = in_features
self.out_features = out_features
self.r = r
self.lora_alpha = lora_alpha
self.scaling = lora_alpha / r
# 原始权重层,冻结
self.linear = nn.Linear(in_features, out_features, bias=False)
self.linear.weight.requires_grad = False
# LoRA 可训练参数
self.lora_A = nn.Parameter(torch.zeros(r, in_features))
self.lora_B = nn.Parameter(torch.zeros(out_features, r))
self.lora_dropout = nn.Dropout(p=lora_dropout)
# 初始化
nn.init.kaiming_uniform_(self.lora_A, a=5 ** 0.5)
nn.init.zeros_(self.lora_B) # B 初始全零,让 Lora 从零开始
def forward(self, x):
result = self.linear(x) # 原始输出
if self.r > 0:
x = self.lora_dropout(x)
lora_out = (x @ self.lora_A.T @ self.lora_B.T) * self.scaling
result += lora_out
return result
注意:初始化时 $A$ 使用随机分布,$B$ 初始化为零,确保训练开始时 LoRA 分支输出为零,不影响原始模型行为。
应用 LoRA 到线性层
在实际使用时,我们需要替换目标模型中的线性层。以 Hugging Face 的 transformers 库为例,可以定义一个替换函数:
def apply_lora_to_model(model, target_modules, r=8, lora_alpha=32):
for name, module in model.named_children():
if isinstance(module, nn.Linear) and name in target_modules:
in_f, out_f = module.in_features, module.out_features
lora_linear = LoRALinear(in_f, out_f, r=r, lora_alpha=lora_alpha)
lora_linear.linear.weight.data = module.weight.data
setattr(model, name, lora_linear)
else:
# 递归处理子模块
apply_lora_to_model(module, target_modules, r, lora_alpha)
通常 target_modules 可设置为例如 ['q_proj', 'k_proj', 'v_proj', 'o_proj'](具体名称依模型而定)。
训练过程简介
训练循环与普通 PyTorch 训练完全一致:
optimizer = torch.optim.AdamW(
filter(lambda p: p.requires_grad, model.parameters()),
lr=1e-3
)
# 训练循环
model.train()
for batch in dataloader:
loss = model(batch)
loss.backward()
optimizer.step()
optimizer.zero_grad()