微信扫码
添加专属顾问
我要投稿
DoRA(Weight-Decomposed Low-Rank Adaptation)的主要思想是将预训练权重分解为幅度(magnitude)和方向(direction),并利用LoRA来微调方向矩阵,这种权重分解策略允许DoRA更精细地控制模型的学习过程,分别针对权重的幅度和方向进行优化。在调整方向部分时,DoRA利用了LoRA的策略,通过低秩适应来有效地更新方向,而幅度部分则单独进行调整。
LoRA 本质上就是把大矩阵拆成两个小矩阵的乘法
LoRA具体的代码实现
import torchimport torch.nn as nnimport torch.nn.functional as Fclass LoRALayer(nn.Module):def __init__(self, in_dim, out_dim, rank, alpha):super().__init__()std_dev = 1 / torch.sqrt(torch.tensor(rank).float())# 初始化参数 A 和 B,其中 A 是输入特征和排名之间的参数,B 是排名和输出特征之间的参数self.A = nn.Parameter(torch.randn(in_dim, rank) * std_dev)# 参数 Aself.B = nn.Parameter(torch.zeros(rank, out_dim))# 参数 Bself.alpha = alpha# LoRA 中的 alpha 参数def forward(self, x):# LoRA 的前向传播过程x = self.alpha * torch.matmul(torch.matmul(x, self.A), self.B)# 使用参数 A 和 B 进行计算return xclass LinearWithLoRAMerged(nn.Module):def __init__(self, linear, rank, alpha):super().__init__()self.linear = linear# 原始的线性层self.lora = LoRALayer(linear.in_features, linear.out_features, rank, alpha)# LoRA 层def forward(self, x):lora = torch.matmul(self.lora.A, self.lora.B)# 组合 LoRA 中的参数 A 和 Bcombined_weight = self.linear.weight + self.lora.alpha * lora.T# 将 LoRA 和原始权重结合起来return F.linear(x, combined_weight, self.linear.bias)# 使用结合后的权重进行线性变换
DoRA的核心组成可分为以下几个部分:
• 权重分解:DoRA首先对预训练模型的权重进行分解,将每个权重矩阵分解为幅度(magnitude)向量和方向(direction)矩阵。这种分解使得模型可以更好地控制权重的学习过程。
• 幅度和方向调整:在微调阶段,DoRA分别对这两个分解出的组件进行调整。其中,幅度表示权重矩阵的大小,而方向则描述了权重向量的方向变化。
• 方向更新:DoRA使用LoRA进行方向性更新,只调整方向部分的参数,而保持幅度部分不变。
• 混合权重:最终的微调权重通过组合调整后的幅度m和经过LoRA更新的方向V来构建,形式上表现为W' = m * V + ∆V / ||V + ∆V||c。
• 模块选择:在微调过程中,DoRA选择只更新某些模块(如QKV注意力机制中的query、key、value模块)的幅度和方向,而对于剩余的线性层(如MLP层)仅更新其幅度,这样的粒度控制有助于提高性能并减少所需训练的参数数量。
综合以上几点,DoRA通过创新的权重分解策略和定向低秩适应技术,既保持了与全量微调相似的学习行为和容量,又实现了参数效率的优化,从而在广泛的自然语言处理(NLP)任务到跨模态(Vision-Language)任务的各种应用场景中都取得了优于LoRA的效果。
DoRA具体代码实现
import torchimport torch.nn as nnimport torch.nn.functional as Ftorch.manual_seed(0)class DoRALayer(nn.Module):def __init__(self, d_in, d_out, rank=4, weight=None, bias=None):super().__init__()# 初始化权重和偏置if weight is not None:self.weight = nn.Parameter(weight, requires_grad=False)else:self.weight = nn.Parameter(torch.Tensor(d_out, d_in), requires_grad=False)if bias is not None:self.bias = nn.Parameter(bias, requires_grad=False)else:self.bias = nn.Parameter(torch.Tensor(d_out), requires_grad=False)# 计算输出维度上的权重矩阵的列的幅度self.m = nn.Parameter(self.weight.norm(p=2, dim=0, keepdim=True))# 初始化 LoRA 的参数 A 和 Bstd_dev = 1 / torch.sqrt(torch.tensor(rank).float())self.lora_A = nn.Parameter(torch.randn(d_out, rank) * std_dev)self.lora_B = nn.Parameter(torch.zeros(rank, d_in))def forward(self, x):# 计算 LoRA 矩阵lora = torch.matmul(self.lora_A, self.lora_B)# 微调权重adapted = self.weight + lora# 对调整后的权重进行归一化column_norm = adapted.norm(p=2, dim=0, keepdim=True)norm_adapted = adapted / column_norm# 计算最终权重calc_weights = self.m * norm_adapted# 使用最终权重进行线性变换return F.linear(x, calc_weights, self.bias)
DoRA 在各种下游任务(例如常识推理、视觉指令调整和图像/视频文本理解)上微调 LLaMA、LLaVA 和 VL-BART 方面始终优于 LoRA。
具体地:
• 更精准的控制:通过分别针对权重的幅度和方向进行调整,从而能够更准确地适应特定的任务需求。
• 学习能力更优:DoRA的权重分解策略增强了模型在微调过程中的学习能力,能够在不同大小和架构的模型以及各种下游任务上持续超越LoRA的表现,使其在多种下游任务上的性能更接近于全参数微调的方法。
• 保持高效性:尽管DoRA在微调策略上进行了创新,但它仍然保持了LoRA的高效性,避免增加额外的推理成本。
• 更好的训练稳定性:DoRA通过分解权重并专门针对方向使用低秩适应,提高了训练过程的稳定性,有助于避免过拟合和其他训练问题。
53AI,企业落地大模型首选服务商
产品:场景落地咨询+大模型应用平台+行业解决方案
承诺:免费POC验证,效果达标后再合作。零风险落地应用大模型,已交付160+中大型企业
2025-08-21
2025-08-20
2025-09-07
2025-08-21
2025-08-19
2025-08-05
2025-09-16
2025-08-20
2025-07-29
2025-09-08
2025-10-24
2025-10-23
2025-10-23
2025-10-22
2025-10-22
2025-10-20
2025-10-20
2025-10-19