沈阳网站制作企业,网络工程师资料,上海网站建设 app开发,广告网站建设制作设计目录 1.低秩适配(LoRA)概述 2.低秩适配(LoRA)原理 3.低秩适配(LoRA)的工作原理 在大语言模型(LLM)、多模态大模型(MLLM)等预训练模型的应用落地中#xff0c;监督微调(Supervised Fine-Tuning, SFT)是连接通用能力与特定任务的关键桥梁。传统的全参数微调虽然能带来显著的效…目录1.低秩适配(LoRA)概述2.低秩适配(LoRA)原理3.低秩适配(LoRA)的工作原理在大语言模型(LLM)、多模态大模型(MLLM)等预训练模型的应用落地中监督微调(Supervised Fine-Tuning, SFT)是连接通用能力与特定任务的关键桥梁。传统的全参数微调虽然能带来显著的效果提升但对GPU资源的高需求、训练成本的高昂以及过拟合风险的增加使其在资源受限场景下难以普及。1.低秩适配(LoRA)概述一个矩阵具有低秩性意味着它包含较多的冗余信息将其分解为多个低维矩阵后不会损失过多有用信息。例如一个大小为1024×1024的矩阵可以被近似分解为一个大小为1024×2的矩阵与一个大小为2×1024的矩阵的乘积那么这个1024×1024矩阵参数量减少至原来的0.4%左右。这种低秩特性应用广泛例如可以利用SVD分解实现数据压缩、特征降维、图像处理以及模型计算加速等任务。LoRA(Low-Rank Adaptation)是轻量化微调的里程碑式技术其核心在于预训练模型与微调后模型的参数差异ΔW具有低秩性。这意味着可以用两个低秩矩阵A和B的乘积AB近似表示ΔW从而将参数量压缩至原矩阵的0.1%~1%。从原理上看LoRA通过在Transformer的注意力层或全连接层旁增加一条并行的低秩计算路径将原始输出与低秩模块输出相加实现对模型行为的微调。在训练阶段仅更新A和B矩阵预训练参数保持冻结推理阶段可将AB与原权重合并不增加额外计算开销。相较于全参数微调LoRA在参数量减少99%的情况下仍能保持接近的效果同时支持多任务 LoRA模块的实时切换成为当前大模型微调的主流选择。随着LoRA的广泛应用一系列衍生技术不断突破其性能边界AdaLoRA自适应为不同权重矩阵分配不同秩将更多参数分配给关键层实现 “好钢用在刀刃上”。QLoRA将预训练模型量化为4位大幅降低显存占用使单卡即可微调70B级大模型。PiSSA通过奇异值分解初始化低秩矩阵冻结权重次要成分微调主要成分加速训练收敛。DoRA将预训练权重分解为幅度和方向两部分用LoRA进行方向更新进一步提升微调效果。2.低秩适配(LoRA)原理假设参数矩阵Wq​为预训练模型的参数在微调过程中被冻结保持不变。LoRA参数在微调过程中自由更新。预训练参数矩阵Wq​​分别并联了LoRA模块并对这些模块进行微调。实践中可以选择性地仅对部分参数矩阵并联LoRA模块。利用LoRA 模块对预训练参数矩阵Wq​进行微调的原理LoRA模块通过增加一条并行的轻量级计算路径与原模型无缝衔接。然后通过如下的公式将LoRA模块的计算结果Q2​与原始模型的结果Q1​相加得到最终结果Q。随后将Q输入后续环节进行常规计算上下游模块对LoRA的引入与否完全无感知。LoRA模块由两个低维矩阵组成其核心思想是通过降维和升维操作利用低秩特性实现参数微调。在矩阵的两个维度中较小的维度被称为LoRA的秩(rank, r)。其中ALoRA模块的降维参数矩阵形状为[模型隐层大小,r]。BLoRA模块的升维参数矩阵形状为[r,模型隐层大小]。A和 B的初始化方式矩阵A使用随机数初始化如kaiming初始化而矩阵B使用全0初始化或使用极小的随机数初始化目的是确保在训练初期插入的LoRA模块不会对模型整体输出造成过大的扰动。3.低秩适配(LoRA)的工作原理LoRA工作原理可以通过如下的流程图来表示如上图所示1. 原始路径输入→W→Wx保持预训练知识不变权重W被冻结不参与训练。2. LoRA路径输入→A→B→BAxA矩阵负责降维从维度d降到秩rB矩阵负责升维从秩r升回维度d只有A和B参与训练参数量极少。3. 融合输出WxBAx结合原始能力和新学知识实现高效的参数更新其中:W: 原始大模型权重 (d × k) A: LoRA降维矩阵 (d × r), r dB: LoRA升维矩阵 (r × k) ΔW BA: 权重更新量在推理阶段可以预先将LoRA权重与原始模型权重合并PEFT库中已经提供了成熟的权重合并接口。推理时只需加载合并后的模型权重 从而使推理的计算量与原始模型保持一致。如果要同时处理多种任务那么可以将每个任务对应的LoRA模块权重、预训练权重全部加载到GPU根据请求的任务类型在GPU上实时切换并启用相应的LoRA模块执行对应任务的推理。LoRA的实现程程序如下import math import torch import torch.nn as nn import torch.nn.functional as F class LoRA(nn.Linear): def __init__( self, in_features: int, out_features: int, lora_rank: int, lora_alpha: int 1, lora_dropout: float 0.0, **kwargs ): super().__init__(in_features, out_features, **kwargs) self.lora_rank lora_rank self.lora_alpha lora_alpha self.lora_dropout nn.Dropout(lora_dropout) self.scaling float(lora_alpha) / float(lora_rank) # 创建可训练的 LoRA A、B 矩阵 self.lora_A nn.Parameter(torch.zeros((in_features, lora_rank))) self.lora_B nn.Parameter(torch.zeros((lora_rank, out_features))) # 初始化A 使用 kaiming 均匀分布B 使用 0 初始化 nn.init.kaiming_uniform_(self.lora_A, amath.sqrt(5)) nn.init.zeros_(self.lora_B) # 冻结预训练的权重矩阵 self.weight.requires_grad False self.if_weights_merged False # 忽略权重合并相关代码 def forward(self, x: torch.Tensor): if not self.if_weights_merged: # 原始线性层输出 result F.linear(x, self.weight, biasself.bias) # LoRA 分支输出 lora_output self.lora_dropout(x) self.lora_A lora_output lora_output self.lora_B # 缩放并合并 result lora_output * self.scaling return result else: # 权重已合并直接使用合并后的权重 return F.linear(x, self.weight, biasself.bias) # ------------------------------ # 使用示例 # ------------------------------ if __name__ __main__: # 假设输入维度为 1024输出维度为 1024LoRA 秩为 8 lora_layer LoRA( in_features1024, out_features1024, lora_rank8, lora_alpha16, lora_dropout0.1 ) # 随机输入 x torch.randn(2, 1024) # batch_size2, hidden_dim1024 out lora_layer(x) print(输出形状:, out.shape) # torch.Size([2, 1024])通过上述程序假设原始权重矩阵W是一个10000x10000的庞然大物有一亿个参数。全参数微调 需要训练这一亿个参数。LoRA微调 设定一个很小的秩r8。矩阵A的大小是10000x8 (80000参数)。矩阵B的大小是8x1000 (80000参数)。总共只需要训练160000个参数仅仅是全参数微调的1.6%。通过训练这极少量的参数LoRA就能捕捉到模型适应新任务所需的核心变化实现高效微调。