Heng's Blog

系列

LoRA
04 06

这一系列论文一直围绕同一个问题展开:下游任务究竟需要多少 degrees of freedom,以及这些有限的训练能力应该放在哪里。

最开始,random subspace training 用固定随机投影 Δθ‾=P‾‾z‾\underline{\Delta\theta}=\underline{\underline{P}}\underline{z},把训练限制在一个低维 subspace 中。SAID 在此基础上加入逐层 scaling,让不同层获得不同大小的更新。LoRA 又进一步把研究对象从整个模型的参数 vector 转向单个权重 matrix,用 ΔW‾‾=B‾‾A‾‾\underline{\underline{\Delta W}}=\underline{\underline{B}}\underline{\underline{A}} 直接限制更新的 rank。

但 LoRA 通常会为所有目标 matrix 设置相同的 rank。这样虽然实现简单,却隐含了一个很强的假设:每个 module、每一层都需要相同的更新能力。

AdaLoRA 接着追问:

在总 rank budget 固定时,能否根据不同 module 的重要性动态分配 rank?

AdaLoRA: Adaptive Budget Allocation for Parameter-Efficient Fine-Tuning

Qingru Zhang, Minshuo Chen, Alexander Bukharin, Nikos Karampatziakis, Pengcheng He, Yu Cheng, Weizhu Chen, Tuo Zhao

ICLR 2023

arXiv PDF
Qingru Zhang, Minshuo Chen, Alexander Bukharin, Nikos Karampatziakis, Pengcheng He, Yu Cheng, Weizhu Chen, Tuo Zhao. "AdaLoRA: Adaptive Budget Allocation for Parameter-Efficient Fine-Tuning." ICLR, 2023. arXiv:2303.10512

从固定 rank 到动态分配#

LoRA 把一个权重更新写成 ΔW‾‾=B‾‾A‾‾\underline{\underline{\Delta W}}=\underline{\underline{B}}\underline{\underline{A}}。如果每个目标 matrix 都使用相同的 rank rr,那么 rank budget 就会被平均分配到所有位置。

AdaLoRA 的实验观察是,不同 weight matrix 对下游任务的重要性并不相同。某些 module 增加训练能力会带来明显提升,另一些 module 即使获得更多参数,收益也很小。统一使用相同的 rr,可能让不重要的 matrix 占用过多预算,同时限制真正重要的 matrix。

因此,AdaLoRA 不再预先固定每个 matrix 最终保留多少 rank,而是在训练过程中估计各个更新方向的重要性,再把有限的总预算留给更重要的方向。

这个区别也可以写成一个简单的 rank budget constraint。

LoRA 与 AdaLoRA 怎样分配相同的 rank budget?

假设共有 mm 个目标 matrix。在相同的最终总 rank budget 下:

LoRA:平均分配 rankAdaLoRA:动态分配 rank
r1=r2=⋯=rm=rr_1=r_2=\cdots=r_m=r,因此 ∑k=1mrk=mr\sum_{k=1}^{m}r_k=mr∑k=1mrk=mr\sum_{k=1}^{m}r_k=mr,但不要求 r1=r2=⋯=rmr_1=r_2=\cdots=r_m

两边最终可以使用相同数量的 rank;区别在于 LoRA 预先固定每个 matrix 的 rank,而 AdaLoRA 根据训练中估计的重要性决定每个 rkr_k。

把 rank 拆成可以删除的单位#

LoRA 的 B‾‾A‾‾\underline{\underline{B}}\underline{\underline{A}} 已经限制了 rank,但其中不同方向并没有被显式分离。AdaLoRA 将更新重新参数化为类似 SVD 的形式:ΔW‾‾=P‾‾Λ‾‾Q‾‾\underline{\underline{\Delta W}}=\underline{\underline{P}}\underline{\underline{\Lambda}}\underline{\underline{Q}}。

为什么不能直接裁剪 LoRA 的 rank-1 doublet?

LoRA 的分解并不唯一。对于任意可逆 matrix R‾‾\underline{\underline{R}},都有 B‾‾A‾‾=(B‾‾R‾‾)(R‾‾−1A‾‾)\underline{\underline{B}}\underline{\underline{A}}=(\underline{\underline{B}}\underline{\underline{R}})(\underline{\underline{R}}^{-1}\underline{\underline{A}})。

也就是说,同一个 ΔW‾‾\underline{\underline{\Delta W}} 可以由许多组彼此混合的方向表示。因此,B‾‾\underline{\underline{B}} 的第 ii 列和 A‾‾\underline{\underline{A}} 的第 ii 行没有天然、稳定的对应关系,不能直接把它们当作一个具有独立身份的 rank 单位。若将这一对向量全部置零,它们也很难在后续训练中恢复。

为了得到可以独立衡量、删除和重新激活的 rank 单位,AdaLoRA 在 LoRA 的 low-rank update 上引入了更明确的结构。

其中 P‾‾∈Rd1×r\underline{\underline{P}}\in\mathbb{R}^{d_1\times r},Q‾‾∈Rr×d2\underline{\underline{Q}}\in\mathbb{R}^{r\times d_2},而 Λ‾‾=diag⁡(λ1,…,λr)\underline{\underline{\Lambda}}=\operatorname{diag}(\lambda_1,\ldots,\lambda_r) 是一个 diagonal matrix。

把这个乘积展开,可以得到 ΔW‾‾=∑i=1rλipi‾qi‾T\underline{\underline{\Delta W}}=\sum_{i=1}^{r}\lambda_i\underline{p_i}\underline{q_i}^{T}。这里 pi‾\underline{p_i} 是 P‾‾\underline{\underline{P}} 的第 ii 列,qi‾T\underline{q_i}^{T} 是 Q‾‾\underline{\underline{Q}} 的第 ii 行,而 λipi‾qi‾T\lambda_i\underline{p_i}\underline{q_i}^{T} 是一个 rank-1 component。

这样做的关键,是让一个 rank 对应一个可以单独控制的 singular triplet:(pi‾,λi,qi‾)(\underline{p_i},\lambda_i,\underline{q_i})。

  • 当 λi\lambda_i 被保留时,对应的 rank-1 component 继续参与更新;
  • 当 λi\lambda_i 被置零时,这个 component 不再影响 ΔW‾‾\underline{\underline{\Delta W}};
  • pi‾\underline{p_i} 和 qi‾\underline{q_i} 仍然保留并继续更新,因此被错误移除的方向以后还有机会重新激活。

这里改变的是 effective rank,而不是 Λ‾‾\underline{\underline{\Lambda}} 的实际尺寸。训练过程中 Λ‾‾\underline{\underline{\Lambda}} 始终保持同样的形状,AdaLoRA 只是用 mask 将部分 λi\lambda_i 置零;如果某个方向之后重新变得重要,对应的 λi\lambda_i 仍可再次参与更新。

在理想的正交条件下,ΔW‾‾\underline{\underline{\Delta W}} 的 rank 就等于非零 λi\lambda_i 的数量。于是,调整 rank 可以转化成一个更容易操作的问题:保留哪些 λi\lambda_i,又将哪些 λi\lambda_i 置零。

AdaLoRA 并不是在每一步都对完整的 ΔW‾‾\underline{\underline{\Delta W}} 计算一次精确 SVD。它直接训练 P‾‾\underline{\underline{P}}、Λ‾‾\underline{\underline{\Lambda}} 和 Q‾‾\underline{\underline{Q}},用这种 SVD-like parameterization 避免反复分解大型 matrix 的成本。

为什么需要 orthogonal regularization#

如果不同 rank-1 component 学到了高度重复的方向,那么删除其中一个 component 时,λi\lambda_i 就不再是一个清楚、独立的 rank 开关。

因此,AdaLoRA 希望 P‾‾\underline{\underline{P}} 的列向量和 Q‾‾\underline{\underline{Q}} 的行向量分别保持近似 orthogonal,也就是 P‾‾TP‾‾≈I‾‾\underline{\underline{P}}^{T}\underline{\underline{P}}\approx\underline{\underline{I}} 和 Q‾‾Q‾‾T≈I‾‾\underline{\underline{Q}}\underline{\underline{Q}}^{T}\approx\underline{\underline{I}}。

对应的 regularization 是 R(P‾‾,Q‾‾)=∥P‾‾TP‾‾−I‾‾∥F2+∥Q‾‾Q‾‾T−I‾‾∥F2R(\underline{\underline{P}},\underline{\underline{Q}})=\lVert\underline{\underline{P}}^{T}\underline{\underline{P}}-\underline{\underline{I}}\rVert_F^2+\lVert\underline{\underline{Q}}\underline{\underline{Q}}^{T}-\underline{\underline{I}}\rVert_F^2。

训练目标因此变成 task loss 与 orthogonal regularization 的组合。这个约束减少不同方向之间的信息冗余,也让删除某个 singular triplet 时的变化更稳定。

怎样判断一个方向是否重要#

现在的问题变成:AdaLoRA 应该保留哪个 singular triplet (pi‾,λi,qi‾)(\underline{p_i},\lambda_i,\underline{q_i})?

论文先从单个可训练 scalar ww 的 sensitivity 出发,用一阶 Taylor approximation 估计把它置零会怎样改变 loss。

一阶 Taylor approximation 怎样得到 sensitivity?

假设当前参数为 ww。将它移除,就是把它从 ww 变成 00,因此参数变化为 Δw=0−w=−w\Delta w=0-w=-w。

在当前参数附近对 loss 做一阶 Taylor 展开,可得 L(w+Δw)≈L(w)+∂L∂wΔw\mathcal{L}(w+\Delta w)\approx\mathcal{L}(w)+\frac{\partial\mathcal{L}}{\partial w}\Delta w。

因此,置零前后的 loss 变化近似为 ΔL=L(w+Δw)−L(w)≈−w∂L∂w\Delta\mathcal{L}=\mathcal{L}(w+\Delta w)-\mathcal{L}(w)\approx-w\frac{\partial\mathcal{L}}{\partial w}。

这里需要判断的是变化大小,而不是 loss 增减的方向,所以取绝对值: ∣ΔL∣≈∣w∂L∂w∣|\Delta\mathcal{L}|\approx\left|w\frac{\partial\mathcal{L}}{\partial w}\right|。这就得到论文使用的 sensitivity。

这个结果只是当前位置附近的一阶估计。它忽略了二阶及更高阶项,因此不等于真正将参数置零后重新计算得到的精确 loss 变化。

因此,在训练步骤 tt,可以用 St(w)=∣wt∂Lt∂wt∣S_t(w)=\left|w_t\frac{\partial\mathcal{L}_t}{\partial w_t}\right| 表示当前 sensitivity。这个值越大,说明把 ww 置零预计会给 task loss 带来越大的变化。

但单个 mini-batch 得到的 sensitivity 很容易受到采样噪声影响。AdaLoRA 使用 exponential moving average(EMA)对它进行平滑:S‾t(w)=β1S‾t−1(w)+(1−β1)St(w)\overline{S}_t(w)=\beta_1\overline{S}_{t-1}(w)+(1-\beta_1)S_t(w)。

它还记录当前 sensitivity 偏离历史趋势的程度:Ut(w)=β2Ut−1(w)+(1−β2)∣St(w)−S‾t(w)∣U_t(w)=\beta_2U_{t-1}(w)+(1-\beta_2)\left|S_t(w)-\overline{S}_t(w)\right|。Ut(w)U_t(w) 越大,表示这个参数的重要性仍在明显变化,估计具有更高的 uncertainty。

论文实验默认使用 β1=β2=0.85\beta_1=\beta_2=0.85。其中 β1\beta_1 控制 sensitivity 的平滑程度,β2\beta_2 控制 uncertainty 的平滑程度;数值越接近 11,历史估计所占的比重越大。

最终的 parameter-level importance score 是 It(w)=S‾t(w)Ut(w)I_t(w)=\overline{S}_t(w)U_t(w)。也就是说,一个参数既要持续表现出较高的 sensitivity,又要考虑它在近期训练中的变化,才会得到更高的 importance。

从 parameter importance 到 rank importance#

一个 rank-1 component 不只包含 λi\lambda_i,还包含 pi‾\underline{p_i} 和 qi‾\underline{q_i}。因此,AdaLoRA 不应该只看 ∣λi∣|\lambda_i|,而是同时聚合整个 singular triplet 中所有参数的 importance。

对于第 kk 个权重更新中的第 ii 个 triplet,论文把 λk,i\lambda_{k,i} 的 importance、Pk‾‾\underline{\underline{P_k}} 第 ii 列各元素的平均 importance,以及 Qk‾‾\underline{\underline{Q_k}} 第 ii 行各元素的平均 importance 相加,得到 triplet-level importance score。

使用平均值而不是直接求和,是为了避免较大的 vector 仅仅因为包含更多参数就自然获得更高分数。得到所有 triplet 的分数后,AdaLoRA 会跨 module、跨 layer 进行全局排序,把较低分数对应的 λk,i\lambda_{k,i} 置零。

这样,重要的 matrix 最后可以保留更多 singular triplet,也就是获得更高的 rank;不重要的 matrix 则逐渐失去 rank。rank allocation 不再由人工为每一层预先指定,而是在训练过程中由 importance estimation 决定。

singular triplet 的 importance 怎样聚合?

论文用 s(⋅)s(\cdot) 表示单个参数的 importance function。采用前文的 sensitivity 与 uncertainty 时,s(t)(w)=S‾t(w)Ut(w)s^{(t)}(w)=\overline{S}_t(w)U_t(w)。

对第 kk 个 weight update 的第 ii 个 singular triplet,原文的聚合公式为 Sk,i=s(λk,i)+1d1∑j=1d1s(Pk,ji)+1d2∑j=1d2s(Qk,ij)S_{k,i}=s(\lambda_{k,i})+\frac{1}{d_1}\sum_{j=1}^{d_1}s(P_{k,ji})+\frac{1}{d_2}\sum_{j=1}^{d_2}s(Q_{k,ij})。

第一项来自 singular value λk,i\lambda_{k,i},第二项是 Pk‾‾\underline{\underline{P_k}} 第 ii 列的平均 importance,第三项是 Qk‾‾\underline{\underline{Q_k}} 第 ii 行的平均 importance。两个 vector 都取平均值,因此 Sk,iS_{k,i} 不会仅仅因为 vector 较长而变大。

预算怎样逐渐收缩#

AdaLoRA 不会在训练开始时立即把 rank 降到目标值。它先使用一个略高于最终目标的初始预算,让不同方向都有机会参与训练;经过 warm-up 后,再按照 schedule 逐渐减少可保留的 λi\lambda_i 数量,直到达到目标预算;最后固定得到的 rank distribution,继续完成训练。

这个过程让模型先探索哪些方向有用,再逐渐集中到重要方向上。与一开始就固定低 rank 相比,它减少了过早删除潜在重要方向的风险。

global budget scheduler 的公式

设总训练步数为 TT,initial warm-up 和 final fine-tuning 分别持续 tit_i 和 tft_f 步;初始与目标 budget 分别为 b(0)b^{(0)} 和 b(T)b^{(T)}。作者的官方实现使用下面的 cubic schedule: b(t)={b(0),0≤t<ti,b(T)+(b(0)−b(T))(1−t−tiT−ti−tf)3,ti≤t<T−tf,b(T),T−tf≤t≤T.b^{(t)}=\begin{cases}b^{(0)},&0\leq t<t_i,\\b^{(T)}+\left(b^{(0)}-b^{(T)}\right)\left(1-\frac{t-t_i}{T-t_i-t_f}\right)^3,&t_i\leq t<T-t_f,\\b^{(T)},&T-t_f\leq t\leq T.\end{cases}

第一阶段不裁减 budget;第二阶段通过三次函数逐渐从 b(0)b^{(0)} 降到 b(T)b^{(T)};最后 tft_f 步固定目标 budget 和已经得到的 rank distribution。

AdaLoRA 论文附录的印刷公式在第二段分子中写成了 t−ti−tft-t_i-t_f,但这样无法在两个阶段的边界处连续接上。作者官方代码实际使用 t−tit-t_i,这里采用与代码和正文描述一致的形式。

实验如何验证这个故事#

不同位置确实需要不同的 rank#

论文首先用一个控制实验检验“平均分配 rank 是否合理”。作者在 DeBERTaV3-base 上训练 MNLI-m,在总可训练参数固定为约 0.280.28M 的条件下,只改变 LoRA 被分配到哪些 weight matrix 或哪些 layer。

当预算只分配给一种 matrix 时,结果如下:

获得 LoRA 的 matrixWq‾‾\underline{\underline{W_q}}Wk‾‾\underline{\underline{W_k}}Wv‾‾\underline{\underline{W_v}}Wo‾‾\underline{\underline{W_o}}Wf1‾‾\underline{\underline{W_{f1}}}Wf2‾‾\underline{\underline{W_{f2}}}
MNLI-m accuracy88.5888.9889.3689.2889.9189.99

在这个实验中,把预算给 FFN 的 Wf1‾‾\underline{\underline{W_{f1}}} 和 Wf2‾‾\underline{\underline{W_{f2}}},效果高于只给 attention projection。把 LoRA 同时用于一组连续 layer 中的所有 matrix 时,位置差异也很明显:

获得 LoRA 的 layer1–34–67–910–12
MNLI-m accuracy77.8785.8288.1588.60

后几层明显比前几层更需要训练能力。这两个结果并不是说 FFN 或高层在所有任务中都一定最重要,而是说明统一 rank 隐含的“各处同等重要”假设并不可靠,因此应该让 allocation 随任务和训练过程决定。

主实验比较了什么#

论文分别用 DeBERTaV3-base 测试 GLUE 和 SQuAD,用 BART-large 测试 XSum 与 CNN/DailyMail。比较对象包括 full fine-tuning、BitFit、Adapter 和 LoRA。为了避免只给 attention matrix 的实现选择影响结论,实验中的 LoRA 也被扩展到与 AdaLoRA 相同的一组目标 matrix。

GLUE 实验把最终预算设为约 0.30.3M、0.60.6M 和 1.21.2M 个可训练参数;对应的 AdaLoRA 总 rank budget 分别为 144144、288288 和 576576,初始预算是最终预算的 1.51.5 倍。也就是说,它先用较宽的搜索空间探索,再逐步收缩到与 baseline 接近的最终参数量。

下面选取三个不同任务中的结果。每一行只能在本行内比较,因为 accuracy、F1 和 ROUGE-2 是不同指标:

任务与预算指标LoRAAdaLoRA
GLUE,约 0.30.3M 参数八个任务平均分88.1588.86
SQuAD v2.0,0.08%0.08\% 参数F187.588.7
XSum,1.10%1.10\% 参数ROUGE-220.2021.13

这些结果支持的是一个相对具体的结论:在相近的最终参数预算下,动态决定各处保留多少 rank,通常比统一 rank 更有效。它们并不能单独证明所有 weight update 都天然具有某个唯一的低秩结构,也不能说明 AdaLoRA 在任意数据集上都会优于 LoRA。

消融实验验证了哪些设计#

论文还分别移除了或替换了 AdaLoRA 的关键部分:

  • 直接对 LoRA 的 rank-1 doublet 做 structured pruning,整体上不如 SVD-like parameterization。例如在 0.08%0.08\% 参数预算的 CoLA 实验中,前者得分为 66.7166.71,AdaLoRA 为 70.2170.21;
  • 只看 sensitivity,或只按 ∣λi∣|\lambda_i| 排序,都不如完整的 sensitivity 与 uncertainty 组合稳定,说明一次 mini-batch 上的梯度并不足以可靠决定一个方向是否应该被删除;
  • 只使用 SVD-like parameterization、但不做 adaptive allocation,虽然能改善 LoRA,却仍然达不到完整 AdaLoRA 的结果;
  • 去掉 orthogonal regularization 会使表现下降,说明“让每个 singular triplet 成为较独立的 rank 单位”确实是后续排序和删除成立的重要条件。

最终得到的 rank distribution 也与最开始的控制实验相呼应:更多预算通常流向 FFN 和较高层。不过,这个分布是训练得到的结果,不应该被反过来写成所有模型都必须遵守的手工规则。

参数更少不等于训练更便宜#

AdaLoRA 需要维护 importance 的 moving average、执行全局排序和 mask,还加入了 orthogonal regularization。因此,它的主要贡献是提高固定最终参数预算的使用效率,而不是让训练过程自动变得更快。

论文报告,在单张 V100 上的比较中,AdaLoRA 的显存占用与 LoRA 接近,但训练时间增加约 11%11\%–16%16\%。例如 MNLI 的 0.08%0.08\% 参数设置中,LoRA 每个 epoch 约需 105105 分钟,AdaLoRA 约需 116116 分钟。这个开销换来的是更灵活的 rank allocation,以及同预算下通常更好的任务表现。

从 LoRA 到 AdaLoRA#

LoRA 的问题是如何用 low-rank update 代替完整的 weight update;AdaLoRA 的问题则是,在 low-rank update 已经成立之后,有限的 rank 应该分配给哪些 matrix。

它的推导路径可以概括为:

  1. 把 ΔW‾‾\underline{\underline{\Delta W}} 写成 SVD-like parameterization;
  2. 将它拆成多个可以独立控制的 rank-1 component;
  3. 用 sensitivity 和 uncertainty 估计每个 triplet 的 importance;
  4. 在所有 layer 和 module 之间全局排序;
  5. 逐渐将低重要性方向对应的 λi\lambda_i 置零。

这里还留下了一个值得继续追问的问题:AdaLoRA 把一个 singular triplet,也就是一个 rank,当作统一的预算单位;但对于不同形状的 matrix,一个 rank 实际对应的参数量是 d1+d2+1d_1+d_2+1,成本并不相同。

因此,“应该给哪个 matrix 更多 rank”之后,还有一个更精确的问题:“在真实参数成本固定时,不同 layer 的 capacity 应该如何分配?”这也是我继续阅读 Layer-Wise Capacity Allocation for Low-Rank Vision-Language-Action Fine-Tuning Under Demonstration Budget Constraints 的原因。

Layer-Wise Capacity Allocation for Low-Rank Vision-Language-Action Fine-Tuning Under Demonstration Budget Constraints

Aditi Mehra, Kevin Daniel Park, Jonathan Miles Carter, Laura Denise Franklin

Preprint 2026

DOI
Aditi Mehra, Kevin Daniel Park, Jonathan Miles Carter, Laura Denise Franklin. "Layer-Wise Capacity Allocation for Low-Rank Vision-Language-Action Fine-Tuning Under Demonstration Budget Constraints." Preprint, 2026. https://doi.org/10.13140/RG.2.2.12261.15846
LoRA的秩与容量 AdaLoRA: Adaptive Budget Allocation
https://heng-blog.pages.dev/blog/adalora
Author 杨苏恒
Published at July 25, 2026