datawhale--llm-algo-leetcode[10] LoRA

发布时间:2026/10/27 6:55:16

datawhale--llm-algo-leetcode[10] LoRA 链接笔记10. LoRA Tutorial | LoRA 教程本章目标实现最小LoRALinear看清低秩旁路 A、B 如何构成Δ W \Delta WΔW以及为什么它能用较少的可训练参数完成微调。完成后你应该能把 LoRA 接到端到端微调实验和 QLoRA 低比特微调里。冻结主权重 → 低秩旁路 A/B → 缩放 → 合并权重 → 合并后的零额外 LoRA 推理开销本章不会重新讲优化器基础只聚焦 LoRA 的低秩更新机制和参数冻结关系。模型架构总览LoRA 在微调技术路线中的位置预训练模型权重 W_0 冻结LoRA 旁路矩阵 A (r×k), B (d×r)前向传播h W_0 x (α/r) BAx训练只更新 A 和 B合并权重W_merged W_0 (α/r) BA推理标准 Linear 层零额外开销微调后的模型与原始模型结构相同结构说明LoRA 的核心思想是冻结预训练权重只在旁边加一条低秩可训练旁路。推理时可以将旁路权重合并回主权重实现合并后的零额外 LoRA 推理开销。LoRA 前向传播数据流输入 x[B, S, k]主权重 W_0[d, k] 冻结矩阵 A[r, k] 可训练矩阵 B[d, r] 可训练缩放 α/r主分支输出W_0 x[B, S, d]LoRA 分支输出(α/r) BAx[B, S, d]最终输出h W_0 x (α/r) BAx合并后W_merged W_0 (α/r) BA本节核心概念LoRA 三要素冻结主权重W_0 不更新低秩旁路A (降维), B (升维)合并后的零额外 LoRA 推理开销合并权重本节涉及的模块模块章节形状变化核心作用输入张量#0[B, S, k]原始输入主权重 W_0#1[d, k]冻结的预训练权重矩阵 A#1[r, k]降维矩阵可训练矩阵 B#1[d, r]升维矩阵可训练LoRA 输出#2[B, S, d]低秩旁路的增量合并权重#3[d, k]W_0 (α/r) BA核心原则LoRA 不是少写几个参数而是把更新预算集中到最有效的低秩方向上。0. 学习本章前先认识这些名词名词英文简单理解LoRALow-Rank Adaptation低秩适配冻结主权重训练旁路矩阵旁路Sidecar / Adapter在主干网络旁边附加的可训练模块低秩Low-Rank矩阵的秩远小于原始维度缩放因子Scaling Factorα/r控制 LoRA 更新的影响程度合并权重Merge Weights将 LoRA 旁路合并回主权重实现合并后的零额外 LoRA 推理开销PEFTParameter-Efficient Fine-Tuning参数高效微调不需要过度强调LoRA 只用于大模型LoRA 的思想可以应用到任何线性层包括小模型和卷积层。理解低秩更新的数学本质比记住LoRA 用于 7B 模型更重要。1. 核心差异与机制1.1 全参微调 vs LoRA全参微调和 LoRA 的关键差异在于参数更新范围全参微调 (Full Fine-tuning): 给定预训练模型 更新所有参数 显存参数 梯度 优化器状态Adam 通常包含参数、梯度和一阶/二阶状态 目标重新学习所有任务相关的权重 LoRA: 给定预训练模型 更新只更新旁路矩阵 A 和 B 显存只保存 A、B 的梯度和优化器状态 目标在预训练知识基础上做小幅适配为什么 LoRA 能节省显存以 7B 模型为例方法可训练参数显存占用FP16全参微调7B~14GB仅参数LoRA (r8)约35M取决于目标层仅参数约70MB不含梯度和优化器状态LoRA (r16)~70M~140MBLoRA 的训练显存节省主要来自不需要保存主权重的梯度不需要为主权重保存优化器状态动量、方差只保存 A、B 两个小矩阵的优化器状态1.2 低秩更新的数学原理核心假设预训练权重的更新矩阵Δ W \Delta WΔW是低秩的即Δ W ≈ B A \Delta W \approx BAΔW≈BA其中B ∈ R d × r B \in \mathbb{R}^{d \times r}B∈Rd×rA ∈ R r × k A \in \mathbb{R}^{r \times k}A∈Rr×kr ≪ min ⁡ ( d , k ) r \ll \min(d, k)r≪min(d,k)为什么是低秩直觉预训练模型已经在高维空间中学习到了通用特征。微调时我们只需要在少数几个方向上做小幅调整不需要重新学习所有维度。理解重点LoRA 假设微调产生的更新矩阵可以被低秩矩阵近似实际效果需要通过具体任务实验验证。1.3 缩放因子α / r \alpha/rα/r为什么需要缩放当改变秩r rr时需要控制 LoRA 更新量的幅度。缩放因子α / r \alpha/rα/r的作用是作为一个额外缩放项帮助控制不同秩设置下的更新幅度实际效果取决于α \alphaα、r rr、学习率和训练设置通常设置α r × learning_rate_scale \alpha r \times \text{learning\_rate\_scale}αr×learning_rate_scale常见配置秩 r缩放因子 α实际缩放 α/r81621616132321646412. 代码实现框架2.1 LoRALinear 完整实现importtorchimporttorch.nnasnnimporttorch.nn.functionalasFimportmathclassLoRALinear(nn.Module):def__init__(self,in_features:int,out_features:int,r:int8,lora_alpha:int16):super().__init__()self.rr self.lora_alphalora_alpha self.scalingself.lora_alpha/self.r# 主权重冻结的预训练线性层self.linearnn.Linear(in_features,out_features,biasFalse)self.linear.weight.requires_gradFalse# LoRA 旁路矩阵self.lora_Ann.Parameter(torch.empty(r,in_features))self.lora_Bnn.Parameter(torch.empty(out_features,r))self.reset_parameters()defreset_parameters(self):按照 LoRA 论文的规则初始化# 主权重保持预训练权重的原始初始化# 实际使用预训练模型时此处应加载已有 W_0而不是重新初始化# nn.init.kaiming_uniform_(self.linear.weight, amath.sqrt(5))# LoRA AKaiming 均匀分布提供随机性nn.init.kaiming_uniform_(self.lora_A,amath.sqrt(5))# LoRA B必须初始化为 0确保初始输出等于冻结权重nn.init.zeros_(self.lora_B)defforward(self,x:torch.Tensor)-torch.Tensor: 前向传播主分支 LoRA 旁路 Args: x: [..., in_features] Returns: output: [..., out_features] # 主分支输出resultself.linear(x)# LoRA 旁路输出lora_out(x self.lora_A.T) self.lora_B.T*self.scaling# 两者相加resultlora_outreturnresultdefmerge_weights(self): 将 LoRA 旁路合并回主权重 合并后W_merged W_0 (α/r) BA 推理时与标准 Linear 层完全相同 self.linear.weight.data(self.lora_B self.lora_A)*self.scalingShape 对齐示意输入 x: [B, S, k] 主权重 W_0: [d, k] LoRA A: [r, k] LoRA B: [d, r] 主分支: x W_0.T → [B, S, d] LoRA 分支: x A.T B.T → [B, S, d] 缩放: * (α/r) 最终: 主分支 LoRA 分支 → [B, S, d]3. 动手实战下面是独立 toy 示例不依赖主线模型。3.1 TODOTODO 1初始化补全__init__中的主权重和 LoRA 矩阵初始化。TODO 2权重初始化补全reset_parameters中的 Kaiming 和 zeros 初始化。TODO 3前向传播补全forward中的主分支和 LoRA 旁路计算。TODO 4合并权重补全merge_weights中的权重合并逻辑。3.2 建议测试代码deftest_lora():in_dim,out_dim128,256batch_size,seq_len32,10layerLoRALinear(in_dim,out_dim,r8,lora_alpha16)xtorch.randn(batch_size,seq_len,in_dim)# 1. 验证初始化B 全零所以初始输出等于冻结权重的输出withtorch.no_grad():out_loralayer(x)out_baselayer.linear(x)asserttorch.allclose(out_lora,out_base),\初始化错误: lora_B 未被初始化为 0# 2. 模拟训练一步改变 B 的值layer.lora_B.data.normal_(0,0.02)out_trainedlayer(x)assertnottorch.allclose(out_trained,out_base),\前向传播错误: 旁路未能注入增量# 3. 验证合并权重的正确性layer.merge_weights()out_mergedlayer.linear(x)asserttorch.allclose(out_trained,out_merged,atol1e-5),\权重合并错误: 合并后的输出与分离时的输出不一致print(\n✅ tests passed)这些测试分别证明什么asserttorch.allclose(out_lora,out_base)证明初始化时 B 全零LoRA 旁路输出为 0总输出等于冻结权重的输出。assertnottorch.allclose(out_trained,out_base)证明 LoRA 旁路可以注入有效的增量更新。asserttorch.allclose(out_trained,out_merged,atol1e-5)证明合并后的权重与分离时的输出完全一致合并后的零额外 LoRA 推理开销成立。4. 与真实源码对应4.1 Hugging Face PEFTHugging Face 的peft库中LoRA 的实现逻辑相同frompeftimportLoraConfig,get_peft_model configLoraConfig(r8,lora_alpha16,target_modules[q_proj,v_proj],lora_dropout0.05,biasnone,task_typeCAUSAL_LM)modelget_peft_model(model,config)4.2 参数量对比以 LLaMA3 8B 为例只对 Q/V 投影应用 LoRA (r8)组件原始参数量LoRA 参数量比例Q/K/V Linear3 × 4096 × 4096 ≈ 50.3M2 × (8 × 4096 4096 × 8) ≈ 131K0.26%单层---32 层-~4.2M-5. 工程要点5.1 秩 r 的选择秩 r参数量适用场景4最少简单任务数据量小8常用大多数场景的默认选择16较多复杂任务数据量充足32很多接近全参微调收益递减经验法则从 r8 开始如果效果不足再逐步增加。r32 以上通常不如直接全参微调。5.2 目标模块的选择不是所有线性层都需要加 LoRA# 常见选择只对 Q/K/V 投影加 LoRAtarget_modules[q_proj,k_proj,v_proj]# 也可以包括 output projectiontarget_modules[q_proj,k_proj,v_proj,o_proj]# 包括 MLP参数量更大target_modules[q_proj,k_proj,v_proj,gate_proj,up_proj,down_proj]经验法则Attention 的 Q/V 投影是常见选择之一不同任务和模型结构可能需要实验比较其他目标模块。5.3 合并权重的时机训练中保持 A 和 B 分离方便继续训练或调整部署前合并权重移除 A 和 B降低推理延迟和显存多适配器可以训练多个 A/B 对推理时动态加载不同适配器5.4 常见陷阱忘记冻结主权重如果requires_grad TrueLoRA 退化为全参微调B 未初始化为 0会导致训练开始时输出与预训练模型不一致缩放因子设置错误影响训练稳定性和最终效果秩过高r 过大时 LoRA 失去意义接近全参微调6. 与 QLoRA 的关系LoRA 和 QLoRA 的关系LoRA: 参数高效微调只训练少量参数 QLoRA: LoRA 4-bit 量化进一步降低显存QLoRA 在 LoRA 的基础上将主权重量化为 4-bitLoRA 旁路保持 FP16/BF16前向传播时反量化主权重与 LoRA 旁路相加7. 本章掌握检查已掌握后应该能回答LoRA 的核心公式h W 0 x α r B A x h W_0 x \frac{\alpha}{r} BAxhW0​xrα​BAx中每个符号代表什么为什么 LoRA B 必须初始化为 0而 A 可以随机初始化合并权重后为什么推理延迟与原始模型相同缩放因子α / r \alpha/rα/r的作用是什么LoRA 和全参微调在数学上有什么区别为什么说 LoRA 不是少写几个参数而是把更新集中到低秩方向8. 本章最终带走的结构输入 x [B, S, k] ↓ 主分支x W_0.T → [B, S, d]冻结 ↓ LoRA 分支x A.T B.T * (α/r) → [B, S, d]可训练 ↓ 相加h W_0 x (α/r) BAx ↓ 训练只更新 A 和 B ↓ 合并W_merged W_0 (α/r) BA ↓ 推理标准 Linear零额外开销9. 带走的直觉LoRA 的核心是低秩假设预训练权重的更新可以用低秩矩阵近似B 初始化为 0 是关键细节确保训练开始时模型行为与预训练模型一致合并权重实现合并后的零额外 LoRA 推理开销这是 LoRA 相比 Adapter 等方法的重要优势缩放因子保持学习率稳定性改变秩时不需要重新调整学习率LoRA 是参数层面的技巧与 SFT 的 loss masking数据层面正交可以同时使用10.辅助理解
延伸阅读

更多相关文章

2026/10/24 8:53:09

分布式定时任务常见问题 解决方案

主流框架:XXL‑Job、Elastic‑Job、Spring‑TaskRedis、Quartz 集群、PowerJob。核心痛点:集中在重复执行、任务丢失、分片错乱、时间漂移、死锁、雪崩、长任务。1. 任务重复执行(最常见)现象同一时刻,多台机器同时跑同…

2026/10/26 23:38:45

VB 6.0控件注册与部署:ReSize.ocx、imgctls.ocx及80040154错误排查

简介:本资源是面向VB初学者与中级开发者的ActiveX控件集成学习包,聚焦窗体自适应布局与图像交互功能增强,解决传统VB界面僵化、图形处理能力薄弱等实际开发痛点。压缩包共75个文件,含2个核心OCX控件(Resize32.ocx与Img…

2026/10/25 23:36:00

Java面试八股文:从背题到讲原理,构建完整知识体系

每次看到"Java面试八股文"这几个字,我心里其实挺复杂的。一方面,市面上确实有太多人靠背诵题库拿到了Offer,结果入职后连一个简单的内存泄漏问题都定位不了;另一方面,面试本身就是一场"八股项目算法&qu…

2026/10/27 16:38:36

YOLO26结合Triplet Attention提升目标检测性能

1. 项目概述:YOLO26与Triplet Attention的强强联合在目标检测领域,YOLO系列算法一直以其实时性和准确性著称。最新发布的YOLO26在保持前代优势的基础上,通过引入WACV-2021提出的Triplet Attention(三重注意力)机制&…

2026/10/27 16:38:36

VS中多个cpp文件含main的调试解决方案

1. 问题本质:VS里“当前文件执行main”不是默认行为,而是需要主动配置的开发习惯 很多人第一次在Visual Studio里打开一个含多个 .cpp 文件的C项目时,会自然地认为:“我正编辑 network_client.cpp ,点调试按钮&…

2026/10/27 16:38:36

SWT RowLayout布局实战:参数语义、换行与RowData缓存坑

SWT 里做桌面界面,最容易被低估的往往不是控件,而是布局。RowLayout 这个名字听起来平平无奇——不就是"一行一行排"吗?可我带过的几个项目里,真正把 RowLayout 用明白的人并不多,更多人是在 GridLayout 里绕…

2026/10/27 16:38:36

SWT RowLayout布局参数详解与动态界面避坑指南

1. 一行控件排不齐,多半是布局方式选错了 第一次在 SWT 里画一堆按钮,很多人的第一反应是给每个控件 setBounds(x, y, w, h) 手动摆位置。写完那一刻看着挺整齐,等到窗口被拖动、字体换成高 DPI、界面语言切换成长短不一的文案,…

2026/10/27 16:38:36

30万行导入拖垮接口后,我落地了一套简易异步任务中心

1. 为什么要单独搞一个异步任务中心1.1 一次 30 万行导入把接口拖垮的现场先说结论:批量导入这类活儿,天生就不该塞进同步 HTTP 请求里。我最早接手的一个后台系统,用户上传 Excel 导入客户资料,接口里直接从MultipartFile读流、逐…

2026/10/27 16:33:34

40G/50G高速网络实战指南:从PAM4、PCIe到RoCEv2全栈调优

1. 这不是“换个网卡”那么简单:40G/50G接口背后的真实战场 你可能在服务器选型单上见过“支持40G/50G SFP”的标注,也可能在机房巡检时瞥见交换机面板上密密麻麻的QSFP28光模块插槽——但绝大多数人对它的理解,还停留在“比万兆快四倍”的粗…

2026/10/27 14:24:03

全国计算机二级C语言真题PDF高效刷题指南

简介:这份PDF是全国计算机二级C语言考试的试题与答案解析,专为备考二级C语言的考生准备。内容涵盖C语言特点与设计理念、程序基本组成单位、main函数执行流程、函数嵌套调用规则、标识符命名规范、整型实型字符型数据类型、八进制十六进制数合法形式、运…

2026/10/27 9:34:54

requests+BeautifulSoup:爬虫抓取h1标题的入门实战指南

简介:一份以实战为导向的Python爬虫入门资源,面向具备基本编程基础、希望快速掌握网络数据抓取的初学者,可解决从零编写简单爬虫的常见困惑。实例以requests库发送HTTP请求、BeautifulSoup解析HTML文档,完整演示从网页中提取 标题…

2026/10/27 0:59:21

递推最小二乘参数辨识MATLAB编程:二阶系统与渐消记忆实现

简介:这是一篇面向控制系统、信号处理与机器学习等领域学习者的最小二乘参数辨识程序说明文档。资源共包含一个docx格式文档,压缩包大小七十八KB,内容围绕递推最小二乘算法和渐消记忆最小二乘算法展开:先构造一个极点位于单位圆内…

2026/10/27 0:02:28

WorkBuddy_新建任务与工作模式19_“模式选错”的典型代价

“模式选错”的典型代价 摘要 在软件工程中,设计模式、架构模式、并发模式乃至团队协作模式的选择,往往在项目早期就决定了后续的开发效率和维护成本。本文通过多个真实场景,剖析“模式选错”带来的典型代价——包括返工成本、技术债务累积、…

2026/10/27 0:02:28

WorkBuddy_新建任务与工作模式20_新手推荐路径

新手推荐路径 摘要 在 AI 辅助开发工具快速普及的今天,新手面对最多的困惑往往不是"工具够不够强",而是"我该从哪一步开始用"。本文提出一条经过实践验证的三阶段学习路径:先从 Ask(问答式交互)起…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑