0%

DoRA详解:从LoRA到Weight-Decomposed Low-Rank Adaptation

DoRA详解:从LoRA到Weight-Decomposed Low-Rank Adaptation

DoRA(Weight-Decomposed Low-Rank Adaptation)是对LoRA的一种重要改进方法。它的核心思想是:将权重更新分解为“方向 + 幅度”两个部分分别建模,从而提升表达能力,同时保持参数高效性。

本文将围绕论文中的关键内容进行系统介绍。


1. 3.2 Weight Decomposition Analysis:Analysis Results

论文提出一个关键视角:将权重分解为 方向(direction)+ 幅度(magnitude)

其中:

  • $V$:方向(未归一化)
  • $\frac{V}{|V|}$:单位方向
  • $m$:幅度(norm)

Analysis Results(核心结论)

论文通过实验对比 LoRA 和 Full Fine-Tuning(FT)发现:

1️⃣ 幅度(Magnitude)变化

  • FT:幅度变化显著
  • LoRA:幅度变化非常有限

👉 说明 LoRA 无法有效调整权重的scale


2️⃣ 方向(Direction)变化

  • FT:方向变化更加多样
  • LoRA:方向变化较为单一(受低秩限制)

👉 LoRA 的更新空间被限制在低秩子空间


3️⃣ 本质结论

模型能力差异 ≠ 参数量
而是来源于 更新模式(update pattern)

即:

  • FT:同时自由调整 magnitude + direction
  • LoRA:受限地调整(尤其是 magnitude)

2. 4.1 Intuition

论文给出了两个关键直觉(原文核心思想):


Intuition 1

Firstly, the magnitude and direction of weights play different roles in model adaptation.

解释:

  • magnitude($m$):控制“强度”
  • direction($V$):控制“语义/表示方向”

👉 两者作用不同,不应该混在一起学习


Intuition 2

Secondly, LoRA mainly restricts the update of direction, while magnitude is under-explored.

解释:

  • LoRA 本质是在更新:

  • 但这种方式:

    • 对 direction 有限制(低秩)
    • 对 magnitude 几乎没有单独建模能力

👉 导致表达能力不足


3. 方法(DoRA)

DoRA 的核心思想:

解耦权重:方向用LoRA学习,幅度单独学习


参数化方式

DoRA 将权重写为:

其中:

  • $W_0$:预训练权重
  • $BA$:LoRA低秩更新
  • $m’$:可学习幅度

方法拆解

组件 学习方式
direction LoRA(低秩)
magnitude full parameter

对比总结

方法 magnitude direction
FT
LoRA ❌(弱) ✅(低秩)
DoRA ✅(低秩)

优势

  • 更接近 FT 的学习行为
  • 仍保持参数高效
  • 无推理额外开销(可merge)
  • 更稳定训练

4. 简单实现 + 张量运算讲解

我们来看一个简化实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class DoRALinear(nn.Module):
def __init__(self, in_features: int, out_features: int, rank: int, alpha: float = 1.0):
super().__init__()
self.in_features = in_features
self.out_features = out_features
self.rank = rank
self.alpha = alpha

# Base weight V (direction)
self.W = nn.Parameter(torch.empty(out_features, in_features))
nn.init.kaiming_uniform_(self.W)

# Magnitude vector (initialized from W's norm)
self.m = nn.Parameter(self.W.norm(dim=1))

# LoRA matrices
self.A = nn.Parameter(torch.empty(rank, in_features))
self.B = nn.Parameter(torch.zeros(out_features, rank))
nn.init.kaiming_uniform_(self.A)

def forward(self, x: torch.Tensor) -> torch.Tensor:
# Compute effective weight: m * (V + BA) / ||V + BA||
V = self.W
BA = self.B @ self.A * (self.alpha / self.rank) if self.rank > 0 else 0
W_eff = V + BA
W_eff = self.m.view(-1, 1) * W_eff / W_eff.norm(dim=1, keepdim=True)
return x @ W_eff.T

4.1 核心计算解析

1️⃣ LoRA部分

1
BA = self.B @ self.A
  • B: (out, r)
  • A: (r, in)
  • 结果:(out, in)

2️⃣ 方向更新

👉 表示新的“方向向量”


3️⃣ 归一化(关键)

1
W_eff.norm(dim=1, keepdim=True)
  • dim=1:对每一行(每个输出通道)求norm
  • keepdim=True:保持 shape = (out, 1)

4️⃣ 广播(Broadcasting)

1
self.m.view(-1, 1) * W_eff

shape:

  • m: (out,)
  • → view(-1,1) → (out,1)
  • W_eff: (out, in)

👉 广播规则:

  • (out,1) × (out,in)
  • 自动扩展为 (out,in)

广播成立条件

两个张量可以广播,当:

  1. 从右往左维度匹配
  2. 或其中一个为1

例如:

张量A 张量B 是否可广播
(out,1) (out,in)
(1,in) (out,in)
(out,) (out,in) ❌(需reshape)

5️⃣ 最终公式


6️⃣ 前向传播

1
return x @ W_eff.T
  • x: (batch, in)
  • W_eff.T: (in, out)
  • 输出: (batch, out)

5. 其它重要理解


5.1 本质:DoRA = LoRA + Weight Normalization

DoRA 非常类似:

👉 与 WeightNorm 的思想一致


5.2 为什么有效?

👉 关键点:

  • direction:决定“表示空间”
  • magnitude:决定“激活强度”

LoRA:

  • 两者耦合 → 学习受限

DoRA:

  • 解耦 → 表达能力提升

5.3 为什么只让 LoRA 控制 direction?

因为:

  • direction 是高维结构(更重要)
  • magnitude 是标量(容易学)

👉 用有限参数优先建模“复杂部分”


5.4 推理效率

DoRA 和 LoRA 一样:

  • 可 merge:
  • inference 无额外开销

6. 总结

DoRA 的核心贡献可以一句话概括:

通过“方向(LoRA)+ 幅度(全参数)”解耦,使参数高效微调更接近全量微调的表达能力。


关键 takeaway

  • LoRA 的瓶颈:更新模式受限
  • DoRA 的突破:结构性解耦
  • 本质思想:表示分解(representation decomposition)

如果你读到这里,其实已经抓住 DoRA 的精髓了。

如果你还想更进一步,可以继续问我:

👉「DoRA 为什么在某些任务上接近 FT?」
👉「DoRA 和 QLoRA 能不能结合?」