LoRA假说提出,针对新任务调整预训练权重矩阵 $W$ 所需的改变,可以通过低秩结构有效表示。LoRA不是直接训练可能很大的更新矩阵 $\Delta W$,而是将这个更新分解为两个较小的矩阵 $B$ 和 $A$。考虑我们大型语言模型(LLM)中某层的原始权重矩阵 $W \in \mathbb{R}^{d \times k}$(例如,自注意力或前馈网络中的线性层)。全量微调方法会更新 $W$ 中的所有 $d \times k$ 个参数。LoRA通过保持 $W$ 不变并引入两个新矩阵来避免这种情况:$A \in \mathbb{R}^{r \times k}$$B \in \mathbb{R}^{d \times r}$这里,$r$ 是分解的秩,它是选择的超参数,使得 $r \ll \min(d, k)$。原始权重更新 $\Delta W$ 随后通过这两个矩阵的乘积进行近似:$$ \Delta W \approx BA $$注意尺寸:矩阵 $B$($d \times r$)与矩阵 $A$($r \times k$)相乘得到一个原始尺寸 $d \times k$ 的矩阵,适合作为 $W$ 的更新。修改后的前向传播在微调过程中,层的正向传播被修改。对于输入 $x \in \mathbb{R}^{k}$,原始计算是 $h = Wx$。使用LoRA后,输出 $h \in \mathbb{R}^{d}$ 变为:$$ h = Wx + \Delta W x = Wx + BAx $$值得注意的是,预训练权重 $W$ 在训练期间不会更新。只有尺寸小得多的矩阵 $A$ 和 $B$ 的参数得到优化。这大大减少了可训练参数的数量。The LoRA技术引入了一个缩放因子 $\alpha$。包含此缩放的修改后前向传播通常写为:$$ h = Wx + \frac{\alpha}{r} BAx $$这里,$\alpha$ 是另一个超参数,它缩放LoRA更新的贡献。除以秩 $r$ 有助于规范更新的量级,使 $\alpha$ 的影响对 $r$ 的选择依赖性降低。本质上,$\alpha$ 控制了调整后的模型与原始模型的偏离程度。参数效率效率提升源于可训练参数的大幅减少。我们不再训练 $\Delta W$ 的 $d \times k$ 个参数,而只训练 $A$ 和 $B$ 中的参数。LoRA中的总可训练参数 = 参数(A) + 参数(B) = $(r \times k) + (d \times r) = r(d + k)$。考虑一个典型的,其中 $d = k = 4096$ 的大型线性层。$W$(或 $\Delta W$)中的参数数量:$4096 \times 4096 = 16,777,216$。LoRA中 $r=8$ 时的参数数量:$8 \times (4096 + 4096) = 8 \times 8192 = 65,536$。在这个例子中,相较于该单一层的全量微调,LoRA仅需训练约 $0.39%$ 的参数(即 $65,536 / 16,777,216$)。这种减少非常显著,尤其当应用于大型模型中的多个层时,带来内存(用于优化器状态、梯度)的大幅节省和潜在更快的训练迭代。初始化LoRA矩阵的恰当初始化对于训练稳定性很重要。一种常见做法是:使用随机高斯值初始化 $A$。用零初始化 $B$。这保证了在训练开始时($t=0$),乘积 $BA$ 为零。因此,初始的LoRA适应模型行为与原始预训练模型($\Delta W = 0$)完全相同,为适应过程提供了一个稳定的起点。数据流的可视化我们可以可视化LoRA调整层中的数据流,它如何修改线性层的标准前向传播。digraph G { rankdir=LR; node [shape=box, style=rounded, fontname="sans-serif", color="#495057", fillcolor="#e9ecef", style="filled, rounded"]; edge [fontname="sans-serif", color="#495057"]; subgraph cluster_original { label="原始层"; bgcolor="#f8f9fa"; style=dashed; color="#adb5bd"; x [label="输入 (x)", shape=ellipse, color="#228be6", fillcolor="#a5d8ff"]; W [label="冻结权重 (W)"]; h_orig [label="输出 (Wx)", shape=ellipse, color="#228be6", fillcolor="#a5d8ff"]; x -> W [label=" 相乘"]; W -> h_orig; } subgraph cluster_lora { label="LoRA路径"; bgcolor="#fff9db"; style=dashed; color="#fab005"; A [label="矩阵 A (r x k)", color="#f76707", fillcolor="#ffd8a8"]; B [label="矩阵 B (d x r)", color="#f76707", fillcolor="#ffd8a8"]; Scale [label="缩放 (α/r)", shape=diamond, color="#ae3ec9", fillcolor="#eebefa"]; BAx [label="BAx"]; x_copy [shape=point, width=0]; x -> x_copy [style=invis]; // 用于定位的辅助节点 x_copy -> A [label=" 相乘"]; A -> B [label=" 相乘"]; B -> Scale; Scale -> BAx; } Add [label="相加", shape=circle, style="filled", fillcolor="#ced4da", fixedsize=true, width=0.5]; h_final [label="最终输出 (h)", shape=ellipse, color="#228be6", fillcolor="#a5d8ff"]; h_orig -> Add; BAx -> Add; Add -> h_final; // 使输入x在视觉上只出现一次 { rank=same; x; x_copy } }LoRA调整层中的数据流。输入 x 经过原始冻结权重矩阵 W。同时,x 也由低秩矩阵 A 和 B 处理,随后进行缩放。这两条路径的输出随后相加,生成最终输出 h。这种分解使得LoRA能够高效地调整大型模型,通过将学习过程集中在一组小的、精心构造的参数上,这些参数近似于对原始权重所需的改变。后续部分将介绍实用方面,例如选择秩 $r$ 和缩放因子 $\alpha$。