lora通过在冻结的原始权重旁注入低秩矩阵a和b实现轻量微调:遍历模型,将目标linear层(如q_proj、v_proj)替换为自定义层,其中lora_a形状为(r, in_features)、lora_b为(out_features, r),初始化lora_a为高斯噪声、lora_b为零;仅对含“lora_”前缀的参数优化,训练后仅保存这两组小权重,加载时需映射回对应层并确保scaling因子合理。

LoRA层怎么加进PyTorch模型里
直接在原始权重上做全参数微调成本太高,LoRA的核心是“不动原权重,只加小矩阵”。PyTorch本身不内置LoRA,得手动替换Linear层——不是用装饰器或自动注入,而是遍历模型子模块,把目标nn.Linear替换成带lora_A和lora_B的自定义层。
关键点:只对特定层加LoRA(比如Transformer里的q_proj、v_proj),避免全模型膨胀;lora_A形状为 (r, in_features),lora_B为 (out_features, r),相乘后维度才匹配原权重增量;初始化时lora_A用高斯噪声、lora_B置零,保证初始更新为0。
- 别替换
nn.Embedding或nn.LayerNorm——LoRA对它们无效且易崩 - 替换前用
model.named_modules()确认目标层名,比如model.layers.0.self_attn.q_proj - 替换后务必调用
model.requires_grad_(False)冻结原参数,再单独设lora_A/lora_B为requires_grad=True
训练时如何控制LoRA参数更新
PyTorch的optimizer默认会收集所有requires_grad=True的参数,但LoRA要求只优化新增的小矩阵,必须显式过滤。不能靠model.parameters()一股脑传进去,否则会意外训练原始权重。
典型写法是用生成器表达式提取LoRA参数:
lora_params = [p for n, p in model.named_parameters() if 'lora_' in n] optimizer = torch.optim.AdamW(lora_params, lr=3e-4)
注意:'lora_'是命名约定,你自定义层里要统一用这个前缀;如果用了peft库,它内部也靠类似逻辑筛选,但手写更可控。
- 检查
len(lora_params)是否符合预期(比如r=8时,单个Linear层引入2×8×hidden_size参数) - 别漏掉
lora_dropout这类可训练参数(如果实现里加了dropout并设了requires_grad=True) - 混合精度训练(
torch.cuda.amp)下,确保lora_A/lora_B没被误转成float16导致梯度溢出——可单独设dtype=torch.float32
保存和加载LoRA权重要注意什么
LoRA权重体积小,但不能直接torch.save(model.state_dict())——里面混着冻结的大权重,浪费空间还难复现。正确做法是只保存lora_A和lora_B,且文件名明确标注r值和目标层。
加载时不是load_state_dict()整个模型,而是先重建原始模型(比如从transformers.AutoModel加载),再按名称映射把LoRA张量赋给对应层的属性。
- 保存示例:
torch.save({n: p for n, p in model.named_parameters() if 'lora_' in n}, 'lora_r8_qv.pt') - 加载后必须调用
model.eval()或确保lora_dropout处于正确模式(训练/推理) - 跨设备加载(比如CPU训完GPU跑)记得加
map_location,否则RuntimeError: attempting to deserialize object on a CUDA device
为什么验证时loss不降反升
常见原因是LoRA缩放因子没设对。原始LoRA论文中,最终增量是(lora_B @ lora_A) * scaling,其中scaling = r / alpha。很多实现默认alpha=1,但实际应设为与r同量级(如r=8时alpha=16),否则更新步长过大,梯度爆炸。
另一个隐蔽坑:LoRA只加在输入投影方向(如q/v),但有些模型结构里o_proj(输出投影)也参与注意力计算,漏掉它会导致信息流不对称。
- 检查
forward里是否漏了self.scaling乘法,或者误写成alpha / r - 用
torch.norm(lora_B @ lora_A, 2)对比原权重torch.norm(weight, 2),理想比值应在1e-3量级 - 如果用
HuggingFace Transformers加载模型,注意config.hidden_size是否被修改过——会影响LoRA矩阵形状校验
LoRA不是黑盒开关,每个r值、每组目标层、每个scaling系数,都得结合下游任务loss曲线来试;最常被跳过的步骤是——没在验证集上单独测LoRA权重加载后的前向一致性。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











